Kaydet (Commit) 1cb7aa3e authored tarafından Jeremy Hylton's avatar Jeremy Hylton

Internal refactoring of convertsimple() and friends.

Note that lots of code was re-indented.

Replace two-step of convertsimple() and convertsimple1() with
convertsimple() and helper converterr(), which is called to format
error messages when convertsimple() fails.  The old code did all the
real work in convertsimple1(), but deferred error message formatting
to conversimple().  The result was paying the price of a second
function call on every call just to format error messages in the
failure cases.

Factor out of the buffer-handling code in convertsimple() and package
it as convertbuffer().

Add two macros to ease readability of Unicode coversions,
UNICODE_DEFAULT_ENCODING() and CONV_UNICODE, an error string.

The convertsimple() routine had awful indentation problems, primarily
because there were two tabs between the case line and the body of the
case statements.  This patch reformats the entire function to have a
single tab between case line and case body, which makes the code
easier to read (and consistent with ceval).  The introduction of
converterr() exacerbated the problem and prompted this fix.

Also, eliminate non-standard whitespace after opening paren and before
closing paren in a few if statements.

(This checkin is part of SF patch 426072.)
üst 9cea41c1
......@@ -25,7 +25,7 @@ static char *convertitem(PyObject *, char **, va_list *, int *, char *);
static char *converttuple(PyObject *, char **, va_list *,
int *, char *, int);
static char *convertsimple(PyObject *, char **, va_list *, char *);
static char *convertsimple1(PyObject *, char **, va_list *);
static int convertbuffer(PyObject *, void **p, char **);
static int vgetargskeywords(PyObject *, PyObject *,
char *, char **, va_list *);
......@@ -352,374 +352,361 @@ convertitem(PyObject *arg, char **p_format, va_list *p_va, int *levels,
}
/* Convert a non-tuple argument. Adds to convertsimple1 functionality
by formatting messages as "must be <desired type>, not <actual type>". */
/* Internal API needed by convertsimple() and a helper macro. */
extern
PyObject *_PyUnicode_AsDefaultEncodedString(PyObject *unicode,
const char *errors);
#define UNICODE_DEFAULT_ENCODING(arg) \
_PyUnicode_AsDefaultEncodedString(arg, NULL)
/* Format an error message generated by convertsimple(). */
static char *
convertsimple(PyObject *arg, char **p_format, va_list *p_va, char *msgbuf)
converterr(char *expected, PyObject *arg, char *msgbuf)
{
char *msg = convertsimple1(arg, p_format, p_va);
if (msg != NULL) {
sprintf(msgbuf, "must be %.50s, not %.50s", msg,
arg == Py_None ? "None" : arg->ob_type->tp_name);
msg = msgbuf;
}
return msg;
assert (expected != NULL);
sprintf(msgbuf, "must be %.50s, not %.50s", expected,
arg == Py_None ? "None" : arg->ob_type->tp_name);
return msgbuf;
}
/* Internal API needed by convertsimple1(): */
extern
PyObject *_PyUnicode_AsDefaultEncodedString(PyObject *unicode,
const char *errors);
#define CONV_UNICODE "(unicode conversion error)"
/* Convert a non-tuple argument. Return NULL if conversion went OK,
or a string representing the expected type if the conversion failed.
or a string with a message describing the failure. The message is
formatted as "must be <desired type>, not <actual type>".
When failing, an exception may or may not have been raised.
Don't call if a tuple is expected. */
Don't call if a tuple is expected.
*/
static char *
convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
convertsimple(PyObject *arg, char **p_format, va_list *p_va, char *msgbuf)
{
char *format = *p_format;
char c = *format++;
switch (c) {
case 'b': /* unsigned byte -- very short int */
{
char *p = va_arg(*p_va, char *);
long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred())
return "integer<b>";
else if (ival < 0) {
PyErr_SetString(PyExc_OverflowError,
"unsigned byte integer is less than minimum");
return "integer<b>";
}
else if (ival > UCHAR_MAX) {
PyErr_SetString(PyExc_OverflowError,
"unsigned byte integer is greater than maximum");
return "integer<b>";
}
else
*p = (unsigned char) ival;
break;
case 'b': { /* unsigned byte -- very short int */
char *p = va_arg(*p_va, char *);
long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred())
return converterr("integer<b>", arg, msgbuf);
else if (ival < 0) {
PyErr_SetString(PyExc_OverflowError,
"unsigned byte integer is less than minimum");
return converterr("integer<b>", arg, msgbuf);
}
else if (ival > UCHAR_MAX) {
PyErr_SetString(PyExc_OverflowError,
"unsigned byte integer is greater than maximum");
return converterr("integer<b>", arg, msgbuf);
}
else
*p = (unsigned char) ival;
break;
}
case 'B': /* byte sized bitfield - both signed and unsigned values allowed */
{
char *p = va_arg(*p_va, char *);
long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred())
return "integer<b>";
else if (ival < SCHAR_MIN) {
PyErr_SetString(PyExc_OverflowError,
"byte-sized integer bitfield is less than minimum");
return "integer<B>";
}
else if (ival > (int)UCHAR_MAX) {
PyErr_SetString(PyExc_OverflowError,
"byte-sized integer bitfield is greater than maximum");
return "integer<B>";
}
else
*p = (unsigned char) ival;
break;
case 'B': {/* byte sized bitfield - both signed and unsigned
values allowed */
char *p = va_arg(*p_va, char *);
long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred())
return converterr("integer<b>", arg, msgbuf);
else if (ival < SCHAR_MIN) {
PyErr_SetString(PyExc_OverflowError,
"byte-sized integer bitfield is less than minimum");
return converterr("integer<B>", arg, msgbuf);
}
else if (ival > (int)UCHAR_MAX) {
PyErr_SetString(PyExc_OverflowError,
"byte-sized integer bitfield is greater than maximum");
return converterr("integer<B>", arg, msgbuf);
}
else
*p = (unsigned char) ival;
break;
}
case 'h': /* signed short int */
{
short *p = va_arg(*p_va, short *);
long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred())
return "integer<h>";
else if (ival < SHRT_MIN) {
PyErr_SetString(PyExc_OverflowError,
"signed short integer is less than minimum");
return "integer<h>";
}
else if (ival > SHRT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"signed short integer is greater than maximum");
return "integer<h>";
}
else
*p = (short) ival;
break;
case 'h': {/* signed short int */
short *p = va_arg(*p_va, short *);
long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred())
return converterr("integer<h>", arg, msgbuf);
else if (ival < SHRT_MIN) {
PyErr_SetString(PyExc_OverflowError,
"signed short integer is less than minimum");
return converterr("integer<h>", arg, msgbuf);
}
else if (ival > SHRT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"signed short integer is greater than maximum");
return converterr("integer<h>", arg, msgbuf);
}
else
*p = (short) ival;
break;
}
case 'H': /* short int sized bitfield, both signed and unsigned allowed */
{
unsigned short *p = va_arg(*p_va, unsigned short *);
long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred())
return "integer<H>";
else if (ival < SHRT_MIN) {
PyErr_SetString(PyExc_OverflowError,
"short integer bitfield is less than minimum");
return "integer<H>";
}
else if (ival > USHRT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"short integer bitfield is greater than maximum");
return "integer<H>";
}
else
*p = (unsigned short) ival;
break;
case 'H': { /* short int sized bitfield, both signed and
unsigned allowed */
unsigned short *p = va_arg(*p_va, unsigned short *);
long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred())
return converterr("integer<H>", arg, msgbuf);
else if (ival < SHRT_MIN) {
PyErr_SetString(PyExc_OverflowError,
"short integer bitfield is less than minimum");
return converterr("integer<H>", arg, msgbuf);
}
else if (ival > USHRT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"short integer bitfield is greater than maximum");
return converterr("integer<H>", arg, msgbuf);
}
else
*p = (unsigned short) ival;
break;
}
case 'i': /* signed int */
{
int *p = va_arg(*p_va, int *);
long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred())
return "integer<i>";
else if (ival > INT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"signed integer is greater than maximum");
return "integer<i>";
}
else if (ival < INT_MIN) {
PyErr_SetString(PyExc_OverflowError,
"signed integer is less than minimum");
return "integer<i>";
}
else
*p = ival;
break;
case 'i': {/* signed int */
int *p = va_arg(*p_va, int *);
long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred())
return converterr("integer<i>", arg, msgbuf);
else if (ival > INT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"signed integer is greater than maximum");
return converterr("integer<i>", arg, msgbuf);
}
case 'l': /* long int */
{
long *p = va_arg(*p_va, long *);
long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred())
return "integer<l>";
else
*p = ival;
break;
else if (ival < INT_MIN) {
PyErr_SetString(PyExc_OverflowError,
"signed integer is less than minimum");
return converterr("integer<i>", arg, msgbuf);
}
else
*p = ival;
break;
}
case 'l': {/* long int */
long *p = va_arg(*p_va, long *);
long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred())
return converterr("integer<l>", arg, msgbuf);
else
*p = ival;
break;
}
#ifdef HAVE_LONG_LONG
case 'L': /* LONG_LONG */
{
LONG_LONG *p = va_arg( *p_va, LONG_LONG * );
LONG_LONG ival = PyLong_AsLongLong( arg );
if( ival == (LONG_LONG)-1 && PyErr_Occurred() ) {
return "long<L>";
} else {
*p = ival;
}
break;
case 'L': {/* LONG_LONG */
LONG_LONG *p = va_arg( *p_va, LONG_LONG * );
LONG_LONG ival = PyLong_AsLongLong( arg );
if( ival == (LONG_LONG)-1 && PyErr_Occurred() ) {
return converterr("long<L>", arg, msgbuf);
} else {
*p = ival;
}
break;
}
#endif
case 'f': /* float */
{
float *p = va_arg(*p_va, float *);
double dval = PyFloat_AsDouble(arg);
if (PyErr_Occurred())
return "float<f>";
else
*p = (float) dval;
break;
}
case 'f': {/* float */
float *p = va_arg(*p_va, float *);
double dval = PyFloat_AsDouble(arg);
if (PyErr_Occurred())
return converterr("float<f>", arg, msgbuf);
else
*p = (float) dval;
break;
}
case 'd': /* double */
{
double *p = va_arg(*p_va, double *);
double dval = PyFloat_AsDouble(arg);
if (PyErr_Occurred())
return "float<d>";
else
*p = dval;
break;
}
case 'd': {/* double */
double *p = va_arg(*p_va, double *);
double dval = PyFloat_AsDouble(arg);
if (PyErr_Occurred())
return converterr("float<d>", arg, msgbuf);
else
*p = dval;
break;
}
#ifndef WITHOUT_COMPLEX
case 'D': /* complex double */
{
Py_complex *p = va_arg(*p_va, Py_complex *);
Py_complex cval;
cval = PyComplex_AsCComplex(arg);
if (PyErr_Occurred())
return "complex<D>";
else
*p = cval;
break;
}
case 'D': {/* complex double */
Py_complex *p = va_arg(*p_va, Py_complex *);
Py_complex cval;
cval = PyComplex_AsCComplex(arg);
if (PyErr_Occurred())
return converterr("complex<D>", arg, msgbuf);
else
*p = cval;
break;
}
#endif /* WITHOUT_COMPLEX */
case 'c': /* char */
{
char *p = va_arg(*p_va, char *);
if (PyString_Check(arg) && PyString_Size(arg) == 1)
*p = PyString_AsString(arg)[0];
else
return "char";
break;
}
case 'c': {/* char */
char *p = va_arg(*p_va, char *);
if (PyString_Check(arg) && PyString_Size(arg) == 1)
*p = PyString_AsString(arg)[0];
else
return converterr("char", arg, msgbuf);
break;
}
case 's': /* string */
{
if (*format == '#') {
void **p = (void **)va_arg(*p_va, char **);
int *q = va_arg(*p_va, int *);
if (PyString_Check(arg)) {
*p = PyString_AS_STRING(arg);
*q = PyString_GET_SIZE(arg);
}
else if (PyUnicode_Check(arg)) {
arg = _PyUnicode_AsDefaultEncodedString(
arg, NULL);
if (arg == NULL)
return "(unicode conversion error)";
*p = PyString_AS_STRING(arg);
*q = PyString_GET_SIZE(arg);
}
else { /* any buffer-like object */
PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
int count;
if ( pb == NULL ||
pb->bf_getreadbuffer == NULL ||
pb->bf_getsegcount == NULL )
return "string or read-only buffer";
if ( (*pb->bf_getsegcount)(arg, NULL) != 1 )
return "string or single-segment read-only buffer";
if ( (count =
(*pb->bf_getreadbuffer)(arg, 0, p)) < 0 )
return "(unspecified)";
*q = count;
}
format++;
} else {
char **p = va_arg(*p_va, char **);
case 's': {/* string */
if (*format == '#') {
void **p = (void **)va_arg(*p_va, char **);
int *q = va_arg(*p_va, int *);
if (PyString_Check(arg))
*p = PyString_AS_STRING(arg);
else if (PyUnicode_Check(arg)) {
arg = _PyUnicode_AsDefaultEncodedString(
arg, NULL);
if (arg == NULL)
return "(unicode conversion error)";
*p = PyString_AS_STRING(arg);
}
else
return "string";
if ((int)strlen(*p) != PyString_Size(arg))
return "string without null bytes";
if (PyString_Check(arg)) {
*p = PyString_AS_STRING(arg);
*q = PyString_GET_SIZE(arg);
}
break;
else if (PyUnicode_Check(arg)) {
arg = UNICODE_DEFAULT_ENCODING(arg);
if (arg == NULL)
return converterr(CONV_UNICODE,
arg, msgbuf);
*p = PyString_AS_STRING(arg);
*q = PyString_GET_SIZE(arg);
}
else { /* any buffer-like object */
char *buf;
int count = convertbuffer(arg, p, &buf);
if (count < 0)
return converterr(buf, arg, msgbuf);
*q = count;
}
format++;
} else {
char **p = va_arg(*p_va, char **);
if (PyString_Check(arg))
*p = PyString_AS_STRING(arg);
else if (PyUnicode_Check(arg)) {
arg = UNICODE_DEFAULT_ENCODING(arg);
if (arg == NULL)
return converterr(CONV_UNICODE,
arg, msgbuf);
*p = PyString_AS_STRING(arg);
}
else
return converterr("string", arg, msgbuf);
if ((int)strlen(*p) != PyString_Size(arg))
return converterr("string without null bytes",
arg, msgbuf);
}
break;
}
case 'z': /* string, may be NULL (None) */
{
if (*format == '#') { /* any buffer-like object */
void **p = (void **)va_arg(*p_va, char **);
int *q = va_arg(*p_va, int *);
case 'z': {/* string, may be NULL (None) */
if (*format == '#') { /* any buffer-like object */
void **p = (void **)va_arg(*p_va, char **);
int *q = va_arg(*p_va, int *);
if (arg == Py_None) {
*p = 0;
*q = 0;
}
else if (PyString_Check(arg)) {
*p = PyString_AS_STRING(arg);
*q = PyString_GET_SIZE(arg);
}
else if (PyUnicode_Check(arg)) {
arg = UNICODE_DEFAULT_ENCODING(arg);
if (arg == NULL)
return converterr(CONV_UNICODE,
arg, msgbuf);
*p = PyString_AS_STRING(arg);
*q = PyString_GET_SIZE(arg);
}
else { /* any buffer-like object */
char *buf;
int count = convertbuffer(arg, p, &buf);
if (arg == Py_None) {
*p = 0;
*q = 0;
}
else if (PyString_Check(arg)) {
*p = PyString_AS_STRING(arg);
*q = PyString_GET_SIZE(arg);
}
else if (PyUnicode_Check(arg)) {
arg = _PyUnicode_AsDefaultEncodedString(
arg, NULL);
if (arg == NULL)
return "(unicode conversion error)";
*p = PyString_AS_STRING(arg);
*q = PyString_GET_SIZE(arg);
}
else { /* any buffer-like object */
PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
int count;
if ( pb == NULL ||
pb->bf_getreadbuffer == NULL ||
pb->bf_getsegcount == NULL )
return "string or read-only buffer";
if ( (*pb->bf_getsegcount)(arg, NULL) != 1 )
return "string or single-segment read-only buffer";
if ( (count =
(*pb->bf_getreadbuffer)(arg, 0, p)) < 0 )
return "(unspecified)";
*q = count;
}
format++;
} else {
char **p = va_arg(*p_va, char **);
if (count < 0)
return converterr(buf, arg, msgbuf);
*q = count;
}
format++;
} else {
char **p = va_arg(*p_va, char **);
if (arg == Py_None)
*p = 0;
else if (PyString_Check(arg))
*p = PyString_AsString(arg);
else if (PyUnicode_Check(arg)) {
arg = UNICODE_DEFAULT_ENCODING(arg);
if (arg == NULL)
return converterr(CONV_UNICODE,
arg, msgbuf);
*p = PyString_AS_STRING(arg);
}
else
return converterr("string or None",
arg, msgbuf);
if (*format == '#') {
int *q = va_arg(*p_va, int *);
if (arg == Py_None)
*p = 0;
else if (PyString_Check(arg))
*p = PyString_AsString(arg);
else if (PyUnicode_Check(arg)) {
arg = _PyUnicode_AsDefaultEncodedString(
arg, NULL);
if (arg == NULL)
return "(unicode conversion error)";
*p = PyString_AS_STRING(arg);
}
*q = 0;
else
return "string or None";
if (*format == '#') {
int *q = va_arg(*p_va, int *);
if (arg == Py_None)
*q = 0;
else
*q = PyString_Size(arg);
format++;
}
else if (*p != NULL &&
(int)strlen(*p) != PyString_Size(arg))
return "string without null bytes or None";
*q = PyString_Size(arg);
format++;
}
break;
else if (*p != NULL &&
(int)strlen(*p) != PyString_Size(arg))
return converterr(
"string without null bytes or None",
arg, msgbuf);
}
break;
}
case 'e': /* encoded string */
{
char **buffer;
const char *encoding;
PyObject *u, *s;
int size, recode_strings;
/* Get 'e' parameter: the encoding name */
encoding = (const char *)va_arg(*p_va, const char *);
if (encoding == NULL)
encoding = PyUnicode_GetDefaultEncoding();
case 'e': {/* encoded string */
char **buffer;
const char *encoding;
PyObject *u, *s;
int size, recode_strings;
/* Get 'e' parameter: the encoding name */
encoding = (const char *)va_arg(*p_va, const char *);
if (encoding == NULL)
encoding = PyUnicode_GetDefaultEncoding();
/* Get output buffer parameter:
's' (recode all objects via Unicode) or
't' (only recode non-string objects)
*/
if (*format == 's')
recode_strings = 1;
else if (*format == 't')
recode_strings = 0;
else
return "(unknown parser marker combination)";
buffer = (char **)va_arg(*p_va, char **);
format++;
if (buffer == NULL)
return "(buffer is NULL)";
/* Get output buffer parameter:
's' (recode all objects via Unicode) or
't' (only recode non-string objects)
*/
if (*format == 's')
recode_strings = 1;
else if (*format == 't')
recode_strings = 0;
else
return converterr(
"(unknown parser marker combination)",
arg, msgbuf);
buffer = (char **)va_arg(*p_va, char **);
format++;
if (buffer == NULL)
return converterr("(buffer is NULL)",
arg, msgbuf);
/* Encode object */
if (!recode_strings && PyString_Check(arg)) {
s = arg;
Py_INCREF(s);
}
else {
/* Encode object */
if (!recode_strings && PyString_Check(arg)) {
s = arg;
Py_INCREF(s);
}
else {
/* Convert object to Unicode */
u = PyUnicode_FromObject(arg);
if (u == NULL)
return \
"string or unicode or text buffer";
return converterr(
"string or unicode or text buffer",
arg, msgbuf);
/* Encode object; use default error handling */
s = PyUnicode_AsEncodedString(u,
......@@ -727,234 +714,227 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
NULL);
Py_DECREF(u);
if (s == NULL)
return "(encoding failed)";
return converterr("(encoding failed)",
arg, msgbuf);
if (!PyString_Check(s)) {
Py_DECREF(s);
return \
"(encoder failed to return a string)";
}
return converterr(
"(encoder failed to return a string)",
arg, msgbuf);
}
size = PyString_GET_SIZE(s);
/* Write output; output is guaranteed to be
0-terminated */
if (*format == '#') {
/* Using buffer length parameter '#':
- if *buffer is NULL, a new buffer
of the needed size is allocated and
the data copied into it; *buffer is
updated to point to the new buffer;
the caller is responsible for
PyMem_Free()ing it after usage
- if *buffer is not NULL, the data
is copied to *buffer; *buffer_len
has to be set to the size of the
buffer on input; buffer overflow is
signalled with an error; buffer has
to provide enough room for the
encoded string plus the trailing
0-byte
- in both cases, *buffer_len is
updated to the size of the buffer
/excluding/ the trailing 0-byte
*/
int *buffer_len = va_arg(*p_va, int *);
}
size = PyString_GET_SIZE(s);
/* Write output; output is guaranteed to be 0-terminated */
if (*format == '#') {
/* Using buffer length parameter '#':
- if *buffer is NULL, a new buffer of the
needed size is allocated and the data
copied into it; *buffer is updated to point
to the new buffer; the caller is
responsible for PyMem_Free()ing it after
usage
- if *buffer is not NULL, the data is
copied to *buffer; *buffer_len has to be
set to the size of the buffer on input;
buffer overflow is signalled with an error;
buffer has to provide enough room for the
encoded string plus the trailing 0-byte
- in both cases, *buffer_len is updated to
the size of the buffer /excluding/ the
trailing 0-byte
*/
int *buffer_len = va_arg(*p_va, int *);
format++;
if (buffer_len == NULL)
return "(buffer_len is NULL)";
format++;
if (buffer_len == NULL)
return converterr(
"(buffer_len is NULL)",
arg, msgbuf);
if (*buffer == NULL) {
*buffer = PyMem_NEW(char, size + 1);
if (*buffer == NULL) {
*buffer = PyMem_NEW(char, size + 1);
if (*buffer == NULL) {
Py_DECREF(s);
return "(memory error)";
}
} else {
if (size + 1 > *buffer_len) {
Py_DECREF(s);
return "(buffer overflow)";
}
Py_DECREF(s);
return converterr(
"(memory error)",
arg, msgbuf);
}
memcpy(*buffer,
PyString_AS_STRING(s),
size + 1);
*buffer_len = size;
} else {
/* Using a 0-terminated buffer:
- the encoded string has to be
0-terminated for this variant to
work; if it is not, an error raised
- a new buffer of the needed size
is allocated and the data copied
into it; *buffer is updated to
point to the new buffer; the caller
is responsible for PyMem_Free()ing it
after usage
*/
if ((int)strlen(PyString_AS_STRING(s)) != size)
return "(encoded string without NULL bytes)";
*buffer = PyMem_NEW(char, size + 1);
if (*buffer == NULL) {
if (size + 1 > *buffer_len) {
Py_DECREF(s);
return "(memory error)";
return converterr(
"(buffer overflow)",
arg, msgbuf);
}
memcpy(*buffer,
PyString_AS_STRING(s),
size + 1);
}
Py_DECREF(s);
break;
}
memcpy(*buffer,
PyString_AS_STRING(s),
size + 1);
*buffer_len = size;
} else {
/* Using a 0-terminated buffer:
- the encoded string has to be 0-terminated
for this variant to work; if it is not, an
error raised
- a new buffer of the needed size is
allocated and the data copied into it;
*buffer is updated to point to the new
buffer; the caller is responsible for
PyMem_Free()ing it after usage
case 'u': /* raw unicode buffer (Py_UNICODE *) */
{
if (*format == '#') { /* any buffer-like object */
void **p = (void **)va_arg(*p_va, char **);
PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
int *q = va_arg(*p_va, int *);
int count;
if ( pb == NULL ||
pb->bf_getreadbuffer == NULL ||
pb->bf_getsegcount == NULL )
return "unicode or read-only buffer";
if ( (*pb->bf_getsegcount)(arg, NULL) != 1 )
return "unicode or single-segment read-only buffer";
if ( (count =
(*pb->bf_getreadbuffer)(arg, 0, p)) < 0 )
return "(unspecified)";
/* buffer interface returns bytes, we want
length in characters */
*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
return "unicode";
*/
if ((int)strlen(PyString_AS_STRING(s)) != size)
return converterr(
"(encoded string without NULL bytes)",
arg, msgbuf);
*buffer = PyMem_NEW(char, size + 1);
if (*buffer == NULL) {
Py_DECREF(s);
return converterr("(memory error)",
arg, msgbuf);
}
break;
memcpy(*buffer,
PyString_AS_STRING(s),
size + 1);
}
Py_DECREF(s);
break;
}
case 'S': /* string object */
{
PyObject **p = va_arg(*p_va, PyObject **);
if (PyString_Check(arg))
*p = arg;
case 'u': {/* raw unicode buffer (Py_UNICODE *) */
if (*format == '#') { /* any buffer-like object */
void **p = (void **)va_arg(*p_va, char **);
int *q = va_arg(*p_va, int *);
char *buf;
int count = convertbuffer(arg, p, &buf);
if (count < 0)
return converterr(buf, arg, msgbuf);
*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
return "string";
break;
return converterr("unicode", arg, msgbuf);
}
break;
}
case 'S': { /* string object */
PyObject **p = va_arg(*p_va, PyObject **);
if (PyString_Check(arg))
*p = arg;
else
return converterr("string", arg, msgbuf);
break;
}
case 'U': /* Unicode object */
{
PyObject **p = va_arg(*p_va, PyObject **);
if (PyUnicode_Check(arg))
case 'U': { /* Unicode object */
PyObject **p = va_arg(*p_va, PyObject **);
if (PyUnicode_Check(arg))
*p = arg;
else
return converterr("unicode", arg, msgbuf);
break;
}
case 'O': { /* object */
PyTypeObject *type;
PyObject **p;
if (*format == '!') {
type = va_arg(*p_va, PyTypeObject*);
p = va_arg(*p_va, PyObject **);
format++;
if (arg->ob_type == type)
*p = arg;
else
return "unicode";
break;
}
case 'O': /* object */
{
PyTypeObject *type;
PyObject **p;
if (*format == '!') {
type = va_arg(*p_va, PyTypeObject*);
p = va_arg(*p_va, PyObject **);
format++;
if (arg->ob_type == type)
*p = arg;
else
return type->tp_name;
return converterr(type->tp_name, arg, msgbuf);
}
else if (*format == '?') {
inquiry pred = va_arg(*p_va, inquiry);
p = va_arg(*p_va, PyObject **);
format++;
if ((*pred)(arg))
*p = arg;
else
return "(unspecified)";
}
else if (*format == '&') {
typedef int (*converter)(PyObject *, void *);
converter convert = va_arg(*p_va, converter);
void *addr = va_arg(*p_va, void *);
format++;
if (! (*convert)(arg, addr))
return "(unspecified)";
}
else {
p = va_arg(*p_va, PyObject **);
}
else if (*format == '?') {
inquiry pred = va_arg(*p_va, inquiry);
p = va_arg(*p_va, PyObject **);
format++;
if ((*pred)(arg))
*p = arg;
}
break;
else
return converterr("(unspecified)",
arg, msgbuf);
}
else if (*format == '&') {
typedef int (*converter)(PyObject *, void *);
converter convert = va_arg(*p_va, converter);
void *addr = va_arg(*p_va, void *);
format++;
if (! (*convert)(arg, addr))
return converterr("(unspecified)",
arg, msgbuf);
}
else {
p = va_arg(*p_va, PyObject **);
*p = arg;
}
break;
}
case 'w': /* memory buffer, read-write access */
{
void **p = va_arg(*p_va, void **);
PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
int count;
case 'w': { /* memory buffer, read-write access */
void **p = va_arg(*p_va, void **);
PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
int count;
if ( pb == NULL || pb->bf_getwritebuffer == NULL ||
pb->bf_getsegcount == NULL )
return "read-write buffer";
if ( (*pb->bf_getsegcount)(arg, NULL) != 1 )
return "single-segment read-write buffer";
if ( (count = pb->bf_getwritebuffer(arg, 0, p)) < 0 )
return "(unspecified)";
if (*format == '#') {
int *q = va_arg(*p_va, int *);
*q = count;
format++;
}
break;
if (pb == NULL ||
pb->bf_getwritebuffer == NULL ||
pb->bf_getsegcount == NULL)
return converterr("read-write buffer", arg, msgbuf);
if ((*pb->bf_getsegcount)(arg, NULL) != 1)
return converterr("single-segment read-write buffer",
arg, msgbuf);
if ((count = pb->bf_getwritebuffer(arg, 0, p)) < 0)
return converterr("(unspecified)", arg, msgbuf);
if (*format == '#') {
int *q = va_arg(*p_va, int *);
*q = count;
format++;
}
break;
}
case 't': /* 8-bit character buffer, read-only access */
{
const char **p = va_arg(*p_va, const char **);
PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
int count;
if ( *format++ != '#' )
return "invalid use of 't' format character";
if ( !PyType_HasFeature(
arg->ob_type,
Py_TPFLAGS_HAVE_GETCHARBUFFER) ||
pb == NULL ||
pb->bf_getcharbuffer == NULL ||
pb->bf_getsegcount == NULL )
return "string or read-only character buffer";
if ( (*pb->bf_getsegcount)(arg, NULL) != 1 )
return "string or single-segment read-only buffer";
if ( (count = pb->bf_getcharbuffer(arg, 0, p)) < 0 )
return "(unspecified)";
*va_arg(*p_va, int *) = count;
break;
}
case 't': { /* 8-bit character buffer, read-only access */
const char **p = va_arg(*p_va, const char **);
char *buf;
int count;
if (*format++ != '#')
return converterr(
"invalid use of 't' format character",
arg, msgbuf);
if (!PyType_HasFeature(arg->ob_type,
Py_TPFLAGS_HAVE_GETCHARBUFFER))
return converterr(
"string or read-only character buffer",
arg, msgbuf);
count = convertbuffer(arg, (void **)p, &buf);
if (count < 0)
return converterr(buf, arg, msgbuf);
*va_arg(*p_va, int *) = count;
break;
}
default:
return "impossible<bad format char>";
return converterr("impossible<bad format char>", arg, msgbuf);
}
......@@ -962,6 +942,25 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
return NULL;
}
int convertbuffer(PyObject *arg, void **p, char **errmsg)
{
PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
int count;
if (pb == NULL ||
pb->bf_getreadbuffer == NULL ||
pb->bf_getsegcount == NULL) {
*errmsg = "string or read-only buffer";
return -1;
}
if ((*pb->bf_getsegcount)(arg, NULL) != 1) {
*errmsg = "string or single-segment read-only buffer";
return -1;
}
if ((count = (*pb->bf_getreadbuffer)(arg, 0, p)) < 0) {
*errmsg = "(unspecified)";
}
return count;
}
/* Support for keyword arguments donated by
Geoff Philbrick <philbric@delphi.hks.com> */
......
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