mirror of
https://github.com/python/cpython.git
synced 2025-10-22 22:53:06 +00:00
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:
parent
9cea41c195
commit
1cb7aa3e6e
1 changed files with 529 additions and 530 deletions
399
Python/getargs.c
399
Python/getargs.c
|
|
@ -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> */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue