diff configmix/_speedups.c @ 550:79db28e879f8

Provide a C-implementation of configmix.config.quote() also: fast_quote
author Franz Glasner <fzglas.hg@dom66.de>
date Sun, 02 Jan 2022 02:04:07 +0100
parents 84657447ab39
children 39e5d07d8dbc
line wrap: on
line diff
--- a/configmix/_speedups.c	Sun Jan 02 01:00:10 2022 +0100
+++ b/configmix/_speedups.c	Sun Jan 02 02:04:07 2022 +0100
@@ -23,6 +23,7 @@
     PyObject *QUOTE;
     PyObject *NS_SEPARATOR;
     PyObject *EMPTY_STR;
+    PyObject *QUOTE_MAP;
 };
 
 
@@ -402,6 +403,60 @@
 
 static
 PyObject *
+fast_quote(PyObject *self, PyObject *s)
+{
+    Py_ssize_t s_len;
+    Py_ssize_t i;
+    Py_UCS4 c;
+    int need_quoting;
+    struct speedups_state *sstate;
+
+    s_len = PyUnicode_GetLength(s);
+    if (s_len < 0) {
+        return NULL;
+    }
+    if (s_len == 0) {
+        Py_INCREF(s);
+        return s;
+    }
+    need_quoting = 0;
+    for (i=0; i<s_len; i++) {
+        c = PyUnicode_ReadChar(s, i);   /* type already checked */
+        switch (c) {
+        case 0x25:
+        case 0x2e:
+        case 0x3a:
+        case 0x23:
+        case 0x7c:
+        case 0x22:
+        case 0x27:
+        case 0x7b:
+        case 0x7d:
+        case 0x5b:
+        case 0x5d:
+            need_quoting = 1;
+            i = s_len;   /* break the for-loop */
+            break;
+        default:
+            /* VOID */
+            ;
+        }
+    }
+    if (!need_quoting) {
+        Py_INCREF(s);
+        return s;
+    }
+    sstate = PyModule_GetState(self);
+    if (sstate == NULL) {
+        PyErr_SetString(PyExc_RuntimeError, "no module state available");
+        return NULL;
+    }
+    return PyUnicode_Translate(s, sstate->QUOTE_MAP, "strict");
+}
+
+
+static
+PyObject *
 fast_pathstr2path(PyObject *self, PyObject *varname)
 {
     Py_ssize_t varname_len;
@@ -520,6 +575,7 @@
 
 static struct PyMethodDef speedups_methods[] = {
     {"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_ns", fast_split_ns, METH_O, PyDoc_STR("C-implementation of configmix.config._split_ns")},
     {NULL, NULL, 0, NULL}
@@ -571,6 +627,23 @@
     }
     PyUnicode_InternInPlace(&(sstate->EMPTY_STR));
 
+    sstate->QUOTE_MAP = Py_BuildValue(
+        "{IsIsIsIsIsIsIsIsIsIsIs}",
+        0x25, "%x25",     /* QUOTE: % */
+        0x2e, "%x2e",     /* DOT: . */
+        0x3a, "%x3a",     /* NS_SEPARATOR: : */
+        0x23, "%x23",     /* COMMENT/anchor: # */
+        0x7c, "%x7c",     /* FILTER_SEPARATOR: | */
+        0x22, "%x22",
+        0x27, "%x27",
+        0x7b, "%x7b",
+        0x7d, "%x7d",
+        0x5b, "%x5b",
+        0x5d, "%x5d");
+    if (sstate->QUOTE_MAP == NULL) {
+        return -1;
+    }
+
     return 0;
 }
 
@@ -586,6 +659,7 @@
         Py_VISIT(sstate->QUOTE);
         Py_VISIT(sstate->NS_SEPARATOR);
         Py_VISIT(sstate->EMPTY_STR);
+        Py_VISIT(sstate->QUOTE_MAP);
     }
     return 0;
 }
@@ -602,6 +676,7 @@
         Py_CLEAR(sstate->QUOTE);
         Py_CLEAR(sstate->NS_SEPARATOR);
         Py_CLEAR(sstate->EMPTY_STR);
+        Py_CLEAR(sstate->QUOTE_MAP);
     }
     return 0;
 }