summaryrefslogtreecommitdiff
path: root/psycopg/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'psycopg/utils.c')
-rw-r--r--psycopg/utils.c68
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
+}