@@ -79,6 +79,10 @@ static int vgetargskeywords(PyObject *, PyObject *,
7979 const char * , char * * , va_list * , int );
8080static int vgetargskeywordsfast (PyObject * , PyObject * ,
8181 struct _PyArg_Parser * , va_list * , int );
82+ static int vgetargskeywordsfast_impl (PyObject * * args , Py_ssize_t nargs ,
83+ PyObject * keywords , PyObject * kwnames ,
84+ struct _PyArg_Parser * parser ,
85+ va_list * p_va , int flags );
8286static const char * skipitem (const char * * , va_list * , int );
8387
8488int
@@ -1469,6 +1473,46 @@ _PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords,
14691473 return retval ;
14701474}
14711475
1476+ int
1477+ _PyArg_ParseStack (PyObject * * args , Py_ssize_t nargs , PyObject * kwnames ,
1478+ struct _PyArg_Parser * parser , ...)
1479+ {
1480+ int retval ;
1481+ va_list va ;
1482+
1483+ if ((kwnames != NULL && !PyTuple_Check (kwnames )) ||
1484+ parser == NULL )
1485+ {
1486+ PyErr_BadInternalCall ();
1487+ return 0 ;
1488+ }
1489+
1490+ va_start (va , parser );
1491+ retval = vgetargskeywordsfast_impl (args , nargs , NULL , kwnames , parser , & va , 0 );
1492+ va_end (va );
1493+ return retval ;
1494+ }
1495+
1496+ int
1497+ _PyArg_ParseStack_SizeT (PyObject * * args , Py_ssize_t nargs , PyObject * kwnames ,
1498+ struct _PyArg_Parser * parser , ...)
1499+ {
1500+ int retval ;
1501+ va_list va ;
1502+
1503+ if ((kwnames != NULL && !PyTuple_Check (kwnames )) ||
1504+ parser == NULL )
1505+ {
1506+ PyErr_BadInternalCall ();
1507+ return 0 ;
1508+ }
1509+
1510+ va_start (va , parser );
1511+ retval = vgetargskeywordsfast_impl (args , nargs , NULL , kwnames , parser , & va , FLAG_SIZE_T );
1512+ va_end (va );
1513+ return retval ;
1514+ }
1515+
14721516
14731517int
14741518_PyArg_VaParseTupleAndKeywordsFast (PyObject * args , PyObject * keywords ,
@@ -1899,10 +1943,37 @@ parser_clear(struct _PyArg_Parser *parser)
18991943 Py_CLEAR (parser -> kwtuple );
19001944}
19011945
1946+ static PyObject *
1947+ find_keyword (PyObject * kwnames , PyObject * * kwstack , PyObject * key )
1948+ {
1949+ Py_ssize_t i , nkwargs ;
1950+
1951+ nkwargs = PyTuple_GET_SIZE (kwnames );
1952+ for (i = 0 ; i < nkwargs ; i ++ ) {
1953+ PyObject * kwname = PyTuple_GET_ITEM (kwnames , i );
1954+
1955+ /* ptr==ptr should match in most cases since keyword keys
1956+ should be interned strings */
1957+ if (kwname == key ) {
1958+ return kwstack [i ];
1959+ }
1960+ if (!PyUnicode_Check (kwname )) {
1961+ /* ignore non-string keyword keys:
1962+ an error will be raised above */
1963+ continue ;
1964+ }
1965+ if (_PyUnicode_EQ (kwname , key )) {
1966+ return kwstack [i ];
1967+ }
1968+ }
1969+ return NULL ;
1970+ }
1971+
19021972static int
1903- vgetargskeywordsfast (PyObject * args , PyObject * keywords ,
1904- struct _PyArg_Parser * parser ,
1905- va_list * p_va , int flags )
1973+ vgetargskeywordsfast_impl (PyObject * * args , Py_ssize_t nargs ,
1974+ PyObject * keywords , PyObject * kwnames ,
1975+ struct _PyArg_Parser * parser ,
1976+ va_list * p_va , int flags )
19061977{
19071978 PyObject * kwtuple ;
19081979 char msgbuf [512 ];
@@ -1911,17 +1982,20 @@ vgetargskeywordsfast(PyObject *args, PyObject *keywords,
19111982 const char * msg ;
19121983 PyObject * keyword ;
19131984 int i , pos , len ;
1914- Py_ssize_t nargs , nkeywords ;
1985+ Py_ssize_t nkeywords ;
19151986 PyObject * current_arg ;
19161987 freelistentry_t static_entries [STATIC_FREELIST_ENTRIES ];
19171988 freelist_t freelist ;
1989+ PyObject * * kwstack = NULL ;
19181990
19191991 freelist .entries = static_entries ;
19201992 freelist .first_available = 0 ;
19211993 freelist .entries_malloced = 0 ;
19221994
1923- assert (args != NULL && PyTuple_Check (args ));
19241995 assert (keywords == NULL || PyDict_Check (keywords ));
1996+ assert (kwnames == NULL || PyTuple_Check (kwnames ));
1997+ assert ((keywords != NULL || kwnames != NULL )
1998+ || (keywords == NULL && kwnames == NULL ));
19251999 assert (parser != NULL );
19262000 assert (p_va != NULL );
19272001
@@ -1942,8 +2016,16 @@ vgetargskeywordsfast(PyObject *args, PyObject *keywords,
19422016 freelist .entries_malloced = 1 ;
19432017 }
19442018
1945- nargs = PyTuple_GET_SIZE (args );
1946- nkeywords = (keywords == NULL ) ? 0 : PyDict_Size (keywords );
2019+ if (keywords != NULL ) {
2020+ nkeywords = PyDict_Size (keywords );
2021+ }
2022+ else if (kwnames != NULL ) {
2023+ nkeywords = PyTuple_GET_SIZE (kwnames );
2024+ kwstack = args + nargs ;
2025+ }
2026+ else {
2027+ nkeywords = 0 ;
2028+ }
19472029 if (nargs + nkeywords > len ) {
19482030 PyErr_Format (PyExc_TypeError ,
19492031 "%s%s takes at most %d argument%s (%zd given)" ,
@@ -1976,9 +2058,14 @@ vgetargskeywordsfast(PyObject *args, PyObject *keywords,
19762058
19772059 current_arg = NULL ;
19782060 if (nkeywords && i >= pos ) {
1979- current_arg = PyDict_GetItem (keywords , keyword );
1980- if (!current_arg && PyErr_Occurred ()) {
1981- return cleanreturn (0 , & freelist );
2061+ if (keywords != NULL ) {
2062+ current_arg = PyDict_GetItem (keywords , keyword );
2063+ if (!current_arg && PyErr_Occurred ()) {
2064+ return cleanreturn (0 , & freelist );
2065+ }
2066+ }
2067+ else {
2068+ current_arg = find_keyword (kwnames , kwstack , keyword );
19822069 }
19832070 }
19842071 if (current_arg ) {
@@ -1993,7 +2080,7 @@ vgetargskeywordsfast(PyObject *args, PyObject *keywords,
19932080 }
19942081 }
19952082 else if (i < nargs ) {
1996- current_arg = PyTuple_GET_ITEM ( args , i ) ;
2083+ current_arg = args [ i ] ;
19972084 }
19982085
19992086 if (current_arg ) {
@@ -2040,31 +2127,74 @@ vgetargskeywordsfast(PyObject *args, PyObject *keywords,
20402127
20412128 /* make sure there are no extraneous keyword arguments */
20422129 if (nkeywords > 0 ) {
2043- PyObject * key , * value ;
2044- Py_ssize_t pos = 0 ;
2045- while (PyDict_Next (keywords , & pos , & key , & value )) {
2046- int match ;
2047- if (!PyUnicode_Check (key )) {
2048- PyErr_SetString (PyExc_TypeError ,
2049- "keywords must be strings" );
2050- return cleanreturn (0 , & freelist );
2130+ if (keywords != NULL ) {
2131+ PyObject * key , * value ;
2132+ Py_ssize_t pos = 0 ;
2133+ while (PyDict_Next (keywords , & pos , & key , & value )) {
2134+ int match ;
2135+ if (!PyUnicode_Check (key )) {
2136+ PyErr_SetString (PyExc_TypeError ,
2137+ "keywords must be strings" );
2138+ return cleanreturn (0 , & freelist );
2139+ }
2140+ match = PySequence_Contains (kwtuple , key );
2141+ if (match <= 0 ) {
2142+ if (!match ) {
2143+ PyErr_Format (PyExc_TypeError ,
2144+ "'%U' is an invalid keyword "
2145+ "argument for this function" ,
2146+ key );
2147+ }
2148+ return cleanreturn (0 , & freelist );
2149+ }
20512150 }
2052- match = PySequence_Contains (kwtuple , key );
2053- if (match <= 0 ) {
2054- if (!match ) {
2055- PyErr_Format (PyExc_TypeError ,
2056- "'%U' is an invalid keyword "
2057- "argument for this function" ,
2058- key );
2151+ }
2152+ else {
2153+ Py_ssize_t j , nkwargs ;
2154+
2155+ nkwargs = PyTuple_GET_SIZE (kwnames );
2156+ for (j = 0 ; j < nkwargs ; j ++ ) {
2157+ PyObject * key = PyTuple_GET_ITEM (kwnames , j );
2158+ int match ;
2159+
2160+ if (!PyUnicode_Check (key )) {
2161+ PyErr_SetString (PyExc_TypeError ,
2162+ "keywords must be strings" );
2163+ return cleanreturn (0 , & freelist );
2164+ }
2165+
2166+ match = PySequence_Contains (kwtuple , key );
2167+ if (match <= 0 ) {
2168+ if (!match ) {
2169+ PyErr_Format (PyExc_TypeError ,
2170+ "'%U' is an invalid keyword "
2171+ "argument for this function" ,
2172+ key );
2173+ }
2174+ return cleanreturn (0 , & freelist );
20592175 }
2060- return cleanreturn (0 , & freelist );
20612176 }
20622177 }
20632178 }
20642179
20652180 return cleanreturn (1 , & freelist );
20662181}
20672182
2183+ static int
2184+ vgetargskeywordsfast (PyObject * args , PyObject * keywords ,
2185+ struct _PyArg_Parser * parser , va_list * p_va , int flags )
2186+ {
2187+ PyObject * * stack ;
2188+ Py_ssize_t nargs ;
2189+
2190+ assert (args != NULL && PyTuple_Check (args ));
2191+
2192+ stack = & PyTuple_GET_ITEM (args , 0 );
2193+ nargs = PyTuple_GET_SIZE (args );
2194+ return vgetargskeywordsfast_impl (stack , nargs , keywords , NULL ,
2195+ parser , p_va , flags );
2196+ }
2197+
20682198
20692199static const char *
20702200skipitem (const char * * p_format , va_list * p_va , int flags )
0 commit comments