Add _PyArg_ParseStack() helper function
Issue #29286. Function similar to PyArg_ParseTuple(), but uses a C array of PyObject* to pass arguments. Don't support the compatibility mode.
This commit is contained in:
parent
3e1fad6913
commit
6518a93cb1
|
@ -79,17 +79,27 @@ typedef struct _PyArg_Parser {
|
||||||
} _PyArg_Parser;
|
} _PyArg_Parser;
|
||||||
#ifdef PY_SSIZE_T_CLEAN
|
#ifdef PY_SSIZE_T_CLEAN
|
||||||
#define _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT
|
#define _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT
|
||||||
|
#define _PyArg_ParseStack _PyArg_ParseStack_SizeT
|
||||||
#define _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT
|
#define _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT
|
||||||
#define _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT
|
#define _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT
|
||||||
#endif
|
#endif
|
||||||
PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *,
|
PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *,
|
||||||
struct _PyArg_Parser *, ...);
|
struct _PyArg_Parser *, ...);
|
||||||
PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,
|
PyAPI_FUNC(int) _PyArg_ParseStack(
|
||||||
struct _PyArg_Parser *, ...);
|
PyObject **args,
|
||||||
|
Py_ssize_t nargs,
|
||||||
|
const char *format,
|
||||||
|
...);
|
||||||
|
PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords(
|
||||||
|
PyObject **args,
|
||||||
|
Py_ssize_t nargs,
|
||||||
|
PyObject *kwnames,
|
||||||
|
struct _PyArg_Parser *,
|
||||||
|
...);
|
||||||
PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *,
|
PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *,
|
||||||
struct _PyArg_Parser *, va_list);
|
struct _PyArg_Parser *, va_list);
|
||||||
void _PyArg_Fini(void);
|
void _PyArg_Fini(void);
|
||||||
#endif
|
#endif /* Py_LIMITED_API */
|
||||||
|
|
||||||
PyAPI_FUNC(int) PyModule_AddObject(PyObject *, const char *, PyObject *);
|
PyAPI_FUNC(int) PyModule_AddObject(PyObject *, const char *, PyObject *);
|
||||||
PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long);
|
PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long);
|
||||||
|
|
|
@ -26,6 +26,8 @@ int _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *,
|
||||||
#ifdef HAVE_DECLSPEC_DLL
|
#ifdef HAVE_DECLSPEC_DLL
|
||||||
/* Export functions */
|
/* Export functions */
|
||||||
PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...);
|
PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...);
|
||||||
|
PyAPI_FUNC(int) _PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs,
|
||||||
|
const char *format, ...);
|
||||||
PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords_SizeT(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,
|
PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords_SizeT(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,
|
||||||
struct _PyArg_Parser *parser, ...);
|
struct _PyArg_Parser *parser, ...);
|
||||||
PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, const char *, ...);
|
PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, const char *, ...);
|
||||||
|
@ -66,6 +68,8 @@ typedef struct {
|
||||||
#define STATIC_FREELIST_ENTRIES 8
|
#define STATIC_FREELIST_ENTRIES 8
|
||||||
|
|
||||||
/* Forward */
|
/* Forward */
|
||||||
|
static int vgetargs1_impl(PyObject *args, PyObject **stack, Py_ssize_t nargs,
|
||||||
|
const char *format, va_list *p_va, int flags);
|
||||||
static int vgetargs1(PyObject *, const char *, va_list *, int);
|
static int vgetargs1(PyObject *, const char *, va_list *, int);
|
||||||
static void seterror(Py_ssize_t, const char *, int *, const char *, const char *);
|
static void seterror(Py_ssize_t, const char *, int *, const char *, const char *);
|
||||||
static const char *convertitem(PyObject *, const char **, va_list *, int, int *,
|
static const char *convertitem(PyObject *, const char **, va_list *, int, int *,
|
||||||
|
@ -137,6 +141,31 @@ _PyArg_ParseTuple_SizeT(PyObject *args, const char *format, ...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyArg_ParseStack(PyObject **args, Py_ssize_t nargs, const char *format, ...)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, format);
|
||||||
|
retval = vgetargs1_impl(NULL, args, nargs, format, &va, 0);
|
||||||
|
va_end(va);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs, const char *format, ...)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, format);
|
||||||
|
retval = vgetargs1_impl(NULL, args, nargs, format, &va, FLAG_SIZE_T);
|
||||||
|
va_end(va);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
PyArg_VaParse(PyObject *args, const char *format, va_list va)
|
PyArg_VaParse(PyObject *args, const char *format, va_list va)
|
||||||
{
|
{
|
||||||
|
@ -220,7 +249,8 @@ cleanreturn(int retval, freelist_t *freelist)
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
|
vgetargs1_impl(PyObject *compat_args, PyObject **stack, Py_ssize_t nargs, const char *format,
|
||||||
|
va_list *p_va, int flags)
|
||||||
{
|
{
|
||||||
char msgbuf[256];
|
char msgbuf[256];
|
||||||
int levels[32];
|
int levels[32];
|
||||||
|
@ -231,17 +261,18 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
|
||||||
int level = 0;
|
int level = 0;
|
||||||
int endfmt = 0;
|
int endfmt = 0;
|
||||||
const char *formatsave = format;
|
const char *formatsave = format;
|
||||||
Py_ssize_t i, len;
|
Py_ssize_t i;
|
||||||
const char *msg;
|
const char *msg;
|
||||||
int compat = flags & FLAG_COMPAT;
|
int compat = flags & FLAG_COMPAT;
|
||||||
freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];
|
freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];
|
||||||
freelist_t freelist;
|
freelist_t freelist;
|
||||||
|
|
||||||
|
assert(nargs == 0 || stack != NULL);
|
||||||
|
|
||||||
freelist.entries = static_entries;
|
freelist.entries = static_entries;
|
||||||
freelist.first_available = 0;
|
freelist.first_available = 0;
|
||||||
freelist.entries_malloced = 0;
|
freelist.entries_malloced = 0;
|
||||||
|
|
||||||
assert(compat || (args != (PyObject*)NULL));
|
|
||||||
flags = flags & ~FLAG_COMPAT;
|
flags = flags & ~FLAG_COMPAT;
|
||||||
|
|
||||||
while (endfmt == 0) {
|
while (endfmt == 0) {
|
||||||
|
@ -305,7 +336,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
|
||||||
|
|
||||||
if (compat) {
|
if (compat) {
|
||||||
if (max == 0) {
|
if (max == 0) {
|
||||||
if (args == NULL)
|
if (compat_args == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"%.200s%s takes no arguments",
|
"%.200s%s takes no arguments",
|
||||||
|
@ -314,14 +345,14 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
|
||||||
return cleanreturn(0, &freelist);
|
return cleanreturn(0, &freelist);
|
||||||
}
|
}
|
||||||
else if (min == 1 && max == 1) {
|
else if (min == 1 && max == 1) {
|
||||||
if (args == NULL) {
|
if (compat_args == NULL) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"%.200s%s takes at least one argument",
|
"%.200s%s takes at least one argument",
|
||||||
fname==NULL ? "function" : fname,
|
fname==NULL ? "function" : fname,
|
||||||
fname==NULL ? "" : "()");
|
fname==NULL ? "" : "()");
|
||||||
return cleanreturn(0, &freelist);
|
return cleanreturn(0, &freelist);
|
||||||
}
|
}
|
||||||
msg = convertitem(args, &format, p_va, flags, levels,
|
msg = convertitem(compat_args, &format, p_va, flags, levels,
|
||||||
msgbuf, sizeof(msgbuf), &freelist);
|
msgbuf, sizeof(msgbuf), &freelist);
|
||||||
if (msg == NULL)
|
if (msg == NULL)
|
||||||
return cleanreturn(1, &freelist);
|
return cleanreturn(1, &freelist);
|
||||||
|
@ -335,34 +366,26 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PyTuple_Check(args)) {
|
if (nargs < min || max < nargs) {
|
||||||
PyErr_SetString(PyExc_SystemError,
|
|
||||||
"new style getargs format but argument is not a tuple");
|
|
||||||
return cleanreturn(0, &freelist);
|
|
||||||
}
|
|
||||||
|
|
||||||
len = PyTuple_GET_SIZE(args);
|
|
||||||
|
|
||||||
if (len < min || max < len) {
|
|
||||||
if (message == NULL)
|
if (message == NULL)
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"%.150s%s takes %s %d argument%s (%ld given)",
|
"%.150s%s takes %s %d argument%s (%ld given)",
|
||||||
fname==NULL ? "function" : fname,
|
fname==NULL ? "function" : fname,
|
||||||
fname==NULL ? "" : "()",
|
fname==NULL ? "" : "()",
|
||||||
min==max ? "exactly"
|
min==max ? "exactly"
|
||||||
: len < min ? "at least" : "at most",
|
: nargs < min ? "at least" : "at most",
|
||||||
len < min ? min : max,
|
nargs < min ? min : max,
|
||||||
(len < min ? min : max) == 1 ? "" : "s",
|
(nargs < min ? min : max) == 1 ? "" : "s",
|
||||||
Py_SAFE_DOWNCAST(len, Py_ssize_t, long));
|
Py_SAFE_DOWNCAST(nargs, Py_ssize_t, long));
|
||||||
else
|
else
|
||||||
PyErr_SetString(PyExc_TypeError, message);
|
PyErr_SetString(PyExc_TypeError, message);
|
||||||
return cleanreturn(0, &freelist);
|
return cleanreturn(0, &freelist);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < nargs; i++) {
|
||||||
if (*format == '|')
|
if (*format == '|')
|
||||||
format++;
|
format++;
|
||||||
msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va,
|
msg = convertitem(stack[i], &format, p_va,
|
||||||
flags, levels, msgbuf,
|
flags, levels, msgbuf,
|
||||||
sizeof(msgbuf), &freelist);
|
sizeof(msgbuf), &freelist);
|
||||||
if (msg) {
|
if (msg) {
|
||||||
|
@ -382,6 +405,31 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
|
||||||
return cleanreturn(1, &freelist);
|
return cleanreturn(1, &freelist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
|
||||||
|
{
|
||||||
|
PyObject **stack;
|
||||||
|
Py_ssize_t nargs;
|
||||||
|
|
||||||
|
if (!(flags & FLAG_COMPAT)) {
|
||||||
|
assert(args != NULL);
|
||||||
|
|
||||||
|
if (!PyTuple_Check(args)) {
|
||||||
|
PyErr_SetString(PyExc_SystemError,
|
||||||
|
"new style getargs format but argument is not a tuple");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack = &PyTuple_GET_ITEM(args, 0);
|
||||||
|
nargs = PyTuple_GET_SIZE(args);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stack = NULL;
|
||||||
|
nargs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vgetargs1_impl(args, stack, nargs, format, p_va, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in New Issue