From 74d091d6097f7792bac72dbf8e3da22560714b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 3 Feb 2014 17:45:49 +0100 Subject: [PATCH] utils: allow borrowing a C string We don't always need our own copy of a C string; sometimes we just need to parse it. Create py_str_borrow_c_str() which returns a char pointer to python's internal value string, with which we can avoid an extra copy. --- src/utils.c | 43 +++++++++++++++++++++++++++++++++---------- src/utils.h | 2 ++ 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/utils.c b/src/utils.c index 6a20b01..e63ea9d 100644 --- a/src/utils.c +++ b/src/utils.c @@ -32,27 +32,50 @@ extern PyTypeObject ReferenceType; -/* py_str_to_c_str() returns a newly allocated C string holding - * the string contained in the value argument. */ +/** + * py_str_to_c_str() returns a newly allocated C string holding the string + * contained in the 'value' argument. + */ char * py_str_to_c_str(PyObject *value, const char *encoding) { + const char *borrowed; char *c_str = NULL; + PyObject *tmp = NULL; + + borrowed = py_str_borrow_c_str(&tmp, value, encoding); + if (!borrowed) + return NULL; + + c_str = strdup(borrowed); + + Py_DECREF(tmp); + return c_str; +} + +/** + * Return a pointer to the underlying C string in 'value'. The pointer is + * guaranteed by 'tvalue'. Decrease its refcount when done with the string. + */ +const char * +py_str_borrow_c_str(PyObject **tvalue, PyObject *value, const char *encoding) +{ /* Case 1: byte string */ - if (PyBytes_Check(value)) - return strdup(PyBytes_AsString(value)); + if (PyBytes_Check(value)) { + Py_INCREF(value); + *tvalue = value; + return PyBytes_AsString(value); + } /* Case 2: text string */ if (PyUnicode_Check(value)) { if (encoding == NULL) - value = PyUnicode_AsUTF8String(value); + *tvalue = PyUnicode_AsUTF8String(value); else - value = PyUnicode_AsEncodedString(value, encoding, "strict"); - if (value == NULL) + *tvalue = PyUnicode_AsEncodedString(value, encoding, "strict"); + if (*tvalue == NULL) return NULL; - c_str = strdup(PyBytes_AsString(value)); - Py_DECREF(value); - return c_str; + return PyBytes_AsString(*tvalue); } /* Type error */ diff --git a/src/utils.h b/src/utils.h index 05ddcd2..3b3c42a 100644 --- a/src/utils.h +++ b/src/utils.h @@ -108,6 +108,8 @@ to_bytes(const char * value) } char * py_str_to_c_str(PyObject *value, const char *encoding); +const char *py_str_borrow_c_str(PyObject **tvaue, PyObject *value, const char *encoding); + #define py_path_to_c_str(py_path) \ py_str_to_c_str(py_path, Py_FileSystemDefaultEncoding)