diff options
Diffstat (limited to 'Python/getargs.c')
-rw-r--r-- | Python/getargs.c | 1029 |
1 files changed, 514 insertions, 515 deletions
diff --git a/Python/getargs.c b/Python/getargs.c index b25b20a..c112386 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -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> */ |