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;
/* 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 */

View File

@@ -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)