diff options
author | Marko Kreen | 2008-04-03 09:00:27 +0000 |
---|---|---|
committer | Marko Kreen | 2008-04-03 09:00:27 +0000 |
commit | 40c21125dec7939c3d2a4b3e9ad5d8aef4eff15d (patch) | |
tree | ef1f3eb66b30dbac436e9fad2ca4c05af33e5520 | |
parent | 66ce65ce3c224af8f90685bc20828714a80c57a4 (diff) |
dollar quoting
-rw-r--r-- | python/modules/cquoting.c | 29 | ||||
-rw-r--r-- | python/skytools/_pyquoting.py | 9 |
2 files changed, 38 insertions, 0 deletions
diff --git a/python/modules/cquoting.c b/python/modules/cquoting.c index 2dcfc227..42844ca2 100644 --- a/python/modules/cquoting.c +++ b/python/modules/cquoting.c @@ -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] == '\'') { diff --git a/python/skytools/_pyquoting.py b/python/skytools/_pyquoting.py index 32d548ff..8f72eb5f 100644 --- a/python/skytools/_pyquoting.py +++ b/python/skytools/_pyquoting.py @@ -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 |