[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

AltStyle によって変換されたページ (->オリジナル) /