| /* |
| * utility functions |
| * |
| * src/pl/plpython/plpy_util.c |
| */ |
| |
| #include "postgres.h" |
| |
| #include "mb/pg_wchar.h" |
| #include "plpy_elog.h" |
| #include "plpy_util.h" |
| #include "plpython.h" |
| #include "utils/memutils.h" |
| |
| /* |
| * Convert a Python unicode object to a Python string/bytes object in |
| * PostgreSQL server encoding. Reference ownership is passed to the |
| * caller. |
| */ |
| PyObject * |
| PLyUnicode_Bytes(PyObject *unicode) |
| { |
| PyObject *bytes, |
| *rv; |
| char *utf8string, |
| *encoded; |
| |
| /* First encode the Python unicode object with UTF-8. */ |
| bytes = PyUnicode_AsUTF8String(unicode); |
| if (bytes == NULL) |
| PLy_elog(ERROR, "could not convert Python Unicode object to bytes"); |
| |
| utf8string = PyBytes_AsString(bytes); |
| if (utf8string == NULL) |
| { |
| Py_DECREF(bytes); |
| PLy_elog(ERROR, "could not extract bytes from encoded string"); |
| } |
| |
| /* |
| * Then convert to server encoding if necessary. |
| * |
| * PyUnicode_AsEncodedString could be used to encode the object directly |
| * in the server encoding, but Python doesn't support all the encodings |
| * that PostgreSQL does (EUC_TW and MULE_INTERNAL). UTF-8 is used as an |
| * intermediary in PLyUnicode_FromString as well. |
| */ |
| if (GetDatabaseEncoding() != PG_UTF8) |
| { |
| PG_TRY(); |
| { |
| encoded = pg_any_to_server(utf8string, |
| strlen(utf8string), |
| PG_UTF8); |
| } |
| PG_CATCH(); |
| { |
| Py_DECREF(bytes); |
| PG_RE_THROW(); |
| } |
| PG_END_TRY(); |
| } |
| else |
| encoded = utf8string; |
| |
| /* finally, build a bytes object in the server encoding */ |
| rv = PyBytes_FromStringAndSize(encoded, strlen(encoded)); |
| |
| /* if pg_any_to_server allocated memory, free it now */ |
| if (utf8string != encoded) |
| pfree(encoded); |
| |
| Py_DECREF(bytes); |
| return rv; |
| } |
| |
| /* |
| * Convert a Python unicode object to a C string in PostgreSQL server |
| * encoding. No Python object reference is passed out of this |
| * function. The result is palloc'ed. |
| * |
| * Note that this function is disguised as PyString_AsString() when |
| * using Python 3. That function returns a pointer into the internal |
| * memory of the argument, which isn't exactly the interface of this |
| * function. But in either case you get a rather short-lived |
| * reference that you ought to better leave alone. |
| */ |
| char * |
| PLyUnicode_AsString(PyObject *unicode) |
| { |
| PyObject *o = PLyUnicode_Bytes(unicode); |
| char *rv = pstrdup(PyBytes_AsString(o)); |
| |
| Py_XDECREF(o); |
| return rv; |
| } |
| |
| #if PY_MAJOR_VERSION >= 3 |
| /* |
| * Convert a C string in the PostgreSQL server encoding to a Python |
| * unicode object. Reference ownership is passed to the caller. |
| */ |
| PyObject * |
| PLyUnicode_FromStringAndSize(const char *s, Py_ssize_t size) |
| { |
| char *utf8string; |
| PyObject *o; |
| |
| utf8string = pg_server_to_any(s, size, PG_UTF8); |
| |
| if (utf8string == s) |
| { |
| o = PyUnicode_FromStringAndSize(s, size); |
| } |
| else |
| { |
| o = PyUnicode_FromString(utf8string); |
| pfree(utf8string); |
| } |
| |
| return o; |
| } |
| |
| PyObject * |
| PLyUnicode_FromString(const char *s) |
| { |
| return PLyUnicode_FromStringAndSize(s, strlen(s)); |
| } |
| |
| #endif /* PY_MAJOR_VERSION >= 3 */ |