diff options
Diffstat (limited to 'psycopg/utils.c')
-rw-r--r-- | psycopg/utils.c | 68 |
1 files changed, 62 insertions, 6 deletions
diff --git a/psycopg/utils.c b/psycopg/utils.c index bc6f7be..7f6b6e6 100644 --- a/psycopg/utils.c +++ b/psycopg/utils.c @@ -40,6 +40,8 @@ * and set an exception. The returned string includes quotes and leading E if * needed. * + * `len` is optional: if < 0 it will be calculated. + * * If tolen is set, it will contain the length of the escaped string, * including quotes. */ @@ -50,7 +52,7 @@ psycopg_escape_string(connectionObject *conn, const char *from, Py_ssize_t len, Py_ssize_t ql; int eq = (conn && (conn->equote)) ? 1 : 0; - if (len == 0) { + if (len < 0) { len = strlen(from); } else if (strchr(from, '\0') != from + len) { PyErr_Format(PyExc_ValueError, "A string literal cannot contain NUL (0x00) characters."); @@ -92,13 +94,13 @@ psycopg_escape_string(connectionObject *conn, const char *from, Py_ssize_t len, /* Escape a string for inclusion in a query as identifier. * - * 'len' is optional: if 0 the length is calculated. + * 'len' is optional: if < 0 it will be calculated. * * Return a string allocated by Postgres: free it using PQfreemem * In case of error set a Python exception. */ char * -psycopg_escape_identifier(connectionObject *conn, const char *str, size_t len) +psycopg_escape_identifier(connectionObject *conn, const char *str, Py_ssize_t len) { char *rv = NULL; @@ -107,7 +109,7 @@ psycopg_escape_identifier(connectionObject *conn, const char *str, size_t len) goto exit; } - if (!len) { len = strlen(str); } + if (len < 0) { len = strlen(str); } rv = PQescapeIdentifier(conn->pgconn, str, len); if (!rv) { @@ -127,7 +129,7 @@ exit: /* Duplicate a string. * * Allocate a new buffer on the Python heap containing the new string. - * 'len' is optional: if 0 the length is calculated. + * 'len' is optional: if < 0 the length is calculated. * * Store the return in 'to' and return 0 in case of success, else return -1 * and raise an exception. @@ -141,7 +143,7 @@ psycopg_strdup(char **to, const char *from, Py_ssize_t len) *to = NULL; return 0; } - if (!len) { len = strlen(from); } + if (len < 0) { len = strlen(from); } if (!(*to = PyMem_Malloc(len + 1))) { PyErr_NoMemory(); return -1; @@ -276,3 +278,57 @@ exit: return res; } + + +/* Convert a C string into Python Text using a specified codec. + * + * The codec is the python function codec.getdecoder(enc). It is only used on + * Python 3 to return unicode: in Py2 the function returns a string. + * + * len is optional: use -1 to have it calculated by the function. + */ +PyObject * +psycopg_text_from_chars_safe(const char *str, Py_ssize_t len, PyObject *decoder) +{ +#if PY_MAJOR_VERSION < 3 + + if (!str) { Py_RETURN_NONE; } + + if (len < 0) { len = strlen(str); } + + return PyString_FromStringAndSize(str, len); + +#else + + static PyObject *replace = NULL; + PyObject *rv = NULL; + PyObject *b = NULL; + PyObject *t = NULL; + + if (!str) { Py_RETURN_NONE; } + + if (len < 0) { len = strlen(str); } + + if (decoder) { + if (!replace) { + if (!(replace = PyUnicode_FromString("replace"))) { goto exit; } + } + if (!(b = PyBytes_FromStringAndSize(str, len))) { goto exit; } + if (!(t = PyObject_CallFunctionObjArgs(decoder, b, replace, NULL))) { + goto exit; + } + + if (!(rv = PyTuple_GetItem(t, 0))) { goto exit; } + Py_INCREF(rv); + } + else { + rv = PyUnicode_DecodeASCII(str, len, "replace"); + } + +exit: + Py_XDECREF(t); + Py_XDECREF(b); + return rv; + +#endif +} |