[Python-checkins] cpython: Add _Py_VaBuildStack() function

victor.stinner python-checkins at python.org
Thu Dec 8 20:16:59 EST 2016


https://hg.python.org/cpython/rev/c1414b182232
changeset:   105536:c1414b182232
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Fri Dec 09 00:29:49 2016 +0100
summary:
  Add _Py_VaBuildStack() function

Issue #28915: Similar to Py_VaBuildValue(), but work on a C array of PyObject*,
instead of creating a tuple.

files:
  Include/modsupport.h |  13 ++++
  Python/modsupport.c  |  98 ++++++++++++++++++++++++++++++++
  2 files changed, 111 insertions(+), 0 deletions(-)


diff --git a/Include/modsupport.h b/Include/modsupport.h
--- a/Include/modsupport.h
+++ b/Include/modsupport.h
@@ -21,9 +21,16 @@
 #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 @@
                                                   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 {
diff --git a/Python/modsupport.c b/Python/modsupport.c
--- 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 @@
 /* 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 @@
     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 @@
     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, ...)

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list