Skip to content

Commit 14b5c64

Browse files
Remove outdated Python pre-3.9 code
These are manual fixes of src/c/ wchar_helper_3.h → wchar_helper.h
1 parent 371f16b commit 14b5c64

3 files changed

Lines changed: 68 additions & 324 deletions

File tree

‎src/c/_cffi_backend.c‎

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -398,11 +398,7 @@ typedef struct {
398398
#include "minibuffer.h"
399399
#include "file_emulator.h"
400400

401-
#ifdef PyUnicode_KIND /* Python >= 3.3 */
402-
# include "wchar_helper_3.h"
403-
#else
404-
# include "wchar_helper.h"
405-
#endif
401+
#include "wchar_helper.h"
406402

407403
#include "../cffi/_cffi_errors.h"
408404

@@ -3613,9 +3609,7 @@ static PyTypeObject CDataGCP_Type = {
36133609
0, /* inherited */ /* tp_setattro */
36143610
0, /* tp_as_buffer */
36153611
Py_TPFLAGS_DEFAULT /* tp_flags */
3616-
#ifdef Py_TPFLAGS_HAVE_FINALIZE
36173612
| Py_TPFLAGS_HAVE_FINALIZE
3618-
#endif
36193613
| Py_TPFLAGS_HAVE_GC,
36203614
"This is an internal subtype of _CDataBase for performance only on "
36213615
"CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
@@ -3629,7 +3623,6 @@ static PyTypeObject CDataGCP_Type = {
36293623
0, /* tp_members */
36303624
0, /* tp_getset */
36313625
&CData_Type, /* tp_base */
3632-
#ifdef Py_TPFLAGS_HAVE_FINALIZE /* CPython >= 3.4 */
36333626
0, /* tp_dict */
36343627
0, /* tp_descr_get */
36353628
0, /* tp_descr_set */
@@ -3647,7 +3640,6 @@ static PyTypeObject CDataGCP_Type = {
36473640
0, /* tp_del */
36483641
0, /* version_tag */
36493642
(destructor)cdatagcp_finalize, /* tp_finalize */
3650-
#endif
36513643
};
36523644

36533645
/************************************************************/

‎src/c/wchar_helper.h‎

Lines changed: 67 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -1,212 +1,125 @@
11
/*
2-
* wchar_t helpers
2+
* CPython 3.3 added support for sys.maxunicode == 0x10FFFF on all
3+
* platforms, even ones with wchar_t limited to 2 bytes. As such,
4+
* this code here works from the outside like wchar_helper.h in the
5+
* case Py_UNICODE_SIZE == 4, but the implementation is very different.
36
*/
47

58
typedef uint16_t cffi_char16_t;
69
typedef uint32_t cffi_char32_t;
710

811

9-
#if Py_UNICODE_SIZE == 2
10-
11-
/* Before Python 2.7, PyUnicode_FromWideChar is not able to convert
12-
wchar_t values greater than 65535 into two-unicode-characters surrogates.
13-
But even the Python 2.7 version doesn't detect wchar_t values that are
14-
out of range(1114112), and just returns nonsense.
15-
16-
From cffi 1.11 we can't use it anyway, because we need a version
17-
with char32_t input types.
18-
*/
19-
static PyObject *
20-
_my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size)
21-
{
22-
PyObject *unicode;
23-
register Py_ssize_t i;
24-
Py_ssize_t alloc;
25-
const cffi_char32_t *orig_w;
26-
27-
alloc = size;
28-
orig_w = w;
29-
for (i = size; i > 0; i--) {
30-
if (*w > 0xFFFF)
31-
alloc++;
32-
w++;
33-
}
34-
w = orig_w;
35-
unicode = PyUnicode_FromUnicode(NULL, alloc);
36-
if (!unicode)
37-
return NULL;
38-
39-
/* Copy the wchar_t data into the new object */
40-
{
41-
register Py_UNICODE *u;
42-
u = PyUnicode_AS_UNICODE(unicode);
43-
for (i = size; i > 0; i--) {
44-
if (*w > 0xFFFF) {
45-
cffi_char32_t ordinal;
46-
if (*w > 0x10FFFF) {
47-
PyErr_Format(PyExc_ValueError,
48-
"char32_t out of range for "
49-
"conversion to unicode: 0x%x", (int)*w);
50-
Py_DECREF(unicode);
51-
return NULL;
52-
}
53-
ordinal = *w++;
54-
ordinal -= 0x10000;
55-
*u++ = 0xD800 | (ordinal >> 10);
56-
*u++ = 0xDC00 | (ordinal & 0x3FF);
57-
}
58-
else
59-
*u++ = *w++;
60-
}
61-
}
62-
return unicode;
63-
}
64-
65-
static PyObject *
66-
_my_PyUnicode_FromChar16(const cffi_char16_t *w, Py_ssize_t size)
67-
{
68-
return PyUnicode_FromUnicode((const Py_UNICODE *)w, size);
69-
}
70-
71-
#else /* Py_UNICODE_SIZE == 4 */
72-
7312
static PyObject *
7413
_my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size)
7514
{
76-
return PyUnicode_FromUnicode((const Py_UNICODE *)w, size);
15+
return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, w, size);
7716
}
7817

7918
static PyObject *
8019
_my_PyUnicode_FromChar16(const cffi_char16_t *w, Py_ssize_t size)
8120
{
82-
/* 'size' is the length of the 'w' array */
83-
PyObject *result = PyUnicode_FromUnicode(NULL, size);
84-
85-
if (result != NULL) {
86-
Py_UNICODE *u_base = PyUnicode_AS_UNICODE(result);
87-
Py_UNICODE *u = u_base;
88-
89-
if (size == 1) { /* performance only */
90-
*u = (cffi_char32_t)*w;
91-
}
92-
else {
93-
while (size > 0) {
94-
cffi_char32_t ch = *w++;
95-
size--;
96-
if (0xD800 <= ch && ch <= 0xDBFF && size > 0) {
97-
cffi_char32_t ch2 = *w;
98-
if (0xDC00 <= ch2 && ch2 <= 0xDFFF) {
99-
ch = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000;
100-
w++;
101-
size--;
102-
}
21+
/* are there any surrogate pairs, and if so, how many? */
22+
Py_ssize_t i, count_surrogates = 0;
23+
for (i = 0; i < size - 1; i++) {
24+
if (0xD800 <= w[i] && w[i] <= 0xDBFF &&
25+
0xDC00 <= w[i+1] && w[i+1] <= 0xDFFF)
26+
count_surrogates++;
27+
}
28+
if (count_surrogates == 0) {
29+
/* no, fast path */
30+
return PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, w, size);
31+
}
32+
else
33+
{
34+
PyObject *result = PyUnicode_New(size - count_surrogates, 0x10FFFF);
35+
Py_UCS4 *data;
36+
assert(PyUnicode_KIND(result) == PyUnicode_4BYTE_KIND);
37+
data = PyUnicode_4BYTE_DATA(result);
38+
39+
for (i = 0; i < size; i++)
40+
{
41+
cffi_char32_t ch = w[i];
42+
if (0xD800 <= ch && ch <= 0xDBFF && i < size - 1) {
43+
cffi_char32_t ch2 = w[i + 1];
44+
if (0xDC00 <= ch2 && ch2 <= 0xDFFF) {
45+
ch = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000;
46+
i++;
10347
}
104-
*u++ = ch;
105-
}
106-
if (PyUnicode_Resize(&result, u - u_base) < 0) {
107-
Py_DECREF(result);
108-
return NULL;
10948
}
49+
*data++ = ch;
11050
}
51+
return result;
11152
}
112-
return result;
11353
}
11454

115-
#endif
116-
117-
118-
#define IS_SURROGATE(u) (0xD800 <= (u)[0] && (u)[0] <= 0xDBFF && \
119-
0xDC00 <= (u)[1] && (u)[1] <= 0xDFFF)
120-
#define AS_SURROGATE(u) (0x10000 + (((u)[0] - 0xD800) << 10) + \
121-
((u)[1] - 0xDC00))
122-
12355
static int
12456
_my_PyUnicode_AsSingleChar16(PyObject *unicode, cffi_char16_t *result,
12557
char *err_got)
12658
{
127-
Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode);
128-
if (PyUnicode_GET_SIZE(unicode) != 1) {
59+
cffi_char32_t ch;
60+
if (PyUnicode_GET_LENGTH(unicode) != 1) {
12961
sprintf(err_got, "unicode string of length %zd",
130-
PyUnicode_GET_SIZE(unicode));
62+
PyUnicode_GET_LENGTH(unicode));
13163
return -1;
13264
}
133-
#if Py_UNICODE_SIZE == 4
134-
if (((unsigned int)u[0]) > 0xFFFF)
65+
ch = PyUnicode_READ_CHAR(unicode, 0);
66+
67+
if (ch > 0xFFFF)
13568
{
13669
sprintf(err_got, "larger-than-0xFFFF character");
13770
return -1;
13871
}
139-
#endif
140-
*result = (cffi_char16_t)u[0];
72+
*result = (cffi_char16_t)ch;
14173
return 0;
14274
}
14375

14476
static int
14577
_my_PyUnicode_AsSingleChar32(PyObject *unicode, cffi_char32_t *result,
14678
char *err_got)
14779
{
148-
Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode);
149-
if (PyUnicode_GET_SIZE(unicode) == 1) {
150-
*result = (cffi_char32_t)u[0];
151-
return 0;
152-
}
153-
#if Py_UNICODE_SIZE == 2
154-
if (PyUnicode_GET_SIZE(unicode) == 2 && IS_SURROGATE(u)) {
155-
*result = AS_SURROGATE(u);
156-
return 0;
80+
if (PyUnicode_GET_LENGTH(unicode) != 1) {
81+
sprintf(err_got, "unicode string of length %zd",
82+
PyUnicode_GET_LENGTH(unicode));
83+
return -1;
15784
}
158-
#endif
159-
sprintf(err_got, "unicode string of length %zd",
160-
PyUnicode_GET_SIZE(unicode));
161-
return -1;
85+
*result = PyUnicode_READ_CHAR(unicode, 0);
86+
return 0;
16287
}
16388

16489
static Py_ssize_t _my_PyUnicode_SizeAsChar16(PyObject *unicode)
16590
{
166-
Py_ssize_t length = PyUnicode_GET_SIZE(unicode);
91+
Py_ssize_t length = PyUnicode_GET_LENGTH(unicode);
16792
Py_ssize_t result = length;
93+
unsigned int kind = PyUnicode_KIND(unicode);
16894

169-
#if Py_UNICODE_SIZE == 4
170-
Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode);
171-
Py_ssize_t i;
172-
173-
for (i=0; i<length; i++) {
174-
if (u[i] > 0xFFFF)
175-
result++;
95+
if (kind == PyUnicode_4BYTE_KIND)
96+
{
97+
Py_UCS4 *data = PyUnicode_4BYTE_DATA(unicode);
98+
Py_ssize_t i;
99+
for (i = 0; i < length; i++) {
100+
if (data[i] > 0xFFFF)
101+
result++;
102+
}
176103
}
177-
#endif
178104
return result;
179105
}
180106

181107
static Py_ssize_t _my_PyUnicode_SizeAsChar32(PyObject *unicode)
182108
{
183-
Py_ssize_t length = PyUnicode_GET_SIZE(unicode);
184-
Py_ssize_t result = length;
185-
186-
#if Py_UNICODE_SIZE == 2
187-
Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode);
188-
Py_ssize_t i;
189-
190-
for (i=0; i<length-1; i++) {
191-
if (IS_SURROGATE(u+i))
192-
result--;
193-
}
194-
#endif
195-
return result;
109+
return PyUnicode_GET_LENGTH(unicode);
196110
}
197111

198112
static int _my_PyUnicode_AsChar16(PyObject *unicode,
199113
cffi_char16_t *result,
200114
Py_ssize_t resultlen)
201115
{
202-
Py_ssize_t len = PyUnicode_GET_SIZE(unicode);
203-
Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode);
116+
Py_ssize_t len = PyUnicode_GET_LENGTH(unicode);
117+
unsigned int kind = PyUnicode_KIND(unicode);
118+
void *data = PyUnicode_DATA(unicode);
204119
Py_ssize_t i;
205-
for (i=0; i<len; i++) {
206-
#if Py_UNICODE_SIZE == 2
207-
cffi_char16_t ordinal = u[i];
208-
#else
209-
cffi_char32_t ordinal = u[i];
120+
121+
for (i = 0; i < len; i++) {
122+
cffi_char32_t ordinal = PyUnicode_READ(kind, data, i);
210123
if (ordinal > 0xFFFF) {
211124
if (ordinal > 0x10FFFF) {
212125
PyErr_Format(PyExc_ValueError,
@@ -217,10 +130,9 @@ static int _my_PyUnicode_AsChar16(PyObject *unicode,
217130
ordinal -= 0x10000;
218131
*result++ = 0xD800 | (ordinal >> 10);
219132
*result++ = 0xDC00 | (ordinal & 0x3FF);
220-
continue;
221133
}
222-
#endif
223-
*result++ = ordinal;
134+
else
135+
*result++ = ordinal;
224136
}
225137
return 0;
226138
}
@@ -229,18 +141,7 @@ static int _my_PyUnicode_AsChar32(PyObject *unicode,
229141
cffi_char32_t *result,
230142
Py_ssize_t resultlen)
231143
{
232-
Py_UNICODE *u = PyUnicode_AS_UNICODE(unicode);
233-
Py_ssize_t i;
234-
for (i=0; i<resultlen; i++) {
235-
cffi_char32_t ordinal = *u;
236-
#if Py_UNICODE_SIZE == 2
237-
if (IS_SURROGATE(u)) {
238-
ordinal = AS_SURROGATE(u);
239-
u++;
240-
}
241-
#endif
242-
result[i] = ordinal;
243-
u++;
244-
}
144+
if (PyUnicode_AsUCS4(unicode, (Py_UCS4 *)result, resultlen, 0) == NULL)
145+
return -1;
245146
return 0;
246147
}

0 commit comments

Comments
 (0)