diff options
-rw-r--r-- | Doc/ext/extending.tex | 2 | ||||
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Modules/_testcapimodule.c | 50 | ||||
-rw-r--r-- | Python/getargs.c | 8 |
4 files changed, 61 insertions, 2 deletions
diff --git a/Doc/ext/extending.tex b/Doc/ext/extending.tex index 0051a02..d77a714 100644 --- a/Doc/ext/extending.tex +++ b/Doc/ext/extending.tex @@ -669,6 +669,8 @@ address you pass. \item[\samp{u\#} (Unicode object) {[Py_UNICODE *, int]}] This variant on \samp{u} stores into two C variables, the first one a pointer to a Unicode data buffer, the second one its length. +Non-Unicode objects are handled by interpreting their read buffer +pointer as pointer to a Py_UNICODE array. \item[\samp{es} (string, Unicode object or character buffer compatible object) {[const char *encoding, char **buffer]}] @@ -28,6 +28,9 @@ Build C API +- The "u#" parser marker will now pass through Unicode object as-is + without going through the buffer API. + - The enumerators of cmp_op have been renamed to use the prefix PyCmp_. - An old #define of ANY as void has been removed from pyport.h. This diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 0f5fa7c..824ae87 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -307,6 +307,53 @@ test_L_code(PyObject *self, PyObject *args) #endif /* ifdef HAVE_LONG_LONG */ +#ifdef Py_USING_UNICODE + +/* Test the u and u# codes for PyArg_ParseTuple. May leak memory in case + of an error. +*/ +static PyObject * +test_u_code(PyObject *self, PyObject *args) +{ + PyObject *tuple, *obj; + Py_UNICODE *value; + int len; + + if (!PyArg_ParseTuple(args, ":test_u_code")) + return NULL; + + tuple = PyTuple_New(1); + if (tuple == NULL) + return NULL; + + obj = PyUnicode_Decode("test", strlen("test"), + "ascii", NULL); + if (obj == NULL) + return NULL; + + PyTuple_SET_ITEM(tuple, 0, obj); + + value = 0; + if (PyArg_ParseTuple(tuple, "u:test_u_code", &value) < 0) + return NULL; + if (value != PyUnicode_AS_UNICODE(obj)) + return raiseTestError("test_u_code", + "u code returned wrong value for u'test'"); + value = 0; + if (PyArg_ParseTuple(tuple, "u#:test_u_code", &value, &len) < 0) + return NULL; + if (value != PyUnicode_AS_UNICODE(obj) || + len != PyUnicode_GET_SIZE(obj)) + return raiseTestError("test_u_code", + "u# code returned wrong values for u'test'"); + + Py_DECREF(tuple); + Py_INCREF(Py_None); + return Py_None; +} + +#endif + static PyObject * raise_exception(PyObject *self, PyObject *args) { @@ -343,6 +390,9 @@ static PyMethodDef TestMethods[] = { {"test_longlong_api", test_longlong_api, METH_VARARGS}, {"test_L_code", test_L_code, METH_VARARGS}, #endif +#ifdef Py_USING_UNICODE + {"test_u_code", test_u_code, METH_VARARGS}, +#endif {NULL, NULL} /* sentinel */ }; diff --git a/Python/getargs.c b/Python/getargs.c index 9df2a2e..411c695 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -838,16 +838,20 @@ convertsimple(PyObject *arg, char **p_format, va_list *p_va, char *msgbuf, if (*format == '#') { /* any buffer-like object */ void **p = (void **)va_arg(*p_va, char **); int *q = va_arg(*p_va, int *); + if (PyUnicode_Check(arg)) { + *p = PyUnicode_AS_UNICODE(arg); + *q = PyUnicode_GET_SIZE(arg); + } + else { char *buf; int count = convertbuffer(arg, p, &buf); - if (count < 0) return converterr(buf, arg, msgbuf, bufsize); *q = count/(sizeof(Py_UNICODE)); + } format++; } else { Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - if (PyUnicode_Check(arg)) *p = PyUnicode_AS_UNICODE(arg); else |