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:
43
src/utils.c
43
src/utils.c
@@ -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 */
|
||||||
|
@@ -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)
|
||||||
|
Reference in New Issue
Block a user