Add _Py_VaBuildStack() function
Issue #28915: Similar to Py_VaBuildValue(), but work on a C array of PyObject*, instead of creating a tuple.
This commit is contained in:
parent
b551b6c9f0
commit
e9abde4642
|
@ -21,9 +21,16 @@ extern "C" {
|
|||
#endif /* !Py_LIMITED_API */
|
||||
#define Py_BuildValue _Py_BuildValue_SizeT
|
||||
#define Py_VaBuildValue _Py_VaBuildValue_SizeT
|
||||
#define _Py_VaBuildStack _Py_VaBuildStack_SizeT
|
||||
#else
|
||||
#ifndef Py_LIMITED_API
|
||||
PyAPI_FUNC(PyObject *) _Py_VaBuildValue_SizeT(const char *, va_list);
|
||||
PyAPI_FUNC(PyObject **) _Py_VaBuildStack_SizeT(
|
||||
PyObject **small_stack,
|
||||
Py_ssize_t small_stack_len,
|
||||
const char *format,
|
||||
va_list va,
|
||||
Py_ssize_t *p_nargs);
|
||||
#endif /* !Py_LIMITED_API */
|
||||
#endif
|
||||
|
||||
|
@ -47,6 +54,12 @@ PyAPI_FUNC(int) PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *,
|
|||
const char *, char **, va_list);
|
||||
#endif
|
||||
PyAPI_FUNC(PyObject *) Py_VaBuildValue(const char *, va_list);
|
||||
PyAPI_FUNC(PyObject **) _Py_VaBuildStack(
|
||||
PyObject **small_stack,
|
||||
Py_ssize_t small_stack_len,
|
||||
const char *format,
|
||||
va_list va,
|
||||
Py_ssize_t *p_nargs);
|
||||
|
||||
#ifndef Py_LIMITED_API
|
||||
typedef struct _PyArg_Parser {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
typedef double va_double;
|
||||
|
||||
static PyObject *va_build_value(const char *, va_list, int);
|
||||
static PyObject **va_build_stack(PyObject **small_stack, Py_ssize_t small_stack_len, const char *, va_list, int, Py_ssize_t*);
|
||||
|
||||
/* Package context -- the full module name for package imports */
|
||||
const char *_Py_PackageContext = NULL;
|
||||
|
@ -60,6 +61,7 @@ countformat(const char *format, char endchar)
|
|||
/* After an original idea and first implementation by Steven Miale */
|
||||
|
||||
static PyObject *do_mktuple(const char**, va_list *, char, Py_ssize_t, int);
|
||||
static int do_mkstack(PyObject **, const char**, va_list *, char, Py_ssize_t, int);
|
||||
static PyObject *do_mklist(const char**, va_list *, char, Py_ssize_t, int);
|
||||
static PyObject *do_mkdict(const char**, va_list *, char, Py_ssize_t, int);
|
||||
static PyObject *do_mkvalue(const char**, va_list *, int);
|
||||
|
@ -182,6 +184,43 @@ do_mklist(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int
|
|||
return v;
|
||||
}
|
||||
|
||||
static int
|
||||
do_mkstack(PyObject **stack, const char **p_format, va_list *p_va,
|
||||
char endchar, Py_ssize_t n, int flags)
|
||||
{
|
||||
Py_ssize_t i;
|
||||
|
||||
if (n < 0) {
|
||||
return -1;
|
||||
}
|
||||
/* Note that we can't bail immediately on error as this will leak
|
||||
refcounts on any 'N' arguments. */
|
||||
for (i = 0; i < n; i++) {
|
||||
PyObject *w = do_mkvalue(p_format, p_va, flags);
|
||||
if (w == NULL) {
|
||||
do_ignore(p_format, p_va, endchar, n - i - 1, flags);
|
||||
goto error;
|
||||
}
|
||||
stack[i] = w;
|
||||
}
|
||||
if (**p_format != endchar) {
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"Unmatched paren in format");
|
||||
goto error;
|
||||
}
|
||||
if (endchar) {
|
||||
++*p_format;
|
||||
}
|
||||
return 0;
|
||||
|
||||
error:
|
||||
n = i;
|
||||
for (i=0; i < n; i++) {
|
||||
Py_DECREF(stack[i]);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
do_mktuple(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
|
||||
{
|
||||
|
@ -488,6 +527,65 @@ va_build_value(const char *format, va_list va, int flags)
|
|||
return retval;
|
||||
}
|
||||
|
||||
PyObject **
|
||||
_Py_VaBuildStack(PyObject **small_stack, Py_ssize_t small_stack_len,
|
||||
const char *format, va_list va, Py_ssize_t *p_nargs)
|
||||
{
|
||||
return va_build_stack(small_stack, small_stack_len, format, va, 0, p_nargs);
|
||||
}
|
||||
|
||||
PyObject **
|
||||
_Py_VaBuildStack_SizeT(PyObject **small_stack, Py_ssize_t small_stack_len,
|
||||
const char *format, va_list va, Py_ssize_t *p_nargs)
|
||||
{
|
||||
return va_build_stack(small_stack, small_stack_len, format, va, FLAG_SIZE_T, p_nargs);
|
||||
}
|
||||
|
||||
static PyObject **
|
||||
va_build_stack(PyObject **small_stack, Py_ssize_t small_stack_len,
|
||||
const char *format, va_list va, int flags, Py_ssize_t *p_nargs)
|
||||
{
|
||||
const char *f;
|
||||
Py_ssize_t n;
|
||||
va_list lva;
|
||||
PyObject **stack;
|
||||
int res;
|
||||
|
||||
n = countformat(format, '\0');
|
||||
if (n < 0) {
|
||||
*p_nargs = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
*p_nargs = 0;
|
||||
return small_stack;
|
||||
}
|
||||
|
||||
if (n <= small_stack_len) {
|
||||
stack = small_stack;
|
||||
}
|
||||
else {
|
||||
stack = PyMem_Malloc(n * sizeof(stack[0]));
|
||||
if (stack == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
va_copy(lva, va);
|
||||
f = format;
|
||||
res = do_mkstack(stack, &f, &lva, '\0', n, flags);
|
||||
va_end(lva);
|
||||
|
||||
if (res < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*p_nargs = n;
|
||||
return stack;
|
||||
}
|
||||
|
||||
|
||||
PyObject *
|
||||
PyEval_CallFunction(PyObject *callable, const char *format, ...)
|
||||
|
|
Loading…
Reference in New Issue