diff 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
line wrap: on
line diff
--- a/configmix/_speedups.c	Mon Aug 14 13:00:19 2023 +0200
+++ b/configmix/_speedups.c	Tue Aug 15 09:34:49 2023 +0200
@@ -25,6 +25,7 @@
     PyObject *QUOTE;
     PyObject *NS_SEPARATOR;
     PyObject *FILTER_SEPARATOR;
+    PyObject *FILTER_SEPARATOR_REV;
     PyObject *EMPTY_FILTER;
     PyObject *NONE_FILTER;
     PyObject *EMPTY_STR;
@@ -606,7 +607,7 @@
 
 static
 PyObject *
-_fast_split_filters(PyObject *varname, PyObject *self, struct speedups_state *sstate)
+_fast_split_filters(PyObject *varname, PyObject *self, Py_ssize_t direction, struct speedups_state *sstate)
 {
     Py_ssize_t varname_len;
     Py_ssize_t sep;
@@ -623,7 +624,7 @@
         sep = -1;
     }
     else {
-        sep = PyUnicode_FindChar(varname, '|', 0, varname_len, 1);
+        sep = PyUnicode_FindChar(varname, '|', 0, varname_len, (int)direction);
         if (sep == -2) {
             return NULL;
         }
@@ -682,7 +683,12 @@
         }
     }
 
-    tmp = PyUnicode_Split(filters, sstate->FILTER_SEPARATOR, -1);
+    if (direction == 1) {
+        tmp = PyUnicode_Split(filters, sstate->FILTER_SEPARATOR, -1);
+    }
+    else {
+        tmp = PyUnicode_Split(filters, sstate->FILTER_SEPARATOR_REV, -1);
+    }
     if (tmp == NULL) {
         goto error;
     }
@@ -706,9 +712,28 @@
 
 static
 PyObject *
-fast_split_filters(PyObject *self, PyObject *varname)
+fast_split_filters(PyObject *self, PyObject *args)
 {
-    return _fast_split_filters(varname, self, NULL);
+    PyObject *varname;
+    PyObject *direction_obj;
+    Py_ssize_t direction;
+
+    if (!PyArg_UnpackTuple(args, "fast_split_filters", 2, 2, &varname, &direction_obj)) {
+        return NULL;
+    }
+    direction = PyNumber_AsSsize_t(direction_obj, PyExc_OverflowError);
+    if (direction == -1) {
+        if (PyErr_Occurred()) {
+            return NULL;
+        }
+    }
+    if ((direction == 1) || (direction == -1)) {
+        return _fast_split_filters(varname, self, direction, NULL);
+    }
+    else {
+        PyErr_SetString(PyExc_ValueError, "`direction' must be -1 or +1");
+        return NULL;
+    }
 }
 
 
@@ -910,7 +935,7 @@
             goto error;
         }
 
-        tmp = _fast_split_filters(varname, NULL, sstate);
+        tmp = _fast_split_filters(varname, NULL, 1, sstate);
         if (tmp == NULL) {
             goto error;
         }
@@ -1130,7 +1155,7 @@
         if (tmp == NULL) {
             return NULL;
         }
-        filters = _fast_split_filters(tmp, NULL, sstate);
+        filters = _fast_split_filters(tmp, NULL, -1, sstate);
         if (filters == NULL) {
             py_clear_ref(&tmp);
             return NULL;
@@ -1215,7 +1240,7 @@
             goto error;
         }
 
-        tmp = _fast_split_filters(varname, NULL, sstate);
+        tmp = _fast_split_filters(varname, NULL, 1, sstate);
         if (tmp == NULL) {
             goto error;
         }
@@ -1709,7 +1734,7 @@
     {"fast_unquote", fast_unquote, METH_O, PyDoc_STR("C-implementation of configmix.unquote")},
     {"fast_quote", fast_quote, METH_O, PyDoc_STR("C-implementation of configmix.quote")},
     {"fast_pathstr2path", fast_pathstr2path, METH_O, PyDoc_STR("C-implementation of configmix.pathstr2path")},
-    {"_fast_split_filters", fast_split_filters, METH_O, PyDoc_STR("C-implementation of configmix.config._split_filters")},
+    {"_fast_split_filters", fast_split_filters, METH_VARARGS, PyDoc_STR("C-implementation of configmix.config._split_filters")},
     {"_fast_split_ns", fast_split_ns, METH_O, PyDoc_STR("C-implementation of configmix.config._split_ns")},
     {"_fast_interpolate_variables", fast_interpolate_variables, METH_VARARGS, PyDoc_STR("C-implementation of configmix.config.Configuration.interpolate_variables")},
     {"_fast_getvarl", (PyCFunction)fast_getvarl, METH_VARARGS | METH_KEYWORDS, PyDoc_STR("C-Implementation of configmix.config.Configuration.getvarl")},
@@ -1767,6 +1792,12 @@
     }
     PyUnicode_InternInPlace(&(sstate->FILTER_SEPARATOR));
 
+    sstate->FILTER_SEPARATOR_REV = PyUnicode_FromStringAndSize(",", 1);
+    if (sstate->FILTER_SEPARATOR_REV == NULL) {
+        return -1;
+    }
+    PyUnicode_InternInPlace(&(sstate->FILTER_SEPARATOR_REV));
+
     sstate->EMPTY_FILTER = PyUnicode_FromStringAndSize("Empty", 5);
     if (sstate->EMPTY_FILTER == NULL) {
         return -1;
@@ -1848,6 +1879,7 @@
         Py_VISIT(sstate->QUOTE);
         Py_VISIT(sstate->NS_SEPARATOR);
         Py_VISIT(sstate->FILTER_SEPARATOR);
+        Py_VISIT(sstate->FILTER_SEPARATOR_REV);
         Py_VISIT(sstate->EMPTY_FILTER);
         Py_VISIT(sstate->NONE_FILTER);
         Py_VISIT(sstate->EMPTY_STR);
@@ -1875,6 +1907,7 @@
         Py_CLEAR(sstate->QUOTE);
         Py_CLEAR(sstate->NS_SEPARATOR);
         Py_CLEAR(sstate->FILTER_SEPARATOR);
+        Py_CLEAR(sstate->FILTER_SEPARATOR_REV);
         Py_CLEAR(sstate->EMPTY_FILTER);
         Py_CLEAR(sstate->NONE_FILTER);
         Py_CLEAR(sstate->EMPTY_STR);