Commit 3e3eacb5 authored by Marc-André Lemburg's avatar Marc-André Lemburg

Fixed "u#" parser marker to pass through Unicode objects as-is without

going through the buffer interface API.

Added tests for this to the _testcapi module and updated docs.
parent e0b1e6af
...@@ -669,6 +669,8 @@ address you pass. ...@@ -669,6 +669,8 @@ address you pass.
\item[\samp{u\#} (Unicode object) {[Py_UNICODE *, int]}] \item[\samp{u\#} (Unicode object) {[Py_UNICODE *, int]}]
This variant on \samp{u} stores into two C variables, the first one 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. 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 \item[\samp{es} (string, Unicode object or character buffer compatible
object) {[const char *encoding, char **buffer]}] object) {[const char *encoding, char **buffer]}]
......
...@@ -28,6 +28,9 @@ Build ...@@ -28,6 +28,9 @@ Build
C API 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_. - 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 - An old #define of ANY as void has been removed from pyport.h. This
......
...@@ -307,6 +307,53 @@ test_L_code(PyObject *self, PyObject *args) ...@@ -307,6 +307,53 @@ test_L_code(PyObject *self, PyObject *args)
#endif /* ifdef HAVE_LONG_LONG */ #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 * static PyObject *
raise_exception(PyObject *self, PyObject *args) raise_exception(PyObject *self, PyObject *args)
{ {
...@@ -342,6 +389,9 @@ static PyMethodDef TestMethods[] = { ...@@ -342,6 +389,9 @@ static PyMethodDef TestMethods[] = {
#ifdef HAVE_LONG_LONG #ifdef HAVE_LONG_LONG
{"test_longlong_api", test_longlong_api, METH_VARARGS}, {"test_longlong_api", test_longlong_api, METH_VARARGS},
{"test_L_code", test_L_code, METH_VARARGS}, {"test_L_code", test_L_code, METH_VARARGS},
#endif
#ifdef Py_USING_UNICODE
{"test_u_code", test_u_code, METH_VARARGS},
#endif #endif
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
......
...@@ -838,16 +838,20 @@ convertsimple(PyObject *arg, char **p_format, va_list *p_va, char *msgbuf, ...@@ -838,16 +838,20 @@ convertsimple(PyObject *arg, char **p_format, va_list *p_va, char *msgbuf,
if (*format == '#') { /* any buffer-like object */ if (*format == '#') { /* any buffer-like object */
void **p = (void **)va_arg(*p_va, char **); void **p = (void **)va_arg(*p_va, char **);
int *q = va_arg(*p_va, int *); int *q = va_arg(*p_va, int *);
if (PyUnicode_Check(arg)) {
*p = PyUnicode_AS_UNICODE(arg);
*q = PyUnicode_GET_SIZE(arg);
}
else {
char *buf; char *buf;
int count = convertbuffer(arg, p, &buf); int count = convertbuffer(arg, p, &buf);
if (count < 0) if (count < 0)
return converterr(buf, arg, msgbuf, bufsize); return converterr(buf, arg, msgbuf, bufsize);
*q = count/(sizeof(Py_UNICODE)); *q = count/(sizeof(Py_UNICODE));
}
format++; format++;
} else { } else {
Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **);
if (PyUnicode_Check(arg)) if (PyUnicode_Check(arg))
*p = PyUnicode_AS_UNICODE(arg); *p = PyUnicode_AS_UNICODE(arg);
else else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment