comparison configmix/_speedups.c @ 705:0485a033c95d

FIX: Parsing a filter chain for the new filter-only expansions: parse them backwards and use "," as filter-chain separator here. This allows using filter chains in filter-only expansions also.
author Franz Glasner <fzglas.hg@dom66.de>
date Tue, 15 Aug 2023 09:34:49 +0200
parents 457ef358c1a0
children 10fbc23b4dba
comparison
equal deleted inserted replaced
704:457ef358c1a0 705:0485a033c95d
23 struct speedups_state { 23 struct speedups_state {
24 PyObject *DOT; 24 PyObject *DOT;
25 PyObject *QUOTE; 25 PyObject *QUOTE;
26 PyObject *NS_SEPARATOR; 26 PyObject *NS_SEPARATOR;
27 PyObject *FILTER_SEPARATOR; 27 PyObject *FILTER_SEPARATOR;
28 PyObject *FILTER_SEPARATOR_REV;
28 PyObject *EMPTY_FILTER; 29 PyObject *EMPTY_FILTER;
29 PyObject *NONE_FILTER; 30 PyObject *NONE_FILTER;
30 PyObject *EMPTY_STR; 31 PyObject *EMPTY_STR;
31 PyObject *QUOTE_MAP; 32 PyObject *QUOTE_MAP;
32 PyObject *MISSING; 33 PyObject *MISSING;
604 } 605 }
605 606
606 607
607 static 608 static
608 PyObject * 609 PyObject *
609 _fast_split_filters(PyObject *varname, PyObject *self, struct speedups_state *sstate) 610 _fast_split_filters(PyObject *varname, PyObject *self, Py_ssize_t direction, struct speedups_state *sstate)
610 { 611 {
611 Py_ssize_t varname_len; 612 Py_ssize_t varname_len;
612 Py_ssize_t sep; 613 Py_ssize_t sep;
613 PyObject *res = NULL; 614 PyObject *res = NULL;
614 PyObject *filters = NULL; 615 PyObject *filters = NULL;
621 } 622 }
622 if (varname_len == 0) { 623 if (varname_len == 0) {
623 sep = -1; 624 sep = -1;
624 } 625 }
625 else { 626 else {
626 sep = PyUnicode_FindChar(varname, '|', 0, varname_len, 1); 627 sep = PyUnicode_FindChar(varname, '|', 0, varname_len, (int)direction);
627 if (sep == -2) { 628 if (sep == -2) {
628 return NULL; 629 return NULL;
629 } 630 }
630 } 631 }
631 if (sep == -1) { 632 if (sep == -1) {
680 PyErr_SetString(PyExc_RuntimeError, "no module state available"); 681 PyErr_SetString(PyExc_RuntimeError, "no module state available");
681 goto error; 682 goto error;
682 } 683 }
683 } 684 }
684 685
685 tmp = PyUnicode_Split(filters, sstate->FILTER_SEPARATOR, -1); 686 if (direction == 1) {
687 tmp = PyUnicode_Split(filters, sstate->FILTER_SEPARATOR, -1);
688 }
689 else {
690 tmp = PyUnicode_Split(filters, sstate->FILTER_SEPARATOR_REV, -1);
691 }
686 if (tmp == NULL) { 692 if (tmp == NULL) {
687 goto error; 693 goto error;
688 } 694 }
689 py_transfer_owned(&filters, &tmp); 695 py_transfer_owned(&filters, &tmp);
690 696
704 } 710 }
705 711
706 712
707 static 713 static
708 PyObject * 714 PyObject *
709 fast_split_filters(PyObject *self, PyObject *varname) 715 fast_split_filters(PyObject *self, PyObject *args)
710 { 716 {
711 return _fast_split_filters(varname, self, NULL); 717 PyObject *varname;
718 PyObject *direction_obj;
719 Py_ssize_t direction;
720
721 if (!PyArg_UnpackTuple(args, "fast_split_filters", 2, 2, &varname, &direction_obj)) {
722 return NULL;
723 }
724 direction = PyNumber_AsSsize_t(direction_obj, PyExc_OverflowError);
725 if (direction == -1) {
726 if (PyErr_Occurred()) {
727 return NULL;
728 }
729 }
730 if ((direction == 1) || (direction == -1)) {
731 return _fast_split_filters(varname, self, direction, NULL);
732 }
733 else {
734 PyErr_SetString(PyExc_ValueError, "`direction' must be -1 or +1");
735 return NULL;
736 }
712 } 737 }
713 738
714 739
715 static 740 static
716 PyObject * 741 PyObject *
908 varname = PyUnicode_Substring(pb, 0, idx); 933 varname = PyUnicode_Substring(pb, 0, idx);
909 if (varname == NULL) { 934 if (varname == NULL) {
910 goto error; 935 goto error;
911 } 936 }
912 937
913 tmp = _fast_split_filters(varname, NULL, sstate); 938 tmp = _fast_split_filters(varname, NULL, 1, sstate);
914 if (tmp == NULL) { 939 if (tmp == NULL) {
915 goto error; 940 goto error;
916 } 941 }
917 if (PyTuple_Size(tmp) != 2) { 942 if (PyTuple_Size(tmp) != 2) {
918 py_clear_ref(&tmp); 943 py_clear_ref(&tmp);
1128 */ 1153 */
1129 tmp = PyUnicode_Substring(s, 3, s_len-3); 1154 tmp = PyUnicode_Substring(s, 3, s_len-3);
1130 if (tmp == NULL) { 1155 if (tmp == NULL) {
1131 return NULL; 1156 return NULL;
1132 } 1157 }
1133 filters = _fast_split_filters(tmp, NULL, sstate); 1158 filters = _fast_split_filters(tmp, NULL, -1, sstate);
1134 if (filters == NULL) { 1159 if (filters == NULL) {
1135 py_clear_ref(&tmp); 1160 py_clear_ref(&tmp);
1136 return NULL; 1161 return NULL;
1137 } 1162 }
1138 if (PyTuple_Size(filters) != 2) { 1163 if (PyTuple_Size(filters) != 2) {
1213 varname = PyUnicode_Substring(s, start+2, end); /* 2 == len(STARTTOK) */ 1238 varname = PyUnicode_Substring(s, start+2, end); /* 2 == len(STARTTOK) */
1214 if (varname == NULL) { 1239 if (varname == NULL) {
1215 goto error; 1240 goto error;
1216 } 1241 }
1217 1242
1218 tmp = _fast_split_filters(varname, NULL, sstate); 1243 tmp = _fast_split_filters(varname, NULL, 1, sstate);
1219 if (tmp == NULL) { 1244 if (tmp == NULL) {
1220 goto error; 1245 goto error;
1221 } 1246 }
1222 if (PyTuple_Size(tmp) != 2) { 1247 if (PyTuple_Size(tmp) != 2) {
1223 PyErr_SetString(PyExc_TypeError, "tuple of size 2 expected"); 1248 PyErr_SetString(PyExc_TypeError, "tuple of size 2 expected");
1707 1732
1708 static struct PyMethodDef speedups_methods[] = { 1733 static struct PyMethodDef speedups_methods[] = {
1709 {"fast_unquote", fast_unquote, METH_O, PyDoc_STR("C-implementation of configmix.unquote")}, 1734 {"fast_unquote", fast_unquote, METH_O, PyDoc_STR("C-implementation of configmix.unquote")},
1710 {"fast_quote", fast_quote, METH_O, PyDoc_STR("C-implementation of configmix.quote")}, 1735 {"fast_quote", fast_quote, METH_O, PyDoc_STR("C-implementation of configmix.quote")},
1711 {"fast_pathstr2path", fast_pathstr2path, METH_O, PyDoc_STR("C-implementation of configmix.pathstr2path")}, 1736 {"fast_pathstr2path", fast_pathstr2path, METH_O, PyDoc_STR("C-implementation of configmix.pathstr2path")},
1712 {"_fast_split_filters", fast_split_filters, METH_O, PyDoc_STR("C-implementation of configmix.config._split_filters")}, 1737 {"_fast_split_filters", fast_split_filters, METH_VARARGS, PyDoc_STR("C-implementation of configmix.config._split_filters")},
1713 {"_fast_split_ns", fast_split_ns, METH_O, PyDoc_STR("C-implementation of configmix.config._split_ns")}, 1738 {"_fast_split_ns", fast_split_ns, METH_O, PyDoc_STR("C-implementation of configmix.config._split_ns")},
1714 {"_fast_interpolate_variables", fast_interpolate_variables, METH_VARARGS, PyDoc_STR("C-implementation of configmix.config.Configuration.interpolate_variables")}, 1739 {"_fast_interpolate_variables", fast_interpolate_variables, METH_VARARGS, PyDoc_STR("C-implementation of configmix.config.Configuration.interpolate_variables")},
1715 {"_fast_getvarl", (PyCFunction)fast_getvarl, METH_VARARGS | METH_KEYWORDS, PyDoc_STR("C-Implementation of configmix.config.Configuration.getvarl")}, 1740 {"_fast_getvarl", (PyCFunction)fast_getvarl, METH_VARARGS | METH_KEYWORDS, PyDoc_STR("C-Implementation of configmix.config.Configuration.getvarl")},
1716 {"_fast_getvarl_s", (PyCFunction)fast_getvarl_s, METH_VARARGS | METH_KEYWORDS, PyDoc_STR("C-Implementation of configmix.config.Configuration.getvarl_s")}, 1741 {"_fast_getvarl_s", (PyCFunction)fast_getvarl_s, METH_VARARGS | METH_KEYWORDS, PyDoc_STR("C-Implementation of configmix.config.Configuration.getvarl_s")},
1717 {"_fast_getvar", fast_getvar, METH_VARARGS, PyDoc_STR("C-Implementation of configmix.config.Configuration.getvar")}, 1742 {"_fast_getvar", fast_getvar, METH_VARARGS, PyDoc_STR("C-Implementation of configmix.config.Configuration.getvar")},
1764 sstate->FILTER_SEPARATOR = PyUnicode_FromStringAndSize("|", 1); 1789 sstate->FILTER_SEPARATOR = PyUnicode_FromStringAndSize("|", 1);
1765 if (sstate->FILTER_SEPARATOR == NULL) { 1790 if (sstate->FILTER_SEPARATOR == NULL) {
1766 return -1; 1791 return -1;
1767 } 1792 }
1768 PyUnicode_InternInPlace(&(sstate->FILTER_SEPARATOR)); 1793 PyUnicode_InternInPlace(&(sstate->FILTER_SEPARATOR));
1794
1795 sstate->FILTER_SEPARATOR_REV = PyUnicode_FromStringAndSize(",", 1);
1796 if (sstate->FILTER_SEPARATOR_REV == NULL) {
1797 return -1;
1798 }
1799 PyUnicode_InternInPlace(&(sstate->FILTER_SEPARATOR_REV));
1769 1800
1770 sstate->EMPTY_FILTER = PyUnicode_FromStringAndSize("Empty", 5); 1801 sstate->EMPTY_FILTER = PyUnicode_FromStringAndSize("Empty", 5);
1771 if (sstate->EMPTY_FILTER == NULL) { 1802 if (sstate->EMPTY_FILTER == NULL) {
1772 return -1; 1803 return -1;
1773 } 1804 }
1846 if (sstate != NULL) { 1877 if (sstate != NULL) {
1847 Py_VISIT(sstate->DOT); 1878 Py_VISIT(sstate->DOT);
1848 Py_VISIT(sstate->QUOTE); 1879 Py_VISIT(sstate->QUOTE);
1849 Py_VISIT(sstate->NS_SEPARATOR); 1880 Py_VISIT(sstate->NS_SEPARATOR);
1850 Py_VISIT(sstate->FILTER_SEPARATOR); 1881 Py_VISIT(sstate->FILTER_SEPARATOR);
1882 Py_VISIT(sstate->FILTER_SEPARATOR_REV);
1851 Py_VISIT(sstate->EMPTY_FILTER); 1883 Py_VISIT(sstate->EMPTY_FILTER);
1852 Py_VISIT(sstate->NONE_FILTER); 1884 Py_VISIT(sstate->NONE_FILTER);
1853 Py_VISIT(sstate->EMPTY_STR); 1885 Py_VISIT(sstate->EMPTY_STR);
1854 Py_VISIT(sstate->QUOTE_MAP); 1886 Py_VISIT(sstate->QUOTE_MAP);
1855 Py_VISIT(sstate->MISSING); 1887 Py_VISIT(sstate->MISSING);
1873 if (sstate != NULL) { 1905 if (sstate != NULL) {
1874 Py_CLEAR(sstate->DOT); 1906 Py_CLEAR(sstate->DOT);
1875 Py_CLEAR(sstate->QUOTE); 1907 Py_CLEAR(sstate->QUOTE);
1876 Py_CLEAR(sstate->NS_SEPARATOR); 1908 Py_CLEAR(sstate->NS_SEPARATOR);
1877 Py_CLEAR(sstate->FILTER_SEPARATOR); 1909 Py_CLEAR(sstate->FILTER_SEPARATOR);
1910 Py_CLEAR(sstate->FILTER_SEPARATOR_REV);
1878 Py_CLEAR(sstate->EMPTY_FILTER); 1911 Py_CLEAR(sstate->EMPTY_FILTER);
1879 Py_CLEAR(sstate->NONE_FILTER); 1912 Py_CLEAR(sstate->NONE_FILTER);
1880 Py_CLEAR(sstate->EMPTY_STR); 1913 Py_CLEAR(sstate->EMPTY_STR);
1881 Py_CLEAR(sstate->QUOTE_MAP); 1914 Py_CLEAR(sstate->QUOTE_MAP);
1882 Py_CLEAR(sstate->MISSING); 1915 Py_CLEAR(sstate->MISSING);