diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2016-12-08 23:29:49 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2016-12-08 23:29:49 (GMT) |
commit | e9abde4642451f17d98e43aacc2bac74f83451c3 (patch) | |
tree | 466818933aebd4a9fd82c97f436dc19f57aa3d89 /Python/modsupport.c | |
parent | b551b6c9f083af7bffba224ca32e72175e7f8d54 (diff) | |
download | cpython-e9abde4642451f17d98e43aacc2bac74f83451c3.zip cpython-e9abde4642451f17d98e43aacc2bac74f83451c3.tar.gz cpython-e9abde4642451f17d98e43aacc2bac74f83451c3.tar.bz2 |
Add _Py_VaBuildStack() function
Issue #28915: Similar to Py_VaBuildValue(), but work on a C array of PyObject*,
instead of creating a tuple.
Diffstat (limited to 'Python/modsupport.c')
-rw-r--r-- | Python/modsupport.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/Python/modsupport.c b/Python/modsupport.c index eef79c4..01b5dc9 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -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, ...) |