# HG changeset patch # User Mike Miller # Date 1471141787 25200 # Node ID fd5881d48238ea3b1b9157fe00ebc3f58d15a8f0 # Parent 2b24602952182fa68d3ace95b1462ecf23407081 Overhaul Python string creation and extraction * oct-py-types.cc, oct-py-types.h (pytave::extract_py_str, pytave::make_py_str): New functions to create a Python string and extract string value from Python. (pytave::make_py_dict): Use make_py_str. * octave_to_python.cc (pytave::octvalue_to_pyobj): Use make_py_str. (pytave::octstring_to_pyobject): Delete. * python_to_octave.cc (pytave::pyobj_to_octvalue): Use extract_py_str. (pytave::pyunicode_to_utf8): Delete. diff -r 2b2460295218 -r fd5881d48238 oct-py-types.cc --- a/oct-py-types.cc Fri Aug 12 00:57:46 2016 -0700 +++ b/oct-py-types.cc Sat Aug 13 19:29:47 2016 -0700 @@ -27,6 +27,7 @@ #include #include +#include "exceptions.h" #include "oct-py-types.h" // FIXME: only here to bootstrap nested conversions needed in this file @@ -54,7 +55,10 @@ for (auto p = map.begin (); p != map.end (); ++p) { - PyObject *key = wrap_octvalue_to_pyobj (map.key (p)); + PyObject *key = make_py_str (map.key (p)); + if (! key) + octave_throw_bad_alloc (); + PyObject *item = wrap_octvalue_to_pyobj (map.contents (p)); if (PyDict_SetItem (dict, key, item) < 0) @@ -64,4 +68,47 @@ return dict; } +std::string +extract_py_str (PyObject *obj) +{ + std::string retval; + + if (! obj) + throw object_convert_exception ("failed to extract string: null object"); + if (PyBytes_Check (obj)) + { + retval.assign (PyBytes_AsString (obj), PyBytes_Size (obj)); + } + else if (PyUnicode_Check (obj)) + { + bool ok = false; + PyObject *enc = PyUnicode_AsUTF8String (obj); + if (enc) + { + if (PyBytes_Check (enc)) + { + ok = true; + retval.assign (PyBytes_AsString (enc), PyBytes_Size (enc)); + } + Py_DECREF (enc); + } + if (! ok) + throw object_convert_exception ("failed to extract string: UTF-8 error"); + } + else + throw object_convert_exception ("failed to extract string: wrong type"); + + return retval; } + +PyObject * +make_py_str (const std::string& str) +{ +#if PY_VERSION_HEX >= 0x03000000 + return PyUnicode_FromStringAndSize (str.data (), str.size ()); +#else + return PyString_FromStringAndSize (str.data (), str.size ()); +#endif +} + +} diff -r 2b2460295218 -r fd5881d48238 oct-py-types.h --- a/oct-py-types.h Fri Aug 12 00:57:46 2016 -0700 +++ b/oct-py-types.h Sat Aug 13 19:29:47 2016 -0700 @@ -24,6 +24,7 @@ #define pytave_oct_py_types_h 1 #include +#include class octave_scalar_map; @@ -33,6 +34,12 @@ PyObject * make_py_dict (const octave_scalar_map& map); +std::string +extract_py_str (PyObject *obj); + +PyObject * +make_py_str (const std::string& str); + } #endif diff -r 2b2460295218 -r fd5881d48238 octave_to_python.cc --- a/octave_to_python.cc Fri Aug 12 00:57:46 2016 -0700 +++ b/octave_to_python.cc Sat Aug 13 19:29:47 2016 -0700 @@ -305,19 +305,6 @@ throw value_convert_exception ("unhandled scalar type"); } - static void - octstring_to_pyobject (boost::python::object& py_object, - const std::string& str) - { - py_object = object (handle ( -#if PY_VERSION_HEX >= 0x03000000 - PyUnicode_FromStringAndSize (str.data (), str.size ()) -#else - PyString_FromStringAndSize (str.data (), str.size ()) -#endif - )); - } - void octvalue_to_pyobj (boost::python::object& py_object, const octave_value& octvalue) { @@ -325,7 +312,10 @@ throw value_convert_exception ( "Octave value `undefined'. Can not convert to a Python object"); else if (octvalue.is_string ()) - octstring_to_pyobject (py_object, octvalue.string_value ()); + { + PyObject *obj = make_py_str (octvalue.string_value ()); + py_object = object (handle (obj)); + } else if (octvalue.is_scalar_type ()) octscalar_to_pyobject (py_object, octvalue); else if (octvalue.is_cell ()) diff -r 2b2460295218 -r fd5881d48238 python_to_octave.cc --- a/python_to_octave.cc Fri Aug 12 00:57:46 2016 -0700 +++ b/python_to_octave.cc Sat Aug 13 19:29:47 2016 -0700 @@ -40,6 +40,7 @@ #include "arrayobjectdefs.h" #include "exceptions.h" +#include "oct-py-types.h" #include "python_to_octave.h" #include "pytave_utils.h" @@ -466,16 +467,6 @@ oct_value = map; } - static std::string - pyunicode_to_utf8 (PyObject *unicode) - { - std::string str; - PyObject *utf8 = PyUnicode_AsUTF8String (unicode); - str.assign (PyBytes_AsString (utf8), PyBytes_Size (utf8)); - Py_DECREF (utf8); - return str; - } - static void pyobj_to_oct_pyobject (octave_value& oct_value, const boost::python::object& py_object) @@ -508,8 +499,6 @@ extract boolx (py_object); extract doublex (py_object); extract complexx (py_object); - extract stringx (py_object); - extract wstringx (py_object); extract arrayx (py_object); extract listx (py_object); extract dictx (py_object); @@ -525,10 +514,8 @@ oct_value = complexx (); else if (arrayx.check ()) pyarr_to_octvalue (oct_value, (PyArrayObject*)py_object.ptr ()); - else if (stringx.check ()) - oct_value = stringx (); - else if (wstringx.check ()) - oct_value = pyunicode_to_utf8 (py_object.ptr ()); + else if (PyBytes_Check (py_object.ptr ()) || PyUnicode_Check (py_object.ptr ())) + oct_value = extract_py_str (py_object.ptr ()); else pyobj_to_oct_pyobject (oct_value, py_object); }