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.
This commit is contained in:
Carlos Martín Nieto
2014-02-03 17:45:49 +01:00
parent d7071b88cd
commit 74d091d609
2 changed files with 35 additions and 10 deletions

View File

@@ -32,27 +32,50 @@
extern PyTypeObject ReferenceType; 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 * char *
py_str_to_c_str(PyObject *value, const char *encoding) py_str_to_c_str(PyObject *value, const char *encoding)
{ {
const char *borrowed;
char *c_str = NULL; 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 */ /* Case 1: byte string */
if (PyBytes_Check(value)) if (PyBytes_Check(value)) {
return strdup(PyBytes_AsString(value)); Py_INCREF(value);
*tvalue = value;
return PyBytes_AsString(value);
}
/* Case 2: text string */ /* Case 2: text string */
if (PyUnicode_Check(value)) { if (PyUnicode_Check(value)) {
if (encoding == NULL) if (encoding == NULL)
value = PyUnicode_AsUTF8String(value); *tvalue = PyUnicode_AsUTF8String(value);
else else
value = PyUnicode_AsEncodedString(value, encoding, "strict"); *tvalue = PyUnicode_AsEncodedString(value, encoding, "strict");
if (value == NULL) if (*tvalue == NULL)
return NULL; return NULL;
c_str = strdup(PyBytes_AsString(value)); return PyBytes_AsString(*tvalue);
Py_DECREF(value);
return c_str;
} }
/* Type error */ /* Type error */

View File

@@ -108,6 +108,8 @@ to_bytes(const char * value)
} }
char * py_str_to_c_str(PyObject *value, const char *encoding); 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) \ #define py_path_to_c_str(py_path) \
py_str_to_c_str(py_path, Py_FileSystemDefaultEncoding) py_str_to_c_str(py_path, Py_FileSystemDefaultEncoding)