Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6518a93

Browse files
committed
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.
1 parent 3e1fad6 commit 6518a93

2 files changed

Lines changed: 82 additions & 24 deletions

File tree

Include/modsupport.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,27 @@ typedef struct _PyArg_Parser {
7979
} _PyArg_Parser;
8080
#ifdef PY_SSIZE_T_CLEAN
8181
#define _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT
82+
#define _PyArg_ParseStack _PyArg_ParseStack_SizeT
8283
#define _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT
8384
#define _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT
8485
#endif
8586
PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *,
8687
struct _PyArg_Parser *, ...);
87-
PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,
88-
struct _PyArg_Parser *, ...);
88+
PyAPI_FUNC(int) _PyArg_ParseStack(
89+
PyObject **args,
90+
Py_ssize_t nargs,
91+
const char *format,
92+
...);
93+
PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords(
94+
PyObject **args,
95+
Py_ssize_t nargs,
96+
PyObject *kwnames,
97+
struct _PyArg_Parser *,
98+
...);
8999
PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *,
90100
struct _PyArg_Parser *, va_list);
91101
void _PyArg_Fini(void);
92-
#endif
102+
#endif /* Py_LIMITED_API */
93103

94104
PyAPI_FUNC(int) PyModule_AddObject(PyObject *, const char *, PyObject *);
95105
PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long);

Python/getargs.c

Lines changed: 69 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ int _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *,
2626
#ifdef HAVE_DECLSPEC_DLL
2727
/* Export functions */
2828
PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...);
29+
PyAPI_FUNC(int) _PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs,
30+
const char *format, ...);
2931
PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords_SizeT(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,
3032
struct _PyArg_Parser *parser, ...);
3133
PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, const char *, ...);
@@ -66,6 +68,8 @@ typedef struct {
6668
#define STATIC_FREELIST_ENTRIES 8
6769

6870
/* Forward */
71+
static int vgetargs1_impl(PyObject *args, PyObject **stack, Py_ssize_t nargs,
72+
const char *format, va_list *p_va, int flags);
6973
static int vgetargs1(PyObject *, const char *, va_list *, int);
7074
static void seterror(Py_ssize_t, const char *, int *, const char *, const char *);
7175
static const char *convertitem(PyObject *, const char **, va_list *, int, int *,
@@ -137,6 +141,31 @@ _PyArg_ParseTuple_SizeT(PyObject *args, const char *format, ...)
137141
}
138142

139143

144+
int
145+
_PyArg_ParseStack(PyObject **args, Py_ssize_t nargs, const char *format, ...)
146+
{
147+
int retval;
148+
va_list va;
149+
150+
va_start(va, format);
151+
retval = vgetargs1_impl(NULL, args, nargs, format, &va, 0);
152+
va_end(va);
153+
return retval;
154+
}
155+
156+
int
157+
_PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs, const char *format, ...)
158+
{
159+
int retval;
160+
va_list va;
161+
162+
va_start(va, format);
163+
retval = vgetargs1_impl(NULL, args, nargs, format, &va, FLAG_SIZE_T);
164+
va_end(va);
165+
return retval;
166+
}
167+
168+
140169
int
141170
PyArg_VaParse(PyObject *args, const char *format, va_list va)
142171
{
@@ -220,7 +249,8 @@ cleanreturn(int retval, freelist_t *freelist)
220249

221250

222251
static int
223-
vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
252+
vgetargs1_impl(PyObject *compat_args, PyObject **stack, Py_ssize_t nargs, const char *format,
253+
va_list *p_va, int flags)
224254
{
225255
char msgbuf[256];
226256
int levels[32];
@@ -231,17 +261,18 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
231261
int level = 0;
232262
int endfmt = 0;
233263
const char *formatsave = format;
234-
Py_ssize_t i, len;
264+
Py_ssize_t i;
235265
const char *msg;
236266
int compat = flags & FLAG_COMPAT;
237267
freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];
238268
freelist_t freelist;
239269

270+
assert(nargs == 0 || stack != NULL);
271+
240272
freelist.entries = static_entries;
241273
freelist.first_available = 0;
242274
freelist.entries_malloced = 0;
243275

244-
assert(compat || (args != (PyObject*)NULL));
245276
flags = flags & ~FLAG_COMPAT;
246277

247278
while (endfmt == 0) {
@@ -305,7 +336,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
305336

306337
if (compat) {
307338
if (max == 0) {
308-
if (args == NULL)
339+
if (compat_args == NULL)
309340
return 1;
310341
PyErr_Format(PyExc_TypeError,
311342
"%.200s%s takes no arguments",
@@ -314,14 +345,14 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
314345
return cleanreturn(0, &freelist);
315346
}
316347
else if (min == 1 && max == 1) {
317-
if (args == NULL) {
348+
if (compat_args == NULL) {
318349
PyErr_Format(PyExc_TypeError,
319350
"%.200s%s takes at least one argument",
320351
fname==NULL ? "function" : fname,
321352
fname==NULL ? "" : "()");
322353
return cleanreturn(0, &freelist);
323354
}
324-
msg = convertitem(args, &format, p_va, flags, levels,
355+
msg = convertitem(compat_args, &format, p_va, flags, levels,
325356
msgbuf, sizeof(msgbuf), &freelist);
326357
if (msg == NULL)
327358
return cleanreturn(1, &freelist);
@@ -335,34 +366,26 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
335366
}
336367
}
337368

338-
if (!PyTuple_Check(args)) {
339-
PyErr_SetString(PyExc_SystemError,
340-
"new style getargs format but argument is not a tuple");
341-
return cleanreturn(0, &freelist);
342-
}
343-
344-
len = PyTuple_GET_SIZE(args);
345-
346-
if (len < min || max < len) {
369+
if (nargs < min || max < nargs) {
347370
if (message == NULL)
348371
PyErr_Format(PyExc_TypeError,
349372
"%.150s%s takes %s %d argument%s (%ld given)",
350373
fname==NULL ? "function" : fname,
351374
fname==NULL ? "" : "()",
352375
min==max ? "exactly"
353-
: len < min ? "at least" : "at most",
354-
len < min ? min : max,
355-
(len < min ? min : max) == 1 ? "" : "s",
356-
Py_SAFE_DOWNCAST(len, Py_ssize_t, long));
376+
: nargs < min ? "at least" : "at most",
377+
nargs < min ? min : max,
378+
(nargs < min ? min : max) == 1 ? "" : "s",
379+
Py_SAFE_DOWNCAST(nargs, Py_ssize_t, long));
357380
else
358381
PyErr_SetString(PyExc_TypeError, message);
359382
return cleanreturn(0, &freelist);
360383
}
361384

362-
for (i = 0; i < len; i++) {
385+
for (i = 0; i < nargs; i++) {
363386
if (*format == '|')
364387
format++;
365-
msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va,
388+
msg = convertitem(stack[i], &format, p_va,
366389
flags, levels, msgbuf,
367390
sizeof(msgbuf), &freelist);
368391
if (msg) {
@@ -382,6 +405,31 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
382405
return cleanreturn(1, &freelist);
383406
}
384407

408+
static int
409+
vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
410+
{
411+
PyObject **stack;
412+
Py_ssize_t nargs;
413+
414+
if (!(flags & FLAG_COMPAT)) {
415+
assert(args != NULL);
416+
417+
if (!PyTuple_Check(args)) {
418+
PyErr_SetString(PyExc_SystemError,
419+
"new style getargs format but argument is not a tuple");
420+
return 0;
421+
}
422+
423+
stack = &PyTuple_GET_ITEM(args, 0);
424+
nargs = PyTuple_GET_SIZE(args);
425+
}
426+
else {
427+
stack = NULL;
428+
nargs = 0;
429+
}
430+
431+
return vgetargs1_impl(args, stack, nargs, format, p_va, flags);
432+
}
385433

386434

387435
static void

0 commit comments

Comments
 (0)