* Generic helper for argument parsing * * See macro version for an example pattern of how to use this function. * * @param funcname * @param cache * @param args Python passed args (METH_FASTCALL) * @param len_args * @param kwnames * @param ... List of arguments (see macro version). * * @return Returns 0 on success and -1 on failure. */
| 265 | * @return Returns 0 on success and -1 on failure. |
| 266 | */ |
| 267 | NPY_NO_EXPORT int |
| 268 | _npy_parse_arguments(const char *funcname, |
| 269 | /* cache_ptr is a NULL initialized persistent storage for data */ |
| 270 | _NpyArgParserCache *cache, |
| 271 | PyObject *const *args, Py_ssize_t len_args, PyObject *kwnames, |
| 272 | /* ... is NULL, NULL, NULL terminated: name, converter, value */ |
| 273 | ...) |
| 274 | { |
| 275 | if (NPY_UNLIKELY(cache->npositional == -1)) { |
| 276 | va_list va; |
| 277 | va_start(va, kwnames); |
| 278 | |
| 279 | int res = initialize_keywords(funcname, cache, va); |
| 280 | va_end(va); |
| 281 | if (res < 0) { |
| 282 | return -1; |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | if (NPY_UNLIKELY(len_args > cache->npositional)) { |
| 287 | return raise_incorrect_number_of_positional_args( |
| 288 | funcname, cache, len_args); |
| 289 | } |
| 290 | |
| 291 | /* NOTE: Could remove the limit but too many kwargs are slow anyway. */ |
| 292 | PyObject *all_arguments[NPY_MAXARGS]; |
| 293 | |
| 294 | for (Py_ssize_t i = 0; i < len_args; i++) { |
| 295 | all_arguments[i] = args[i]; |
| 296 | } |
| 297 | |
| 298 | /* Without kwargs, do not iterate all converters. */ |
| 299 | int max_nargs = (int)len_args; |
| 300 | Py_ssize_t len_kwargs = 0; |
| 301 | |
| 302 | /* If there are any kwargs, first handle them */ |
| 303 | if (NPY_LIKELY(kwnames != NULL)) { |
| 304 | len_kwargs = PyTuple_GET_SIZE(kwnames); |
| 305 | max_nargs = cache->nargs; |
| 306 | |
| 307 | for (int i = len_args; i < cache->nargs; i++) { |
| 308 | all_arguments[i] = NULL; |
| 309 | } |
| 310 | |
| 311 | for (Py_ssize_t i = 0; i < len_kwargs; i++) { |
| 312 | PyObject *key = PyTuple_GET_ITEM(kwnames, i); |
| 313 | PyObject *value = args[i + len_args]; |
| 314 | PyObject *const *name; |
| 315 | |
| 316 | /* Super-fast path, check identity: */ |
| 317 | for (name = cache->kw_strings; *name != NULL; name++) { |
| 318 | if (*name == key) { |
| 319 | break; |
| 320 | } |
| 321 | } |
| 322 | if (NPY_UNLIKELY(*name == NULL)) { |
| 323 | /* Slow fallback, if identity checks failed for some reason */ |
| 324 | for (name = cache->kw_strings; *name != NULL; name++) { |
nothing calls this directly
no test coverage detected