Skip to content

Commit 349f76c

Browse files
bpo-36346: Prepare for removing the legacy Unicode C API (AC only). (GH-21223)
1 parent b333266 commit 349f76c

File tree

7 files changed

+523
-45
lines changed

7 files changed

+523
-45
lines changed

Include/cpython/unicodeobject.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
/* --- Internal Unicode Operations ---------------------------------------- */
1313

14+
#define USE_UNICODE_WCHAR_CACHE 1
15+
1416
/* Since splitting on whitespace is an important use case, and
1517
whitespace in most situations is solely ASCII whitespace, we
1618
optimize for the common case by using a quick look-up table
@@ -1169,4 +1171,7 @@ PyAPI_FUNC(PyObject*) _PyUnicode_FromId(_Py_Identifier*);
11691171
and where the hash values are equal (i.e. a very probable match) */
11701172
PyAPI_FUNC(int) _PyUnicode_EQ(PyObject *, PyObject *);
11711173

1174+
PyAPI_FUNC(int) _PyUnicode_WideCharString_Converter(PyObject *, void *);
1175+
PyAPI_FUNC(int) _PyUnicode_WideCharString_Opt_Converter(PyObject *, void *);
1176+
11721177
PyAPI_FUNC(Py_ssize_t) _PyUnicode_ScanIdentifier(PyObject *);

Lib/test/clinic.test

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,13 +1813,26 @@ test_Py_UNICODE_converter(PyObject *module, PyObject *const *args, Py_ssize_t na
18131813
const Py_UNICODE *e;
18141814
Py_ssize_clean_t e_length;
18151815

1816-
if (!_PyArg_ParseStack(args, nargs, "uuZu#Z#:test_Py_UNICODE_converter",
1817-
&a, &b, &c, &d, &d_length, &e, &e_length)) {
1816+
if (!_PyArg_ParseStack(args, nargs, "O&O&O&u#Z#:test_Py_UNICODE_converter",
1817+
_PyUnicode_WideCharString_Converter, &a, _PyUnicode_WideCharString_Converter, &b, _PyUnicode_WideCharString_Opt_Converter, &c, &d, &d_length, &e, &e_length)) {
18181818
goto exit;
18191819
}
18201820
return_value = test_Py_UNICODE_converter_impl(module, a, b, c, d, d_length, e, e_length);
18211821

18221822
exit:
1823+
/* Cleanup for a */
1824+
#if !USE_UNICODE_WCHAR_CACHE
1825+
PyMem_Free((void *)a);
1826+
#endif /* USE_UNICODE_WCHAR_CACHE */
1827+
/* Cleanup for b */
1828+
#if !USE_UNICODE_WCHAR_CACHE
1829+
PyMem_Free((void *)b);
1830+
#endif /* USE_UNICODE_WCHAR_CACHE */
1831+
/* Cleanup for c */
1832+
#if !USE_UNICODE_WCHAR_CACHE
1833+
PyMem_Free((void *)c);
1834+
#endif /* USE_UNICODE_WCHAR_CACHE */
1835+
18231836
return return_value;
18241837
}
18251838

@@ -1830,7 +1843,7 @@ test_Py_UNICODE_converter_impl(PyObject *module, const Py_UNICODE *a,
18301843
Py_ssize_clean_t d_length,
18311844
const Py_UNICODE *e,
18321845
Py_ssize_clean_t e_length)
1833-
/*[clinic end generated code: output=dd0a09a1b772e57b input=064a3b68ad7f04b0]*/
1846+
/*[clinic end generated code: output=ef45e982fedf0b3d input=064a3b68ad7f04b0]*/
18341847

18351848

18361849
/*[clinic input]

Modules/clinic/_winapi.c.h

Lines changed: 12 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/clinic/posixmodule.c.h

Lines changed: 56 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Objects/unicodeobject.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3273,6 +3273,80 @@ PyUnicode_AsWideCharString(PyObject *unicode,
32733273

32743274
#endif /* HAVE_WCHAR_H */
32753275

3276+
int
3277+
_PyUnicode_WideCharString_Converter(PyObject *obj, void *ptr)
3278+
{
3279+
wchar_t **p = (wchar_t **)ptr;
3280+
if (obj == NULL) {
3281+
#if !USE_UNICODE_WCHAR_CACHE
3282+
PyMem_Free(*p);
3283+
#endif /* USE_UNICODE_WCHAR_CACHE */
3284+
*p = NULL;
3285+
return 1;
3286+
}
3287+
if (PyUnicode_Check(obj)) {
3288+
#if USE_UNICODE_WCHAR_CACHE
3289+
_Py_COMP_DIAG_PUSH
3290+
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
3291+
*p = (wchar_t *)_PyUnicode_AsUnicode(obj);
3292+
if (*p == NULL) {
3293+
return 0;
3294+
}
3295+
return 1;
3296+
_Py_COMP_DIAG_POP
3297+
#else /* USE_UNICODE_WCHAR_CACHE */
3298+
*p = PyUnicode_AsWideCharString(obj, NULL);
3299+
if (*p == NULL) {
3300+
return 0;
3301+
}
3302+
return Py_CLEANUP_SUPPORTED;
3303+
#endif /* USE_UNICODE_WCHAR_CACHE */
3304+
}
3305+
PyErr_Format(PyExc_TypeError,
3306+
"argument must be str, not %.50s",
3307+
obj->ob_type->tp_name);
3308+
return 0;
3309+
}
3310+
3311+
int
3312+
_PyUnicode_WideCharString_Opt_Converter(PyObject *obj, void *ptr)
3313+
{
3314+
wchar_t **p = (wchar_t **)ptr;
3315+
if (obj == NULL) {
3316+
#if !USE_UNICODE_WCHAR_CACHE
3317+
PyMem_Free(*p);
3318+
#endif /* USE_UNICODE_WCHAR_CACHE */
3319+
*p = NULL;
3320+
return 1;
3321+
}
3322+
if (obj == Py_None) {
3323+
*p = NULL;
3324+
return 1;
3325+
}
3326+
if (PyUnicode_Check(obj)) {
3327+
#if USE_UNICODE_WCHAR_CACHE
3328+
_Py_COMP_DIAG_PUSH
3329+
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
3330+
*p = (wchar_t *)_PyUnicode_AsUnicode(obj);
3331+
if (*p == NULL) {
3332+
return 0;
3333+
}
3334+
return 1;
3335+
_Py_COMP_DIAG_POP
3336+
#else /* USE_UNICODE_WCHAR_CACHE */
3337+
*p = PyUnicode_AsWideCharString(obj, NULL);
3338+
if (*p == NULL) {
3339+
return 0;
3340+
}
3341+
return Py_CLEANUP_SUPPORTED;
3342+
#endif /* USE_UNICODE_WCHAR_CACHE */
3343+
}
3344+
PyErr_Format(PyExc_TypeError,
3345+
"argument must be str or None, not %.50s",
3346+
obj->ob_type->tp_name);
3347+
return 0;
3348+
}
3349+
32763350
PyObject *
32773351
PyUnicode_FromOrdinal(int ordinal)
32783352
{

0 commit comments

Comments
 (0)