summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2017-01-17 01:29:49 +0100
committerVictor Stinner <victor.stinner@gmail.com>2017-01-17 01:29:49 +0100
commit78a0bd77f603b38267d6e8084cd09873f3beecc1 (patch)
tree831d122bf341b216cf4386f4a516041e6e552dfa
parent271403abe36069797ac332e1c6eae3473878db20 (diff)
downloadcpython-78a0bd77f603b38267d6e8084cd09873f3beecc1.tar.gz
Add _PyArg_ParseStack() helper function
Issue #29286. Function similar to PyArg_ParseTuple(), but uses a C array of PyObject* to pass arguments. Don't support the compatibility mode.
-rw-r--r--Include/modsupport.h16
-rw-r--r--Python/getargs.c90
2 files changed, 82 insertions, 24 deletions
diff --git a/Include/modsupport.h b/Include/modsupport.h
index 188f0b1e12..5c21f98f06 100644
--- a/Include/modsupport.h
+++ b/Include/modsupport.h
@@ -79,17 +79,27 @@ typedef struct _PyArg_Parser {
} _PyArg_Parser;
#ifdef PY_SSIZE_T_CLEAN
#define _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT
+#define _PyArg_ParseStack _PyArg_ParseStack_SizeT
#define _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT
#define _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT
#endif
PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *,
struct _PyArg_Parser *, ...);
-PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,
- struct _PyArg_Parser *, ...);
+PyAPI_FUNC(int) _PyArg_ParseStack(
+ PyObject **args,
+ Py_ssize_t nargs,
+ const char *format,
+ ...);
+PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords(
+ PyObject **args,
+ Py_ssize_t nargs,
+ PyObject *kwnames,
+ struct _PyArg_Parser *,
+ ...);
PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *,
struct _PyArg_Parser *, va_list);
void _PyArg_Fini(void);
-#endif
+#endif /* Py_LIMITED_API */
PyAPI_FUNC(int) PyModule_AddObject(PyObject *, const char *, PyObject *);
PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long);
diff --git a/Python/getargs.c b/Python/getargs.c
index 8dd579fe40..35500d7e7d 100644
--- a/Python/getargs.c
+++ b/Python/getargs.c
@@ -26,6 +26,8 @@ int _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *,
#ifdef HAVE_DECLSPEC_DLL
/* Export functions */
PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...);
+PyAPI_FUNC(int) _PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs,
+ const char *format, ...);
PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords_SizeT(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,
struct _PyArg_Parser *parser, ...);
PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, const char *, ...);
@@ -66,6 +68,8 @@ typedef struct {
#define STATIC_FREELIST_ENTRIES 8
/* Forward */
+static int vgetargs1_impl(PyObject *args, PyObject **stack, Py_ssize_t nargs,
+ const char *format, va_list *p_va, int flags);
static int vgetargs1(PyObject *, const char *, va_list *, int);
static void seterror(Py_ssize_t, const char *, int *, const char *, const char *);
static const char *convertitem(PyObject *, const char **, va_list *, int, int *,
@@ -138,6 +142,31 @@ _PyArg_ParseTuple_SizeT(PyObject *args, const char *format, ...)
int
+_PyArg_ParseStack(PyObject **args, Py_ssize_t nargs, const char *format, ...)
+{
+ int retval;
+ va_list va;
+
+ va_start(va, format);
+ retval = vgetargs1_impl(NULL, args, nargs, format, &va, 0);
+ va_end(va);
+ return retval;
+}
+
+int
+_PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs, const char *format, ...)
+{
+ int retval;
+ va_list va;
+
+ va_start(va, format);
+ retval = vgetargs1_impl(NULL, args, nargs, format, &va, FLAG_SIZE_T);
+ va_end(va);
+ return retval;
+}
+
+
+int
PyArg_VaParse(PyObject *args, const char *format, va_list va)
{
va_list lva;
@@ -220,7 +249,8 @@ cleanreturn(int retval, freelist_t *freelist)
static int
-vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
+vgetargs1_impl(PyObject *compat_args, PyObject **stack, Py_ssize_t nargs, const char *format,
+ va_list *p_va, int flags)
{
char msgbuf[256];
int levels[32];
@@ -231,17 +261,18 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
int level = 0;
int endfmt = 0;
const char *formatsave = format;
- Py_ssize_t i, len;
+ Py_ssize_t i;
const char *msg;
int compat = flags & FLAG_COMPAT;
freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];
freelist_t freelist;
+ assert(nargs == 0 || stack != NULL);
+
freelist.entries = static_entries;
freelist.first_available = 0;
freelist.entries_malloced = 0;
- assert(compat || (args != (PyObject*)NULL));
flags = flags & ~FLAG_COMPAT;
while (endfmt == 0) {
@@ -305,7 +336,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
if (compat) {
if (max == 0) {
- if (args == NULL)
+ if (compat_args == NULL)
return 1;
PyErr_Format(PyExc_TypeError,
"%.200s%s takes no arguments",
@@ -314,14 +345,14 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
return cleanreturn(0, &freelist);
}
else if (min == 1 && max == 1) {
- if (args == NULL) {
+ if (compat_args == NULL) {
PyErr_Format(PyExc_TypeError,
"%.200s%s takes at least one argument",
fname==NULL ? "function" : fname,
fname==NULL ? "" : "()");
return cleanreturn(0, &freelist);
}
- msg = convertitem(args, &format, p_va, flags, levels,
+ msg = convertitem(compat_args, &format, p_va, flags, levels,
msgbuf, sizeof(msgbuf), &freelist);
if (msg == NULL)
return cleanreturn(1, &freelist);
@@ -335,34 +366,26 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
}
}
- if (!PyTuple_Check(args)) {
- PyErr_SetString(PyExc_SystemError,
- "new style getargs format but argument is not a tuple");
- return cleanreturn(0, &freelist);
- }
-
- len = PyTuple_GET_SIZE(args);
-
- if (len < min || max < len) {
+ if (nargs < min || max < nargs) {
if (message == NULL)
PyErr_Format(PyExc_TypeError,
"%.150s%s takes %s %d argument%s (%ld given)",
fname==NULL ? "function" : fname,
fname==NULL ? "" : "()",
min==max ? "exactly"
- : len < min ? "at least" : "at most",
- len < min ? min : max,
- (len < min ? min : max) == 1 ? "" : "s",
- Py_SAFE_DOWNCAST(len, Py_ssize_t, long));
+ : nargs < min ? "at least" : "at most",
+ nargs < min ? min : max,
+ (nargs < min ? min : max) == 1 ? "" : "s",
+ Py_SAFE_DOWNCAST(nargs, Py_ssize_t, long));
else
PyErr_SetString(PyExc_TypeError, message);
return cleanreturn(0, &freelist);
}
- for (i = 0; i < len; i++) {
+ for (i = 0; i < nargs; i++) {
if (*format == '|')
format++;
- msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va,
+ msg = convertitem(stack[i], &format, p_va,
flags, levels, msgbuf,
sizeof(msgbuf), &freelist);
if (msg) {
@@ -382,6 +405,31 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
return cleanreturn(1, &freelist);
}
+static int
+vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
+{
+ PyObject **stack;
+ Py_ssize_t nargs;
+
+ if (!(flags & FLAG_COMPAT)) {
+ assert(args != NULL);
+
+ if (!PyTuple_Check(args)) {
+ PyErr_SetString(PyExc_SystemError,
+ "new style getargs format but argument is not a tuple");
+ return 0;
+ }
+
+ stack = &PyTuple_GET_ITEM(args, 0);
+ nargs = PyTuple_GET_SIZE(args);
+ }
+ else {
+ stack = NULL;
+ nargs = 0;
+ }
+
+ return vgetargs1_impl(args, stack, nargs, format, p_va, flags);
+}
static void