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 */
|
#endif /* !Py_LIMITED_API */
|
||||||
#define Py_BuildValue _Py_BuildValue_SizeT
|
#define Py_BuildValue _Py_BuildValue_SizeT
|
||||||
#define Py_VaBuildValue _Py_VaBuildValue_SizeT
|
#define Py_VaBuildValue _Py_VaBuildValue_SizeT
|
||||||
|
#define _Py_VaBuildStack _Py_VaBuildStack_SizeT
|
||||||
#else
|
#else
|
||||||
#ifndef Py_LIMITED_API
|
#ifndef Py_LIMITED_API
|
||||||
PyAPI_FUNC(PyObject *) _Py_VaBuildValue_SizeT(const char *, va_list);
|
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 /* !Py_LIMITED_API */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -47,6 +54,12 @@ PyAPI_FUNC(int) PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *,
|
||||||
const char *, char **, va_list);
|
const char *, char **, va_list);
|
||||||
#endif
|
#endif
|
||||||
PyAPI_FUNC(PyObject *) Py_VaBuildValue(const char *, va_list);
|
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
|
#ifndef Py_LIMITED_API
|
||||||
typedef struct _PyArg_Parser {
|
typedef struct _PyArg_Parser {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
typedef double va_double;
|
typedef double va_double;
|
||||||
|
|
||||||
static PyObject *va_build_value(const char *, va_list, int);
|
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 */
|
/* Package context -- the full module name for package imports */
|
||||||
const char *_Py_PackageContext = NULL;
|
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 */
|
/* After an original idea and first implementation by Steven Miale */
|
||||||
|
|
||||||
static PyObject *do_mktuple(const char**, va_list *, char, Py_ssize_t, int);
|
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_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_mkdict(const char**, va_list *, char, Py_ssize_t, int);
|
||||||
static PyObject *do_mkvalue(const char**, va_list *, 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;
|
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 *
|
static PyObject *
|
||||||
do_mktuple(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
|
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;
|
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 *
|
PyObject *
|
||||||
PyEval_CallFunction(PyObject *callable, const char *format, ...)
|
PyEval_CallFunction(PyObject *callable, const char *format, ...)
|
||||||
|
|
Loading…
Reference in New Issue