mirror of https://github.com/python/cpython.git
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.
This commit is contained in:
parent
e0b1e6af58
commit
3e3eacb5fc
|
@ -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
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
#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[] = {
|
||||||
#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,
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue