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.)
This commit is contained in:
Jeremy Hylton 2001-05-29 17:37:05 +00:00
parent 9cea41c195
commit 1cb7aa3e6e

View file

@ -25,7 +25,7 @@ static char *convertitem(PyObject *, char **, va_list *, int *, char *);
static char *converttuple(PyObject *, char **, va_list *, static char *converttuple(PyObject *, char **, va_list *,
int *, char *, int); int *, char *, int);
static char *convertsimple(PyObject *, char **, va_list *, char *); 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 *, static int vgetargskeywords(PyObject *, PyObject *,
char *, char **, va_list *); char *, char **, va_list *);
@ -352,162 +352,161 @@ 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>". */
static char * /* Internal API needed by convertsimple() and a helper macro. */
convertsimple(PyObject *arg, char **p_format, va_list *p_va, 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;
}
/* Internal API needed by convertsimple1(): */
extern extern
PyObject *_PyUnicode_AsDefaultEncodedString(PyObject *unicode, PyObject *_PyUnicode_AsDefaultEncodedString(PyObject *unicode,
const char *errors); const char *errors);
/* Convert a non-tuple argument. Return NULL if conversion went OK, #define UNICODE_DEFAULT_ENCODING(arg) \
or a string representing the expected type if the conversion failed. _PyUnicode_AsDefaultEncodedString(arg, NULL)
When failing, an exception may or may not have been raised.
Don't call if a tuple is expected. */ /* Format an error message generated by convertsimple(). */
static char * static char *
convertsimple1(PyObject *arg, char **p_format, va_list *p_va) converterr(char *expected, PyObject *arg, char *msgbuf)
{
assert (expected != NULL);
sprintf(msgbuf, "must be %.50s, not %.50s", expected,
arg == Py_None ? "None" : arg->ob_type->tp_name);
return msgbuf;
}
#define CONV_UNICODE "(unicode conversion error)"
/* Convert a non-tuple argument. Return NULL if conversion went OK,
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.
*/
static char *
convertsimple(PyObject *arg, char **p_format, va_list *p_va, char *msgbuf)
{ {
char *format = *p_format; char *format = *p_format;
char c = *format++; char c = *format++;
switch (c) { switch (c) {
case 'b': /* unsigned byte -- very short int */ case 'b': { /* unsigned byte -- very short int */
{
char *p = va_arg(*p_va, char *); char *p = va_arg(*p_va, char *);
long ival = PyInt_AsLong(arg); long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred()) if (ival == -1 && PyErr_Occurred())
return "integer<b>"; return converterr("integer<b>", arg, msgbuf);
else if (ival < 0) { else if (ival < 0) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"unsigned byte integer is less than minimum"); "unsigned byte integer is less than minimum");
return "integer<b>"; return converterr("integer<b>", arg, msgbuf);
} }
else if (ival > UCHAR_MAX) { else if (ival > UCHAR_MAX) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"unsigned byte integer is greater than maximum"); "unsigned byte integer is greater than maximum");
return "integer<b>"; return converterr("integer<b>", arg, msgbuf);
} }
else else
*p = (unsigned char) ival; *p = (unsigned char) ival;
break; break;
} }
case 'B': /* byte sized bitfield - both signed and unsigned values allowed */ case 'B': {/* byte sized bitfield - both signed and unsigned
{ values allowed */
char *p = va_arg(*p_va, char *); char *p = va_arg(*p_va, char *);
long ival = PyInt_AsLong(arg); long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred()) if (ival == -1 && PyErr_Occurred())
return "integer<b>"; return converterr("integer<b>", arg, msgbuf);
else if (ival < SCHAR_MIN) { else if (ival < SCHAR_MIN) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"byte-sized integer bitfield is less than minimum"); "byte-sized integer bitfield is less than minimum");
return "integer<B>"; return converterr("integer<B>", arg, msgbuf);
} }
else if (ival > (int)UCHAR_MAX) { else if (ival > (int)UCHAR_MAX) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"byte-sized integer bitfield is greater than maximum"); "byte-sized integer bitfield is greater than maximum");
return "integer<B>"; return converterr("integer<B>", arg, msgbuf);
} }
else else
*p = (unsigned char) ival; *p = (unsigned char) ival;
break; break;
} }
case 'h': /* signed short int */ case 'h': {/* signed short int */
{
short *p = va_arg(*p_va, short *); short *p = va_arg(*p_va, short *);
long ival = PyInt_AsLong(arg); long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred()) if (ival == -1 && PyErr_Occurred())
return "integer<h>"; return converterr("integer<h>", arg, msgbuf);
else if (ival < SHRT_MIN) { else if (ival < SHRT_MIN) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"signed short integer is less than minimum"); "signed short integer is less than minimum");
return "integer<h>"; return converterr("integer<h>", arg, msgbuf);
} }
else if (ival > SHRT_MAX) { else if (ival > SHRT_MAX) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"signed short integer is greater than maximum"); "signed short integer is greater than maximum");
return "integer<h>"; return converterr("integer<h>", arg, msgbuf);
} }
else else
*p = (short) ival; *p = (short) ival;
break; break;
} }
case 'H': /* short int sized bitfield, both signed and unsigned allowed */ case 'H': { /* short int sized bitfield, both signed and
{ unsigned allowed */
unsigned short *p = va_arg(*p_va, unsigned short *); unsigned short *p = va_arg(*p_va, unsigned short *);
long ival = PyInt_AsLong(arg); long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred()) if (ival == -1 && PyErr_Occurred())
return "integer<H>"; return converterr("integer<H>", arg, msgbuf);
else if (ival < SHRT_MIN) { else if (ival < SHRT_MIN) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"short integer bitfield is less than minimum"); "short integer bitfield is less than minimum");
return "integer<H>"; return converterr("integer<H>", arg, msgbuf);
} }
else if (ival > USHRT_MAX) { else if (ival > USHRT_MAX) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"short integer bitfield is greater than maximum"); "short integer bitfield is greater than maximum");
return "integer<H>"; return converterr("integer<H>", arg, msgbuf);
} }
else else
*p = (unsigned short) ival; *p = (unsigned short) ival;
break; break;
} }
case 'i': /* signed int */ case 'i': {/* signed int */
{
int *p = va_arg(*p_va, int *); int *p = va_arg(*p_va, int *);
long ival = PyInt_AsLong(arg); long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred()) if (ival == -1 && PyErr_Occurred())
return "integer<i>"; return converterr("integer<i>", arg, msgbuf);
else if (ival > INT_MAX) { else if (ival > INT_MAX) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"signed integer is greater than maximum"); "signed integer is greater than maximum");
return "integer<i>"; return converterr("integer<i>", arg, msgbuf);
} }
else if (ival < INT_MIN) { else if (ival < INT_MIN) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"signed integer is less than minimum"); "signed integer is less than minimum");
return "integer<i>"; return converterr("integer<i>", arg, msgbuf);
} }
else else
*p = ival; *p = ival;
break; break;
} }
case 'l': /* long int */
{ case 'l': {/* long int */
long *p = va_arg(*p_va, long *); long *p = va_arg(*p_va, long *);
long ival = PyInt_AsLong(arg); long ival = PyInt_AsLong(arg);
if (ival == -1 && PyErr_Occurred()) if (ival == -1 && PyErr_Occurred())
return "integer<l>"; return converterr("integer<l>", arg, msgbuf);
else else
*p = ival; *p = ival;
break; break;
} }
#ifdef HAVE_LONG_LONG #ifdef HAVE_LONG_LONG
case 'L': /* LONG_LONG */ case 'L': {/* LONG_LONG */
{
LONG_LONG *p = va_arg( *p_va, LONG_LONG * ); LONG_LONG *p = va_arg( *p_va, LONG_LONG * );
LONG_LONG ival = PyLong_AsLongLong( arg ); LONG_LONG ival = PyLong_AsLongLong( arg );
if( ival == (LONG_LONG)-1 && PyErr_Occurred() ) { if( ival == (LONG_LONG)-1 && PyErr_Occurred() ) {
return "long<L>"; return converterr("long<L>", arg, msgbuf);
} else { } else {
*p = ival; *p = ival;
} }
@ -515,54 +514,49 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
} }
#endif #endif
case 'f': /* float */ case 'f': {/* float */
{
float *p = va_arg(*p_va, float *); float *p = va_arg(*p_va, float *);
double dval = PyFloat_AsDouble(arg); double dval = PyFloat_AsDouble(arg);
if (PyErr_Occurred()) if (PyErr_Occurred())
return "float<f>"; return converterr("float<f>", arg, msgbuf);
else else
*p = (float) dval; *p = (float) dval;
break; break;
} }
case 'd': /* double */ case 'd': {/* double */
{
double *p = va_arg(*p_va, double *); double *p = va_arg(*p_va, double *);
double dval = PyFloat_AsDouble(arg); double dval = PyFloat_AsDouble(arg);
if (PyErr_Occurred()) if (PyErr_Occurred())
return "float<d>"; return converterr("float<d>", arg, msgbuf);
else else
*p = dval; *p = dval;
break; break;
} }
#ifndef WITHOUT_COMPLEX #ifndef WITHOUT_COMPLEX
case 'D': /* complex double */ case 'D': {/* complex double */
{
Py_complex *p = va_arg(*p_va, Py_complex *); Py_complex *p = va_arg(*p_va, Py_complex *);
Py_complex cval; Py_complex cval;
cval = PyComplex_AsCComplex(arg); cval = PyComplex_AsCComplex(arg);
if (PyErr_Occurred()) if (PyErr_Occurred())
return "complex<D>"; return converterr("complex<D>", arg, msgbuf);
else else
*p = cval; *p = cval;
break; break;
} }
#endif /* WITHOUT_COMPLEX */ #endif /* WITHOUT_COMPLEX */
case 'c': /* char */ case 'c': {/* char */
{
char *p = va_arg(*p_va, char *); char *p = va_arg(*p_va, char *);
if (PyString_Check(arg) && PyString_Size(arg) == 1) if (PyString_Check(arg) && PyString_Size(arg) == 1)
*p = PyString_AsString(arg)[0]; *p = PyString_AsString(arg)[0];
else else
return "char"; return converterr("char", arg, msgbuf);
break; break;
} }
case 's': /* string */ case 's': {/* string */
{
if (*format == '#') { if (*format == '#') {
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 *);
@ -572,25 +566,18 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
*q = PyString_GET_SIZE(arg); *q = PyString_GET_SIZE(arg);
} }
else if (PyUnicode_Check(arg)) { else if (PyUnicode_Check(arg)) {
arg = _PyUnicode_AsDefaultEncodedString( arg = UNICODE_DEFAULT_ENCODING(arg);
arg, NULL);
if (arg == NULL) if (arg == NULL)
return "(unicode conversion error)"; return converterr(CONV_UNICODE,
arg, msgbuf);
*p = PyString_AS_STRING(arg); *p = PyString_AS_STRING(arg);
*q = PyString_GET_SIZE(arg); *q = PyString_GET_SIZE(arg);
} }
else { /* any buffer-like object */ else { /* any buffer-like object */
PyBufferProcs *pb = arg->ob_type->tp_as_buffer; char *buf;
int count; int count = convertbuffer(arg, p, &buf);
if ( pb == NULL || if (count < 0)
pb->bf_getreadbuffer == NULL || return converterr(buf, arg, msgbuf);
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; *q = count;
} }
format++; format++;
@ -600,22 +587,22 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
if (PyString_Check(arg)) if (PyString_Check(arg))
*p = PyString_AS_STRING(arg); *p = PyString_AS_STRING(arg);
else if (PyUnicode_Check(arg)) { else if (PyUnicode_Check(arg)) {
arg = _PyUnicode_AsDefaultEncodedString( arg = UNICODE_DEFAULT_ENCODING(arg);
arg, NULL);
if (arg == NULL) if (arg == NULL)
return "(unicode conversion error)"; return converterr(CONV_UNICODE,
arg, msgbuf);
*p = PyString_AS_STRING(arg); *p = PyString_AS_STRING(arg);
} }
else else
return "string"; return converterr("string", arg, msgbuf);
if ((int)strlen(*p) != PyString_Size(arg)) if ((int)strlen(*p) != PyString_Size(arg))
return "string without null bytes"; return converterr("string without null bytes",
arg, msgbuf);
} }
break; break;
} }
case 'z': /* string, may be NULL (None) */ case 'z': {/* string, may be NULL (None) */
{
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 *);
@ -629,25 +616,19 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
*q = PyString_GET_SIZE(arg); *q = PyString_GET_SIZE(arg);
} }
else if (PyUnicode_Check(arg)) { else if (PyUnicode_Check(arg)) {
arg = _PyUnicode_AsDefaultEncodedString( arg = UNICODE_DEFAULT_ENCODING(arg);
arg, NULL);
if (arg == NULL) if (arg == NULL)
return "(unicode conversion error)"; return converterr(CONV_UNICODE,
arg, msgbuf);
*p = PyString_AS_STRING(arg); *p = PyString_AS_STRING(arg);
*q = PyString_GET_SIZE(arg); *q = PyString_GET_SIZE(arg);
} }
else { /* any buffer-like object */ else { /* any buffer-like object */
PyBufferProcs *pb = arg->ob_type->tp_as_buffer; char *buf;
int count; int count = convertbuffer(arg, p, &buf);
if ( pb == NULL ||
pb->bf_getreadbuffer == NULL || if (count < 0)
pb->bf_getsegcount == NULL ) return converterr(buf, arg, msgbuf);
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; *q = count;
} }
format++; format++;
@ -659,14 +640,15 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
else if (PyString_Check(arg)) else if (PyString_Check(arg))
*p = PyString_AsString(arg); *p = PyString_AsString(arg);
else if (PyUnicode_Check(arg)) { else if (PyUnicode_Check(arg)) {
arg = _PyUnicode_AsDefaultEncodedString( arg = UNICODE_DEFAULT_ENCODING(arg);
arg, NULL);
if (arg == NULL) if (arg == NULL)
return "(unicode conversion error)"; return converterr(CONV_UNICODE,
arg, msgbuf);
*p = PyString_AS_STRING(arg); *p = PyString_AS_STRING(arg);
} }
else else
return "string or None"; return converterr("string or None",
arg, msgbuf);
if (*format == '#') { if (*format == '#') {
int *q = va_arg(*p_va, int *); int *q = va_arg(*p_va, int *);
if (arg == Py_None) if (arg == Py_None)
@ -677,13 +659,14 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
} }
else if (*p != NULL && else if (*p != NULL &&
(int)strlen(*p) != PyString_Size(arg)) (int)strlen(*p) != PyString_Size(arg))
return "string without null bytes or None"; return converterr(
"string without null bytes or None",
arg, msgbuf);
} }
break; break;
} }
case 'e': /* encoded string */ case 'e': {/* encoded string */
{
char **buffer; char **buffer;
const char *encoding; const char *encoding;
PyObject *u, *s; PyObject *u, *s;
@ -703,11 +686,14 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
else if (*format == 't') else if (*format == 't')
recode_strings = 0; recode_strings = 0;
else else
return "(unknown parser marker combination)"; return converterr(
"(unknown parser marker combination)",
arg, msgbuf);
buffer = (char **)va_arg(*p_va, char **); buffer = (char **)va_arg(*p_va, char **);
format++; format++;
if (buffer == NULL) if (buffer == NULL)
return "(buffer is NULL)"; return converterr("(buffer is NULL)",
arg, msgbuf);
/* Encode object */ /* Encode object */
if (!recode_strings && PyString_Check(arg)) { if (!recode_strings && PyString_Check(arg)) {
@ -718,8 +704,9 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
/* Convert object to Unicode */ /* Convert object to Unicode */
u = PyUnicode_FromObject(arg); u = PyUnicode_FromObject(arg);
if (u == NULL) if (u == NULL)
return \ return converterr(
"string or unicode or text buffer"; "string or unicode or text buffer",
arg, msgbuf);
/* Encode object; use default error handling */ /* Encode object; use default error handling */
s = PyUnicode_AsEncodedString(u, s = PyUnicode_AsEncodedString(u,
@ -727,56 +714,61 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
NULL); NULL);
Py_DECREF(u); Py_DECREF(u);
if (s == NULL) if (s == NULL)
return "(encoding failed)"; return converterr("(encoding failed)",
arg, msgbuf);
if (!PyString_Check(s)) { if (!PyString_Check(s)) {
Py_DECREF(s); Py_DECREF(s);
return \ return converterr(
"(encoder failed to return a string)"; "(encoder failed to return a string)",
arg, msgbuf);
} }
} }
size = PyString_GET_SIZE(s); size = PyString_GET_SIZE(s);
/* Write output; output is guaranteed to be /* Write output; output is guaranteed to be 0-terminated */
0-terminated */
if (*format == '#') { if (*format == '#') {
/* Using buffer length parameter '#': /* Using buffer length parameter '#':
- if *buffer is NULL, a new buffer - if *buffer is NULL, a new buffer of the
of the needed size is allocated and needed size is allocated and the data
the data copied into it; *buffer is copied into it; *buffer is updated to point
updated to point to the new buffer; to the new buffer; the caller is
the caller is responsible for responsible for PyMem_Free()ing it after
PyMem_Free()ing it after usage usage
- if *buffer is not NULL, the data - if *buffer is not NULL, the data is
is copied to *buffer; *buffer_len copied to *buffer; *buffer_len has to be
has to be set to the size of the set to the size of the buffer on input;
buffer on input; buffer overflow is buffer overflow is signalled with an error;
signalled with an error; buffer has buffer has to provide enough room for the
to provide enough room for the encoded string plus the trailing 0-byte
encoded string plus the trailing
0-byte
- in both cases, *buffer_len is - in both cases, *buffer_len is updated to
updated to the size of the buffer the size of the buffer /excluding/ the
/excluding/ the trailing 0-byte trailing 0-byte
*/ */
int *buffer_len = va_arg(*p_va, int *); int *buffer_len = va_arg(*p_va, int *);
format++; format++;
if (buffer_len == NULL) if (buffer_len == NULL)
return "(buffer_len is NULL)"; return converterr(
"(buffer_len is NULL)",
arg, msgbuf);
if (*buffer == NULL) { if (*buffer == NULL) {
*buffer = PyMem_NEW(char, size + 1); *buffer = PyMem_NEW(char, size + 1);
if (*buffer == NULL) { if (*buffer == NULL) {
Py_DECREF(s); Py_DECREF(s);
return "(memory error)"; return converterr(
"(memory error)",
arg, msgbuf);
} }
} else { } else {
if (size + 1 > *buffer_len) { if (size + 1 > *buffer_len) {
Py_DECREF(s); Py_DECREF(s);
return "(buffer overflow)"; return converterr(
"(buffer overflow)",
arg, msgbuf);
} }
} }
memcpy(*buffer, memcpy(*buffer,
@ -786,24 +778,26 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
} else { } else {
/* Using a 0-terminated buffer: /* Using a 0-terminated buffer:
- the encoded string has to be - the encoded string has to be 0-terminated
0-terminated for this variant to for this variant to work; if it is not, an
work; if it is not, an error raised error raised
- a new buffer of the needed size - a new buffer of the needed size is
is allocated and the data copied allocated and the data copied into it;
into it; *buffer is updated to *buffer is updated to point to the new
point to the new buffer; the caller buffer; the caller is responsible for
is responsible for PyMem_Free()ing it PyMem_Free()ing it after usage
after usage
*/ */
if ((int)strlen(PyString_AS_STRING(s)) != size) if ((int)strlen(PyString_AS_STRING(s)) != size)
return "(encoded string without NULL bytes)"; return converterr(
"(encoded string without NULL bytes)",
arg, msgbuf);
*buffer = PyMem_NEW(char, size + 1); *buffer = PyMem_NEW(char, size + 1);
if (*buffer == NULL) { if (*buffer == NULL) {
Py_DECREF(s); Py_DECREF(s);
return "(memory error)"; return converterr("(memory error)",
arg, msgbuf);
} }
memcpy(*buffer, memcpy(*buffer,
PyString_AS_STRING(s), PyString_AS_STRING(s),
@ -813,25 +807,15 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
break; break;
} }
case 'u': /* raw unicode buffer (Py_UNICODE *) */ case 'u': {/* raw unicode buffer (Py_UNICODE *) */
{
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 **);
PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
int *q = va_arg(*p_va, int *); int *q = va_arg(*p_va, int *);
int count; char *buf;
int count = convertbuffer(arg, p, &buf);
if ( pb == NULL || if (count < 0)
pb->bf_getreadbuffer == NULL || return converterr(buf, arg, msgbuf);
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)); *q = count/(sizeof(Py_UNICODE));
format++; format++;
} else { } else {
@ -840,33 +824,30 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
if (PyUnicode_Check(arg)) if (PyUnicode_Check(arg))
*p = PyUnicode_AS_UNICODE(arg); *p = PyUnicode_AS_UNICODE(arg);
else else
return "unicode"; return converterr("unicode", arg, msgbuf);
} }
break; break;
} }
case 'S': /* string object */ case 'S': { /* string object */
{
PyObject **p = va_arg(*p_va, PyObject **); PyObject **p = va_arg(*p_va, PyObject **);
if (PyString_Check(arg)) if (PyString_Check(arg))
*p = arg; *p = arg;
else else
return "string"; return converterr("string", arg, msgbuf);
break; break;
} }
case 'U': /* Unicode object */ case 'U': { /* Unicode object */
{
PyObject **p = va_arg(*p_va, PyObject **); PyObject **p = va_arg(*p_va, PyObject **);
if (PyUnicode_Check(arg)) if (PyUnicode_Check(arg))
*p = arg; *p = arg;
else else
return "unicode"; return converterr("unicode", arg, msgbuf);
break; break;
} }
case 'O': /* object */ case 'O': { /* object */
{
PyTypeObject *type; PyTypeObject *type;
PyObject **p; PyObject **p;
if (*format == '!') { if (*format == '!') {
@ -876,7 +857,7 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
if (arg->ob_type == type) if (arg->ob_type == type)
*p = arg; *p = arg;
else else
return type->tp_name; return converterr(type->tp_name, arg, msgbuf);
} }
else if (*format == '?') { else if (*format == '?') {
@ -886,7 +867,8 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
if ((*pred)(arg)) if ((*pred)(arg))
*p = arg; *p = arg;
else else
return "(unspecified)"; return converterr("(unspecified)",
arg, msgbuf);
} }
else if (*format == '&') { else if (*format == '&') {
@ -895,7 +877,8 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
void *addr = va_arg(*p_va, void *); void *addr = va_arg(*p_va, void *);
format++; format++;
if (! (*convert)(arg, addr)) if (! (*convert)(arg, addr))
return "(unspecified)"; return converterr("(unspecified)",
arg, msgbuf);
} }
else { else {
p = va_arg(*p_va, PyObject **); p = va_arg(*p_va, PyObject **);
@ -905,19 +888,20 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
} }
case 'w': /* memory buffer, read-write access */ case 'w': { /* memory buffer, read-write access */
{
void **p = va_arg(*p_va, void **); void **p = va_arg(*p_va, void **);
PyBufferProcs *pb = arg->ob_type->tp_as_buffer; PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
int count; int count;
if ( pb == NULL || pb->bf_getwritebuffer == NULL || if (pb == NULL ||
pb->bf_getwritebuffer == NULL ||
pb->bf_getsegcount == NULL) pb->bf_getsegcount == NULL)
return "read-write buffer"; return converterr("read-write buffer", arg, msgbuf);
if ((*pb->bf_getsegcount)(arg, NULL) != 1) if ((*pb->bf_getsegcount)(arg, NULL) != 1)
return "single-segment read-write buffer"; return converterr("single-segment read-write buffer",
arg, msgbuf);
if ((count = pb->bf_getwritebuffer(arg, 0, p)) < 0) if ((count = pb->bf_getwritebuffer(arg, 0, p)) < 0)
return "(unspecified)"; return converterr("(unspecified)", arg, msgbuf);
if (*format == '#') { if (*format == '#') {
int *q = va_arg(*p_va, int *); int *q = va_arg(*p_va, int *);
@ -927,34 +911,30 @@ convertsimple1(PyObject *arg, char **p_format, va_list *p_va)
break; break;
} }
case 't': /* 8-bit character buffer, read-only access */ case 't': { /* 8-bit character buffer, read-only access */
{
const char **p = va_arg(*p_va, const char **); const char **p = va_arg(*p_va, const char **);
PyBufferProcs *pb = arg->ob_type->tp_as_buffer; char *buf;
int count; int count;
if (*format++ != '#') if (*format++ != '#')
return "invalid use of 't' format character"; return converterr(
if ( !PyType_HasFeature( "invalid use of 't' format character",
arg->ob_type, arg, msgbuf);
Py_TPFLAGS_HAVE_GETCHARBUFFER) || if (!PyType_HasFeature(arg->ob_type,
pb == NULL || Py_TPFLAGS_HAVE_GETCHARBUFFER))
pb->bf_getcharbuffer == NULL || return converterr(
pb->bf_getsegcount == NULL ) "string or read-only character buffer",
return "string or read-only character buffer"; arg, msgbuf);
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)";
count = convertbuffer(arg, (void **)p, &buf);
if (count < 0)
return converterr(buf, arg, msgbuf);
*va_arg(*p_va, int *) = count; *va_arg(*p_va, int *) = count;
break; break;
} }
default: 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; 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 /* Support for keyword arguments donated by
Geoff Philbrick <philbric@delphi.hks.com> */ Geoff Philbrick <philbric@delphi.hks.com> */