Mercurial > hgrepos > Python > libs > ConfigMix
comparison configmix/_speedups.c @ 552:39e5d07d8dbc
Provide a C implementation of configmix.config._split_filters.
This is needed as precondition for implementation interpolate_variables in
C also.
Currently the speedup is not measurable but it does not hurt also.
Also provide some unit-tests for _split_filters().
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Sun, 02 Jan 2022 20:40:09 +0100 |
| parents | 79db28e879f8 |
| children | 9d2bd411f5c5 |
comparison
equal
deleted
inserted
replaced
| 551:4c968c5cfce6 | 552:39e5d07d8dbc |
|---|---|
| 20 */ | 20 */ |
| 21 struct speedups_state { | 21 struct speedups_state { |
| 22 PyObject *DOT; | 22 PyObject *DOT; |
| 23 PyObject *QUOTE; | 23 PyObject *QUOTE; |
| 24 PyObject *NS_SEPARATOR; | 24 PyObject *NS_SEPARATOR; |
| 25 PyObject *FILTER_SEPARATOR; | |
| 25 PyObject *EMPTY_STR; | 26 PyObject *EMPTY_STR; |
| 26 PyObject *QUOTE_MAP; | 27 PyObject *QUOTE_MAP; |
| 27 }; | 28 }; |
| 28 | 29 |
| 29 | 30 |
| 249 #endif /* Py_LIMITED_API */ | 250 #endif /* Py_LIMITED_API */ |
| 250 | 251 |
| 251 | 252 |
| 252 static | 253 static |
| 253 PyObject * | 254 PyObject * |
| 254 _fast_unquote(PyObject *self, PyObject *s, Py_ssize_t s_len, struct speedups_state *sstate) | 255 _fast_unquote(PyObject *s, Py_ssize_t s_len, PyObject *self, struct speedups_state *sstate) |
| 255 { | 256 { |
| 256 Py_ssize_t find; | 257 Py_ssize_t find; |
| 257 Py_ssize_t parts_len; | 258 Py_ssize_t parts_len; |
| 258 PyObject *res; | 259 PyObject *res; |
| 259 PyObject *res_parts = NULL; | 260 PyObject *res_parts = NULL; |
| 395 | 396 |
| 396 static | 397 static |
| 397 PyObject * | 398 PyObject * |
| 398 fast_unquote(PyObject *self, PyObject *s) | 399 fast_unquote(PyObject *self, PyObject *s) |
| 399 { | 400 { |
| 400 return _fast_unquote(self, s, -1, NULL); | 401 return _fast_unquote(s, -1, self, NULL); |
| 401 } | 402 } |
| 402 | 403 |
| 403 | 404 |
| 404 static | 405 static |
| 405 PyObject * | 406 PyObject * |
| 497 if (res == NULL) { | 498 if (res == NULL) { |
| 498 goto error; | 499 goto error; |
| 499 } | 500 } |
| 500 for (i=0; i < parts_len; i++) { | 501 for (i=0; i < parts_len; i++) { |
| 501 o = PyList_GetItem(parts, i); /* borrowed */ | 502 o = PyList_GetItem(parts, i); /* borrowed */ |
| 502 u = _fast_unquote(self, o, -1, sstate); | 503 u = _fast_unquote(o, -1, NULL, sstate); |
| 503 if (u == NULL) { | 504 if (u == NULL) { |
| 504 goto error; | 505 goto error; |
| 505 } | 506 } |
| 506 PyTuple_SetItem(res, i, u); /* steals */ | 507 PyTuple_SetItem(res, i, u); /* steals */ |
| 507 } | 508 } |
| 511 | 512 |
| 512 error: | 513 error: |
| 513 Py_XDECREF(parts); | 514 Py_XDECREF(parts); |
| 514 Py_XDECREF(res); | 515 Py_XDECREF(res); |
| 515 return NULL; | 516 return NULL; |
| 517 } | |
| 518 | |
| 519 | |
| 520 static | |
| 521 PyObject * | |
| 522 _fast_split_filters(PyObject *varname, PyObject *self, struct speedups_state *sstate) | |
| 523 { | |
| 524 Py_ssize_t varname_len; | |
| 525 Py_ssize_t sep; | |
| 526 PyObject *res = NULL; | |
| 527 PyObject *filters = NULL; | |
| 528 PyObject *name = NULL; | |
| 529 PyObject *tmp; | |
| 530 | |
| 531 varname_len = PyUnicode_GetLength(varname); | |
| 532 if (varname_len < 0) { | |
| 533 return NULL; | |
| 534 } | |
| 535 if (varname_len == 0) { | |
| 536 sep = -1; | |
| 537 } | |
| 538 else { | |
| 539 sep = PyUnicode_FindChar(varname, '|', 0, varname_len, 1); | |
| 540 if (sep == -2) { | |
| 541 return NULL; | |
| 542 } | |
| 543 } | |
| 544 if (sep == -1) { | |
| 545 res = PyTuple_New(2); | |
| 546 if (res == NULL) { | |
| 547 goto error; | |
| 548 } | |
| 549 Py_INCREF(varname); /* because PyTuple_SetItem steals */ | |
| 550 PyTuple_SetItem(res, 0, varname); /* steals */ | |
| 551 filters = PyList_New(0); | |
| 552 if (filters == NULL) { | |
| 553 goto error; | |
| 554 } | |
| 555 PyTuple_SetItem(res, 1, filters); /* steals */ | |
| 556 return res; | |
| 557 } | |
| 558 name = PyUnicode_Substring(varname, 0, sep); | |
| 559 if (name == NULL) { | |
| 560 goto error; | |
| 561 } | |
| 562 tmp = PyObject_CallMethod(name, "rstrip", NULL); | |
| 563 if (tmp == NULL) { | |
| 564 goto error; | |
| 565 } | |
| 566 Py_DECREF(name); | |
| 567 name = tmp; | |
| 568 | |
| 569 filters = PyUnicode_Substring(varname, sep+1, varname_len); | |
| 570 if (filters == NULL) { | |
| 571 goto error; | |
| 572 } | |
| 573 tmp = PyObject_CallMethod(filters, "strip", NULL); | |
| 574 if (tmp == NULL) { | |
| 575 goto error; | |
| 576 } | |
| 577 Py_DECREF(filters); | |
| 578 filters = tmp; | |
| 579 | |
| 580 if (PyObject_Not(filters)) { | |
| 581 Py_DECREF(filters); filters = NULL; | |
| 582 | |
| 583 res = PyTuple_New(2); | |
| 584 if (res == NULL) { | |
| 585 goto error; | |
| 586 } | |
| 587 PyTuple_SetItem(res, 0, name); /* steals */ | |
| 588 name = NULL; /* no ownership any more */ | |
| 589 filters = PyList_New(0); | |
| 590 if (filters == NULL) { | |
| 591 goto error; | |
| 592 } | |
| 593 PyTuple_SetItem(res, 1, filters); /* steals */ | |
| 594 return res; | |
| 595 } | |
| 596 | |
| 597 if (sstate == NULL) { | |
| 598 sstate = PyModule_GetState(self); | |
| 599 if (sstate == NULL) { | |
| 600 PyErr_SetString(PyExc_RuntimeError, "no module state available"); | |
| 601 goto error; | |
| 602 } | |
| 603 } | |
| 604 | |
| 605 tmp = PyUnicode_Split(filters, sstate->FILTER_SEPARATOR, -1); | |
| 606 if (tmp == NULL) { | |
| 607 goto error; | |
| 608 } | |
| 609 Py_DECREF(filters); | |
| 610 filters = tmp; | |
| 611 | |
| 612 res = PyTuple_New(2); | |
| 613 if (res == NULL) { | |
| 614 goto error; | |
| 615 } | |
| 616 PyTuple_SetItem(res, 0, name); /* steals -- ownership changed */ | |
| 617 PyTuple_SetItem(res, 1, filters); /* steals -- ownership changed */ | |
| 618 return res; | |
| 619 | |
| 620 error: | |
| 621 Py_XDECREF(res); | |
| 622 Py_XDECREF(filters); | |
| 623 Py_XDECREF(name); | |
| 624 return NULL; | |
| 625 } | |
| 626 | |
| 627 | |
| 628 static | |
| 629 PyObject * | |
| 630 fast_split_filters(PyObject *self, PyObject *varname) | |
| 631 { | |
| 632 return _fast_split_filters(varname, self, NULL); | |
| 516 } | 633 } |
| 517 | 634 |
| 518 | 635 |
| 519 static | 636 static |
| 520 PyObject * | 637 PyObject * |
| 553 o1 = PyUnicode_Substring(varname, 0, ns_idx); | 670 o1 = PyUnicode_Substring(varname, 0, ns_idx); |
| 554 if (o1 == NULL) { | 671 if (o1 == NULL) { |
| 555 Py_DECREF(res); | 672 Py_DECREF(res); |
| 556 return NULL; | 673 return NULL; |
| 557 } | 674 } |
| 558 o2 = _fast_unquote(self, o1, ns_idx, NULL); | 675 o2 = _fast_unquote(o1, ns_idx, self, NULL); |
| 559 if (o2 == NULL) { | 676 if (o2 == NULL) { |
| 560 Py_DECREF(o1); | 677 Py_DECREF(o1); |
| 561 Py_DECREF(res); | 678 Py_DECREF(res); |
| 562 return NULL; | 679 return NULL; |
| 563 } | 680 } |
| 575 | 692 |
| 576 static struct PyMethodDef speedups_methods[] = { | 693 static struct PyMethodDef speedups_methods[] = { |
| 577 {"fast_unquote", fast_unquote, METH_O, PyDoc_STR("C-implementation of configmix.unquote")}, | 694 {"fast_unquote", fast_unquote, METH_O, PyDoc_STR("C-implementation of configmix.unquote")}, |
| 578 {"fast_quote", fast_quote, METH_O, PyDoc_STR("C-implementation of configmix.quote")}, | 695 {"fast_quote", fast_quote, METH_O, PyDoc_STR("C-implementation of configmix.quote")}, |
| 579 {"fast_pathstr2path", fast_pathstr2path, METH_O, PyDoc_STR("C-implementation of configmix.pathstr2path")}, | 696 {"fast_pathstr2path", fast_pathstr2path, METH_O, PyDoc_STR("C-implementation of configmix.pathstr2path")}, |
| 697 {"_fast_split_filters", fast_split_filters, METH_O, PyDoc_STR("C-implementation of configmix.config._split_filters")}, | |
| 580 {"_fast_split_ns", fast_split_ns, METH_O, PyDoc_STR("C-implementation of configmix.config._split_ns")}, | 698 {"_fast_split_ns", fast_split_ns, METH_O, PyDoc_STR("C-implementation of configmix.config._split_ns")}, |
| 581 {NULL, NULL, 0, NULL} | 699 {NULL, NULL, 0, NULL} |
| 582 }; | 700 }; |
| 583 | 701 |
| 584 #define STRINGIFY(s) #s | 702 #define STRINGIFY(s) #s |
| 618 sstate->NS_SEPARATOR = PyUnicode_FromStringAndSize(":", 1); | 736 sstate->NS_SEPARATOR = PyUnicode_FromStringAndSize(":", 1); |
| 619 if (sstate->NS_SEPARATOR == NULL) { | 737 if (sstate->NS_SEPARATOR == NULL) { |
| 620 return -1; | 738 return -1; |
| 621 } | 739 } |
| 622 PyUnicode_InternInPlace(&(sstate->NS_SEPARATOR)); | 740 PyUnicode_InternInPlace(&(sstate->NS_SEPARATOR)); |
| 741 | |
| 742 sstate->FILTER_SEPARATOR = PyUnicode_FromStringAndSize("|", 1); | |
| 743 if (sstate->FILTER_SEPARATOR == NULL) { | |
| 744 return -1; | |
| 745 } | |
| 746 PyUnicode_InternInPlace(&(sstate->FILTER_SEPARATOR)); | |
| 623 | 747 |
| 624 sstate->EMPTY_STR = PyUnicode_FromStringAndSize("", 0); | 748 sstate->EMPTY_STR = PyUnicode_FromStringAndSize("", 0); |
| 625 if (sstate->EMPTY_STR == NULL) { | 749 if (sstate->EMPTY_STR == NULL) { |
| 626 return -1; | 750 return -1; |
| 627 } | 751 } |
| 656 | 780 |
| 657 if (sstate != NULL) { | 781 if (sstate != NULL) { |
| 658 Py_VISIT(sstate->DOT); | 782 Py_VISIT(sstate->DOT); |
| 659 Py_VISIT(sstate->QUOTE); | 783 Py_VISIT(sstate->QUOTE); |
| 660 Py_VISIT(sstate->NS_SEPARATOR); | 784 Py_VISIT(sstate->NS_SEPARATOR); |
| 785 Py_VISIT(sstate->FILTER_SEPARATOR); | |
| 661 Py_VISIT(sstate->EMPTY_STR); | 786 Py_VISIT(sstate->EMPTY_STR); |
| 662 Py_VISIT(sstate->QUOTE_MAP); | 787 Py_VISIT(sstate->QUOTE_MAP); |
| 663 } | 788 } |
| 664 return 0; | 789 return 0; |
| 665 } | 790 } |
| 673 | 798 |
| 674 if (sstate != NULL) { | 799 if (sstate != NULL) { |
| 675 Py_CLEAR(sstate->DOT); | 800 Py_CLEAR(sstate->DOT); |
| 676 Py_CLEAR(sstate->QUOTE); | 801 Py_CLEAR(sstate->QUOTE); |
| 677 Py_CLEAR(sstate->NS_SEPARATOR); | 802 Py_CLEAR(sstate->NS_SEPARATOR); |
| 803 Py_CLEAR(sstate->FILTER_SEPARATOR); | |
| 678 Py_CLEAR(sstate->EMPTY_STR); | 804 Py_CLEAR(sstate->EMPTY_STR); |
| 679 Py_CLEAR(sstate->QUOTE_MAP); | 805 Py_CLEAR(sstate->QUOTE_MAP); |
| 680 } | 806 } |
| 681 return 0; | 807 return 0; |
| 682 } | 808 } |
