[Lldb-commits] [lldb] r250530 - Convert SWIG typemap string operations to PythonObjects.

Zachary Turner via lldb-commits lldb-commits at lists.llvm.org
Fri Oct 16 10:51:50 PDT 2015


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




More information about the lldb-commits mailing list