text: /*
   * utility functions
   *
   * src/pl/plpython/plpy_util.c
   */
  
  #include "postgres.h"
  
  #include "mb/pg_wchar.h"
  #include "utils/memutils.h"
  #include "utils/palloc.h"
  
  #include "plpython.h"
  
  #include "plpy_util.h"
  
  #include "plpy_elog.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 retuns 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 */
  