dollar quoting
authorMarko Kreen <markokr@gmail.com>
Thu, 3 Apr 2008 09:00:27 +0000 (09:00 +0000)
committerMarko Kreen <markokr@gmail.com>
Thu, 3 Apr 2008 09:00:27 +0000 (09:00 +0000)
python/modules/cquoting.c
python/skytools/_pyquoting.py

index 2dcfc227ead5deca16e985abe3001ad0bfc17c1f..42844ca2631617d71f40e02c8da845fc4094c33e 100644 (file)
@@ -386,6 +386,33 @@ failed:
        return NULL;
 }
 
+static PyObject *do_dolq(unsigned char *src, Py_ssize_t src_len)
+{
+       /* src_len >= 2, '$' in start and end */
+       unsigned char *src_end = src + src_len;
+       unsigned char *p1 = src + 1, *p2 = src_end - 2;
+       
+       while (p1 < src_end && *p1 != '$')
+               p1++;
+       while (p2 > src && *p2 != '$')
+               p2--;
+       if (p2 <= p1)
+               goto failed;
+       
+       p1++; /* position after '$' */
+
+       if ((p1 - src) != (src_end - p2))
+               goto failed;
+       if (memcmp(src, p2, p1 - src) != 0)
+               goto failed;
+
+       return PyString_FromStringAndSize((char *)p1, p2 - p1);
+
+failed:
+       PyErr_Format(PyExc_ValueError, "Broken dollar-quoted string");
+       return NULL;
+}
+
 static PyObject *unquote_literal(PyObject *self, PyObject *args)
 {
        unsigned char *src = NULL;
@@ -400,6 +427,8 @@ static PyObject *unquote_literal(PyObject *self, PyObject *args)
                Py_INCREF(Py_None);
                return Py_None;
        }
+       if (src_len >= 2 && src[0] == '$' && src[src_len - 1] == '$')
+               return do_dolq(src, src_len);
        if (src_len < 2 || src[src_len - 1] != '\'')
                goto badstr;
        if (src[0] == '\'') {
index 32d548ffde06e33551e3adc43255c40e176476a9..8f72eb5f40063bb6c9bb115b50fed226b823288a 100644 (file)
@@ -179,6 +179,15 @@ def unquote_literal(val, stdstr = False):
             return _esql_rc.sub(_sub_unescape_sqlext, val[1:-1])
     elif len(val) > 2 and val[0] in ('E', 'e') and val[1] == "'" and val[-1] == "'":
         return _esql_rc.sub(_sub_unescape_sqlext, val[2:-1])
+    elif len(val) >= 2 and val[0] == '$' and val[-1] == '$':
+        p1 = val.find('$', 1)
+        p2 = val.rfind('$', 1, -1)
+        if p1 > 0 and p2 > p1:
+            t1 = val[:p1+1]
+            t2 = val[p2:]
+            if t1 == t2:
+                return val[len(t1):-len(t1)]
+        raise Exception("Bad dollar-quoted string")
     elif val.lower() == "null":
         return None
     return val