Author: zturner Date: Fri Oct 16 12:51:49 2015 New Revision: 250530 URL: http://llvm.org/viewvc/llvm-project?rev=250530&view=rev Log: Convert SWIG typemap string operations to PythonObjects.
Modified: lldb/trunk/scripts/Python/python-typemaps.swig lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp Modified: lldb/trunk/scripts/Python/python-typemaps.swig URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/python-typemaps.swig?rev=250530&r1=250529&r2=250530&view=diff ============================================================================== --- lldb/trunk/scripts/Python/python-typemaps.swig (original) +++ lldb/trunk/scripts/Python/python-typemaps.swig Fri Oct 16 12:51:49 2015 @@ -63,34 +63,38 @@ int i; len = 0; while ($1[len]) len++; - lldb_private::PythonList list(len); + using namespace lldb_private; + PythonList list(len); for (i = 0; i < len; i++) - list.SetItemAtIndex(i, lldb_private::PythonString($1[i])); + list.SetItemAtIndex(i, PythonString($1[i])); $result = list.release(); } %typemap(in) char const ** { /* Check if is a list */ - if (PyList_Check($input)) { - int size = PyList_Size($input); - int i = 0; - $1 = (char **) malloc((size+1) * sizeof(char*)); - for (i = 0; i < size; i++) { - PyObject *o = PyList_GetItem($input,i); - if (PyString_Check(o)) - $1[i] = PyString_AsString(o); - else { + using namespace lldb_private; + if (PythonList::Check($input)) { + PythonList py_list(PyRefType::Borrowed, $input); + int size = py_list.GetSize(); + + $1 = (char**)malloc((size+1)*sizeof(char*)); + for (int i = 0; i < size; i++) { + PythonObject o = py_list.GetItemAtIndex(i); + if (!PythonString::Check(o.get())) { PyErr_SetString(PyExc_TypeError,"list must contain strings"); free($1); - return NULL; + return nullptr; } + auto py_str = o.AsType<PythonString>(); + $1[i] = const_cast<char*>(py_str.GetString().data()); } - $1[i] = 0; + + $1[size] = 0; } else if ($input == Py_None) { - $1 = NULL; + $1 = nullptr; } else { PyErr_SetString(PyExc_TypeError,"not a list"); - return NULL; + return nullptr; } } @@ -501,12 +505,13 @@ } %typemap(in) FILE * { + using namespace lldb_private; if ($input == Py_None) - $1 = NULL; + $1 = nullptr; else if (!lldb_private::PythonFile::Check($input)) { int fd = PyObject_AsFileDescriptor($input); - lldb_private::PythonString py_mode(lldb_private::PyRefType::Owned, - PyObject_GetAttrString($input, "mode")); + PythonObject py_input(PyRefType::Borrowed, $input); + PythonString py_mode = py_input.GetAttributeValue("mode").AsType<PythonString>(); if (-1 != fd && py_mode.IsValid()) { FILE *f; @@ -521,10 +526,10 @@ } else { - lldb_private::File file; - lldb_private::PythonFile py_file(lldb_private::PyRefType::Borrowed, $input); - if (!py_file.GetUnderlyingFile(file)) - return nullptr; + PythonFile py_file(PyRefType::Borrowed, $input); + File file; + if (!py_file.GetUnderlyingFile(file)) + return nullptr; $1 = file.GetStream(); } @@ -543,26 +548,34 @@ else // if (flags & __SRW) mode[i++] = 'a'; #endif - lldb_private::File file($1, false); - lldb_private::PythonFile py_file(file, mode); + using namespace lldb_private; + File file($1, false); + PythonFile py_file(file, mode); $result = py_file.release(); } %typemap(in) (const char* string, int len) { + using namespace lldb_private; if ($input == Py_None) { $1 = NULL; $2 = 0; } - else if (PyUnicode_Check($input)) - { - $1 = PyString_AsString(PyUnicode_AsUTF8String($input)); - $2 = strlen($1); - } - else if (PyString_Check($input)) + else if (PythonString::Check($input)) { - $1 = PyString_AsString($input); - $2 = PyString_Size($input); + PythonString py_str(PyRefType::Borrowed, $input); + llvm::StringRef str = py_str.GetString(); + $1 = const_cast<char*>(str.data()); + $2 = str.size(); + // In Python 2, if $input is a PyUnicode object then this + // will trigger a Unicode -> String conversion, in which + // case the `PythonString` will now own the PyString. Thus + // if it goes out of scope, the data will be deleted. The + // only way to avoid this is to leak the Python object in + // that case. Note that if there was no conversion, then + // releasing the string will not leak anything, since we + // created this as a borrowed reference. + py_str.release(); } else { Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp?rev=250530&r1=250529&r2=250530&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp (original) +++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp Fri Oct 16 12:51:49 2015 @@ -111,6 +111,20 @@ PythonObject::HasAttribute(llvm::StringR return !!PyObject_HasAttr(m_py_obj, py_attr.get()); } +PythonObject +PythonObject::GetAttributeValue(llvm::StringRef attr) const +{ + if (!IsValid()) + return PythonObject(); + + PythonString py_attr(attr); + if (!PyObject_HasAttr(m_py_obj, py_attr.get())) + return PythonObject(); + + return PythonObject(PyRefType::Owned, + PyObject_GetAttr(m_py_obj, py_attr.get())); +} + bool PythonObject::IsNone() const { @@ -191,11 +205,13 @@ PythonString::Check(PyObject *py_obj) if (!py_obj) return false; -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_Check(py_obj); -#else - return PyString_Check(py_obj); + if (PyUnicode_Check(py_obj)) + return true; +#if PY_MAJOR_VERSION < 3 + if (PyString_Check(py_obj)) + return true; #endif + return false; } void @@ -210,7 +226,13 @@ PythonString::Reset(PyRefType type, PyOb PythonObject::Reset(); return; } - +#if PY_MAJOR_VERSION < 3 + // In Python 2, Don't store PyUnicode objects directly, because we need + // access to their underlying character buffers which Python 2 doesn't + // provide. + if (PyUnicode_Check(py_obj)) + result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get())); +#endif // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls // back into the virtual implementation. PythonObject::Reset(PyRefType::Borrowed, result.get()); @@ -271,6 +293,12 @@ PythonString::CreateStructuredString() c // PythonInteger //---------------------------------------------------------------------- +PythonInteger::PythonInteger() + : PythonObject() +{ + +} + PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) : PythonObject() { Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h?rev=250530&r1=250529&r2=250530&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h (original) +++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h Fri Oct 16 12:51:49 2015 @@ -201,6 +201,9 @@ public: bool HasAttribute(llvm::StringRef attribute) const; + PythonObject + GetAttributeValue(llvm::StringRef attribute) const; + bool IsValid() const; @@ -210,6 +213,14 @@ public: bool IsNone() const; + template<typename T> + T AsType() const + { + if (!T::Check(m_py_obj)) + return T(); + return T(PyRefType::Borrowed, m_py_obj); + } + StructuredData::ObjectSP CreateStructuredObject() const; protected: Modified: lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp?rev=250530&r1=250529&r2=250530&view=diff ============================================================================== --- lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp (original) +++ lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp Fri Oct 16 12:51:49 2015 @@ -382,3 +382,14 @@ TEST_F(PythonDataObjectsTest, TestPython PythonFile py_file(file, "r"); EXPECT_TRUE(PythonFile::Check(py_file.get())); } + +TEST_F(PythonDataObjectsTest, TestObjectAttributes) +{ + PythonInteger py_int(42); + EXPECT_TRUE(py_int.HasAttribute("numerator")); + EXPECT_FALSE(py_int.HasAttribute("this_should_not_exist")); + + PythonInteger numerator_attr = py_int.GetAttributeValue("numerator").AsType<PythonInteger>(); + EXPECT_TRUE(numerator_attr.IsAllocated()); + EXPECT_EQ(42, numerator_attr.GetInteger()); +} \ No newline at end of file _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits