| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent a9efb2f commit f0ccbbb
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -58,10 +58,13 @@ typedef struct _PyArg_Parser { | |||
| 58 | 58 | } _PyArg_Parser; | |
| 59 | 59 | #ifdef PY_SSIZE_T_CLEAN | |
| 60 | 60 | #define _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT | |
| 61 | + #define _PyArg_ParseStack _PyArg_ParseStack_SizeT | ||
| 61 | 62 | #define _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT | |
| 62 | 63 | #endif | |
| 63 | 64 | PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *, | |
| 64 | 65 | struct _PyArg_Parser *, ...); | |
| 66 | + PyAPI_FUNC(int) _PyArg_ParseStack(PyObject **args, Py_ssize_t nargs, PyObject *kwnames, | ||
| 67 | + struct _PyArg_Parser *, ...); | ||
| 65 | 68 | PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *, | |
| 66 | 69 | struct _PyArg_Parser *, va_list); | |
| 67 | 70 | void _PyArg_Fini(void); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -79,6 +79,10 @@ static int vgetargskeywords(PyObject *, PyObject *, | |||
| 79 | 79 | const char *, char **, va_list *, int); | |
| 80 | 80 | static int vgetargskeywordsfast(PyObject *, PyObject *, | |
| 81 | 81 | 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); | ||
| 82 | 86 | static const char *skipitem(const char **, va_list *, int); | |
| 83 | 87 | ||
| 84 | 88 | int | |
@@ -1469,6 +1473,46 @@ _PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords, | |||
| 1469 | 1473 | return retval; | |
| 1470 | 1474 | } | |
| 1471 | 1475 | ||
| 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 | + | ||
| 1472 | 1516 | ||
| 1473 | 1517 | int | |
| 1474 | 1518 | _PyArg_VaParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords, | |
@@ -1899,10 +1943,37 @@ parser_clear(struct _PyArg_Parser *parser) | |||
| 1899 | 1943 | Py_CLEAR(parser->kwtuple); | |
| 1900 | 1944 | } | |
| 1901 | 1945 | ||
| 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 | + | ||
| 1902 | 1972 | static 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) | ||
| 1906 | 1977 | { | |
| 1907 | 1978 | PyObject *kwtuple; | |
| 1908 | 1979 | char msgbuf[512]; | |
@@ -1911,17 +1982,20 @@ vgetargskeywordsfast(PyObject *args, PyObject *keywords, | |||
| 1911 | 1982 | const char *msg; | |
| 1912 | 1983 | PyObject *keyword; | |
| 1913 | 1984 | int i, pos, len; | |
| 1914 | - Py_ssize_t nargs, nkeywords; | ||
| 1985 | + Py_ssize_t nkeywords; | ||
| 1915 | 1986 | PyObject *current_arg; | |
| 1916 | 1987 | freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; | |
| 1917 | 1988 | freelist_t freelist; | |
| 1989 | + PyObject **kwstack = NULL; | ||
| 1918 | 1990 | ||
| 1919 | 1991 | freelist.entries = static_entries; | |
| 1920 | 1992 | freelist.first_available = 0; | |
| 1921 | 1993 | freelist.entries_malloced = 0; | |
| 1922 | 1994 | ||
| 1923 | - assert(args != NULL && PyTuple_Check(args)); | ||
| 1924 | 1995 | assert(keywords == NULL || PyDict_Check(keywords)); | |
| 1996 | + assert(kwnames == NULL || PyTuple_Check(kwnames)); | ||
| 1997 | + assert((keywords != NULL || kwnames != NULL) | ||
| 1998 | + || (keywords == NULL && kwnames == NULL)); | ||
| 1925 | 1999 | assert(parser != NULL); | |
| 1926 | 2000 | assert(p_va != NULL); | |
| 1927 | 2001 | ||
@@ -1942,8 +2016,16 @@ vgetargskeywordsfast(PyObject *args, PyObject *keywords, | |||
| 1942 | 2016 | freelist.entries_malloced = 1; | |
| 1943 | 2017 | } | |
| 1944 | 2018 | ||
| 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 | + } | ||
| 1947 | 2029 | if (nargs + nkeywords > len) { | |
| 1948 | 2030 | PyErr_Format(PyExc_TypeError, | |
| 1949 | 2031 | "%s%s takes at most %d argument%s (%zd given)", | |
@@ -1976,9 +2058,14 @@ vgetargskeywordsfast(PyObject *args, PyObject *keywords, | |||
| 1976 | 2058 | ||
| 1977 | 2059 | current_arg = NULL; | |
| 1978 | 2060 | 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); | ||
| 1982 | 2069 | } | |
| 1983 | 2070 | } | |
| 1984 | 2071 | if (current_arg) { | |
@@ -1993,7 +2080,7 @@ vgetargskeywordsfast(PyObject *args, PyObject *keywords, | |||
| 1993 | 2080 | } | |
| 1994 | 2081 | } | |
| 1995 | 2082 | else if (i < nargs) { | |
| 1996 | - current_arg = PyTuple_GET_ITEM(args, i); | ||
| 2083 | + current_arg = args[i]; | ||
| 1997 | 2084 | } | |
| 1998 | 2085 | ||
| 1999 | 2086 | if (current_arg) { | |
@@ -2040,31 +2127,74 @@ vgetargskeywordsfast(PyObject *args, PyObject *keywords, | |||
| 2040 | 2127 | ||
| 2041 | 2128 | /* make sure there are no extraneous keyword arguments */ | |
| 2042 | 2129 | 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 | + } | ||
| 2051 | 2150 | } | |
| 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); | ||
| 2059 | 2175 | } | |
| 2060 | - return cleanreturn(0, &freelist); | ||
| 2061 | 2176 | } | |
| 2062 | 2177 | } | |
| 2063 | 2178 | } | |
| 2064 | 2179 | ||
| 2065 | 2180 | return cleanreturn(1, &freelist); | |
| 2066 | 2181 | } | |
| 2067 | 2182 | ||
| 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 | + | ||
| 2068 | 2198 | ||
| 2069 | 2199 | static const char * | |
| 2070 | 2200 | skipitem(const char **p_format, va_list *p_va, int flags) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -705,6 +705,11 @@ def output_templates(self, f): | |||
| 705 | 705 | {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs) | |
| 706 | 706 | """) | |
| 707 | 707 | ||
| 708 | + parser_prototype_fastcall = normalize_snippet(""" | ||
| 709 | + static PyObject * | ||
| 710 | + {c_basename}({self_type}{self_name}, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) | ||
| 711 | + """) | ||
| 712 | + | ||
| 708 | 713 | parser_prototype_varargs = normalize_snippet(""" | |
| 709 | 714 | static PyObject * | |
| 710 | 715 | {c_basename}({self_type}{self_name}, PyObject *args) | |
@@ -845,6 +850,19 @@ def insert_keywords(s): | |||
| 845 | 850 | }} | |
| 846 | 851 | """, indent=4)) | |
| 847 | 852 | ||
| 853 | + elif not new_or_init: | ||
| 854 | + flags = "METH_FASTCALL" | ||
| 855 | + | ||
| 856 | + parser_prototype = parser_prototype_fastcall | ||
| 857 | + | ||
| 858 | + body = normalize_snippet(""" | ||
| 859 | + if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser, | ||
| 860 | + {parse_arguments})) {{ | ||
| 861 | + goto exit; | ||
| 862 | + }} | ||
| 863 | + """, indent=4) | ||
| 864 | + parser_definition = parser_body(parser_prototype, body) | ||
| 865 | + parser_definition = insert_keywords(parser_definition) | ||
| 848 | 866 | else: | |
| 849 | 867 | # positional-or-keyword arguments | |
| 850 | 868 | flags = "METH_VARARGS|METH_KEYWORDS" | |
| Back | FazBrowse Home | New Git URL |
0 commit comments