📄 getargs.c
字号:
return converterr(
"string or read-only character buffer",
arg, msgbuf, bufsize);
if (pb->bf_getsegcount(arg, NULL) != 1)
return converterr(
"string or single-segment read-only buffer",
arg, msgbuf, bufsize);
count = pb->bf_getcharbuffer(arg, 0, p);
if (count < 0)
return converterr("(unspecified)", arg, msgbuf, bufsize);
*va_arg((*p_va), int *) = count;
break;
}
default:
return converterr("impossible<bad format char>", arg, msgbuf, bufsize);
}
*p_format = format;
return NULL;
}
static int
convertbuffer(PyObject *arg, void **p, char **errmsg)
{
// XXX:CW32
PyBufferProcs *pb = (PyBufferProcs *)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> */
// XXX:CW32
/* Return false (0) for error, else true. */
DL_EXPORT(int)
PyArg_ParseTupleAndKeywords(PyObject *args,
PyObject *keywords,
char *format,
const char * const *kwlist, ...)
{
int retval;
va_list va;
if ((args == NULL || !PyTuple_Check(args)) ||
(keywords != NULL && !PyDict_Check(keywords)) ||
format == NULL ||
kwlist == NULL)
{
PyErr_BadInternalCall();
return 0;
}
va_start(va, kwlist);
// XXX:CW32
retval = vgetargskeywords(args, keywords, format, (char **)kwlist, &va);
va_end(va);
return retval;
}
static int
vgetargskeywords(PyObject *args, PyObject *keywords, char *format,
char **kwlist, va_list *p_va)
{
char msgbuf[512];
int levels[32];
char *fname, *message;
int min, max;
char *formatsave;
int i, len, nargs, nkeywords;
char *msg, **p;
assert(args != NULL && PyTuple_Check(args));
assert(keywords == NULL || PyDict_Check(keywords));
assert(format != NULL);
assert(kwlist != NULL);
assert(p_va != NULL);
/* Search the format:
message <- error msg, if any (else NULL).
fname <- routine name, if any (else NULL).
min <- # of required arguments, or -1 if all are required.
max <- most arguments (required + optional).
Check that kwlist has a non-NULL entry for each arg.
Raise error if a tuple arg spec is found.
*/
fname = message = NULL;
formatsave = format;
p = kwlist;
min = -1;
max = 0;
while ((i = *format++) != '\0') {
if (isalpha(i) && i != 'e') {
max++;
if (*p == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"more argument specifiers than "
"keyword list entries");
return 0;
}
p++;
}
else if (i == '|')
min = max;
else if (i == ':') {
fname = format;
break;
}
else if (i == ';') {
message = format;
break;
}
else if (i == '(') {
PyErr_SetString(PyExc_RuntimeError,
"tuple found in format when using keyword "
"arguments");
return 0;
}
}
format = formatsave;
if (*p != NULL) {
PyErr_SetString(PyExc_RuntimeError,
"more keyword list entries than "
"argument specifiers");
return 0;
}
if (min < 0) {
/* All arguments are required. */
min = max;
}
nargs = PyTuple_GET_SIZE(args);
nkeywords = keywords == NULL ? 0 : PyDict_Size(keywords);
/* make sure there are no duplicate values for an argument;
its not clear when to use the term "keyword argument vs.
keyword parameter in messages */
if (nkeywords > 0) {
for (i = 0; i < nargs; i++) {
char *thiskw = kwlist[i];
if (thiskw == NULL)
break;
if (PyDict_GetItemString(keywords, thiskw)) {
PyErr_Format(PyExc_TypeError,
"keyword parameter '%s' was given "
"by position and by name",
thiskw);
return 0;
}
else if (PyErr_Occurred())
return 0;
}
}
/* required arguments missing from args can be supplied by keyword
arguments; set len to the number of posiitional arguments, and,
if that's less than the minimum required, add in the number of
required arguments that are supplied by keywords */
len = nargs;
if (nkeywords > 0 && nargs < min) {
for (i = nargs; i < min; i++) {
if (PyDict_GetItemString(keywords, kwlist[i]))
len++;
else if (PyErr_Occurred())
return 0;
}
}
/* make sure we got an acceptable number of arguments; the message
is a little confusing with keywords since keyword arguments
which are supplied, but don't match the required arguments
are not included in the "%d given" part of the message */
if (len < min || max < len) {
if (message == NULL) {
PyOS_snprintf(msgbuf, sizeof(msgbuf),
"%.200s%s takes %s %d argument%s "
"(%d given)",
fname==NULL ? "function" : fname,
fname==NULL ? "" : "()",
min==max ? "exactly"
: len < min ? "at least" : "at most",
len < min ? min : max,
(len < min ? min : max) == 1 ? "" : "s",
len);
message = msgbuf;
}
PyErr_SetString(PyExc_TypeError, message);
return 0;
}
/* convert the positional arguments */
for (i = 0; i < nargs; i++) {
if (*format == '|')
format++;
msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va,
levels, msgbuf, sizeof(msgbuf));
if (msg) {
seterror(i+1, msg, levels, fname, message);
return 0;
}
}
/* handle no keyword parameters in call */
if (nkeywords == 0)
return 1;
/* convert the keyword arguments; this uses the format
string where it was left after processing args */
for (i = nargs; i < max; i++) {
PyObject *item;
if (*format == '|')
format++;
item = PyDict_GetItemString(keywords, kwlist[i]);
if (item != NULL) {
Py_INCREF(item);
msg = convertitem(item, &format, p_va, levels, msgbuf,
sizeof(msgbuf));
Py_DECREF(item);
if (msg) {
seterror(i+1, msg, levels, fname, message);
return 0;
}
--nkeywords;
if (nkeywords == 0)
break;
}
else if (PyErr_Occurred())
return 0;
else {
msg = skipitem(&format, p_va);
if (msg) {
seterror(i+1, msg, levels, fname, message);
return 0;
}
}
}
/* make sure there are no extraneous keyword arguments */
if (nkeywords > 0) {
PyObject *key, *value;
int pos = 0;
while (PyDict_Next(keywords, &pos, &key, &value)) {
int match = 0;
char *ks = PyString_AsString(key);
for (i = 0; i < max; i++) {
if (!strcmp(ks, kwlist[i])) {
match = 1;
break;
}
}
if (!match) {
PyErr_Format(PyExc_TypeError,
"'%s' is an invalid keyword "
"argument for this function",
ks);
return 0;
}
}
}
return 1;
}
static char *
skipitem(char **p_format, va_list *p_va)
{
char *format = *p_format;
char c = *format++;
switch (c) {
case 'b': /* byte -- very short int */
case 'B': /* byte as bitfield */
{
(void) va_arg((*p_va), char *);
break;
}
case 'h': /* short int */
{
(void) va_arg((*p_va), short *);
break;
}
case 'H': /* short int as bitfield */
{
(void) va_arg((*p_va), unsigned short *);
break;
}
case 'i': /* int */
{
(void) va_arg((*p_va), int *);
break;
}
case 'l': /* long int */
{
(void) va_arg((*p_va), long *);
break;
}
#ifdef HAVE_LONG_LONG
case 'L': /* LONG_LONG int */
{
(void) va_arg((*p_va), LONG_LONG *);
break;
}
#endif
case 'f': /* float */
{
(void) va_arg((*p_va), float *);
break;
}
case 'd': /* double */
{
(void) va_arg((*p_va), double *);
break;
}
#ifndef WITHOUT_COMPLEX
case 'D': /* complex double */
{
(void) va_arg((*p_va), Py_complex *);
break;
}
#endif /* WITHOUT_COMPLEX */
case 'c': /* char */
{
(void) va_arg((*p_va), char *);
break;
}
#ifdef Py_USING_UNICODE
case 'u': /* unicode string */
#endif
case 's': /* string */
{
(void) va_arg((*p_va), char **);
if (*format == '#') {
(void) va_arg((*p_va), int *);
format++;
}
break;
}
case 'z': /* string */
{
(void) va_arg((*p_va), char **);
if (*format == '#') {
(void) va_arg((*p_va), int *);
format++;
}
break;
}
case 'S': /* string object */
{
(void) va_arg((*p_va), PyObject **);
break;
}
case 'O': /* object */
{
if (*format == '!') {
format++;
(void) va_arg((*p_va), PyTypeObject*);
(void) va_arg((*p_va), PyObject **);
}
#if 0
/* I don't know what this is for */
else if (*format == '?') {
inquiry pred = va_arg((*p_va), inquiry);
format++;
if ((*pred)(arg)) {
(void) va_arg((*p_va), PyObject **);
}
}
#endif
else if (*format == '&') {
typedef int (*converter)(PyObject *, void *);
(void) va_arg((*p_va), converter);
(void) va_arg((*p_va), void *);
format++;
}
else {
(void) va_arg((*p_va), PyObject **);
}
break;
}
default:
return "impossible<bad format char>";
}
*p_format = format;
return NULL;
}
DL_EXPORT(int)
PyArg_UnpackTuple(PyObject *args, char *name, int min, int max, ...)
{
int i, l;
PyObject **o;
va_list vargs;
#ifdef HAVE_STDARG_PROTOTYPES
va_start(vargs, max);
#else
va_start(vargs);
#endif
assert(min >= 0);
assert(min <= max);
if (!PyTuple_Check(args)) {
PyErr_SetString(PyExc_SystemError,
"PyArg_UnpackTuple() argument list is not a tuple");
return 0;
}
l = PyTuple_GET_SIZE(args);
if (l < min) {
if (name != NULL)
PyErr_Format(
PyExc_TypeError,
"%s expected %s%d arguments, got %d",
name, (min == max ? "" : "at least "), min, l);
else
PyErr_Format(
PyExc_TypeError,
"unpacked tuple should have %s%d elements,"
" but has %d",
(min == max ? "" : "at least "), min, l);
va_end(vargs);
return 0;
}
if (l > max) {
if (name != NULL)
PyErr_Format(
PyExc_TypeError,
"%s expected %s%d arguments, got %d",
name, (min == max ? "" : "at most "), max, l);
else
PyErr_Format(
PyExc_TypeError,
"unpacked tuple should have %s%d elements,"
" but has %d",
(min == max ? "" : "at most "), max, l);
va_end(vargs);
return 0;
}
for (i = 0; i < l; i++) {
o = va_arg(vargs, PyObject **);
*o = PyTuple_GET_ITEM(args, i);
}
va_end(vargs);
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -