A first version of a bunch of classes that wrap commonly used Python objects in a ref-counting and type-safe C++ API

git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@162481 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/lldb/Interpreter/PythonDataObjects.h b/include/lldb/Interpreter/PythonDataObjects.h
new file mode 100644
index 0000000..70c1a5f
--- /dev/null
+++ b/include/lldb/Interpreter/PythonDataObjects.h
@@ -0,0 +1,214 @@
+//===-- PythonDataObjects.h----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_PythonDataObjects_h_
+#define liblldb_PythonDataObjects_h_
+
+// C Includes
+// C++ Includes
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-defines.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Flags.h"
+#include "lldb/Interpreter/OptionValue.h"
+
+namespace lldb_private {
+    
+    class PythonRefCountedObject
+    {
+    public:
+        PythonRefCountedObject (PyObject* obj) : m_object(obj)
+        {
+            Py_XINCREF(m_object);
+        }
+        
+        ~PythonRefCountedObject ()
+        {
+            Py_XDECREF(m_object);
+        }
+        
+        void
+        Reset (PyObject* object = NULL)
+        {
+            Py_XDECREF(m_object);
+            m_object = object;
+            Py_XINCREF(m_object);
+        }
+        
+        PyObject*
+        GetPyhonObject ()
+        {
+            return m_object;
+        }
+        
+        operator bool ()
+        {
+            return m_object != NULL;
+        }
+        
+    private:
+        PyObject* m_object;
+    };
+    
+    class PythonDataString
+    {
+    public:
+        
+        PythonDataString (PyObject* object);
+        PythonDataString (const char* string);
+        ~PythonDataString ();
+        
+        const char*
+        GetString();
+        
+        void
+        SetString (const char* string);
+        
+        operator bool ()
+        {
+            return m_object.operator bool();
+        }
+        
+        PyObject*
+        GetPythonObject() { return m_object.GetPyhonObject(); }
+    private:
+        PythonRefCountedObject m_object;
+    };
+    
+    class PythonDataInteger
+    {
+    public:
+        
+        PythonDataInteger (PyObject* object);
+        PythonDataInteger (int64_t value);
+        ~PythonDataInteger ();
+        
+        int64_t
+        GetInteger();
+        
+        void
+        SetInteger (int64_t value);
+        
+        operator bool ()
+        {
+            return m_object.operator bool();
+        }
+        
+        PyObject*
+        GetPythonObject() { return m_object.GetPyhonObject(); }
+    private:
+        PythonRefCountedObject m_object;
+    };
+    
+    class PythonDataArray
+    {
+    public:
+        
+        PythonDataArray (uint32_t count);
+        PythonDataArray (PyObject* object);
+        ~PythonDataArray ();
+        
+        uint32_t
+        GetSize();
+        
+        PythonDataObject*
+        GetItemAtIndex (uint32_t index);
+        
+        void
+        SetItemAtIndex (uint32_t index, PythonDataObject* object);
+        
+        void
+        AppendItem (PythonDataObject* object);
+        
+        operator bool ()
+        {
+            return m_object.operator bool();
+        }
+        
+        PyObject*
+        GetPythonObject() { return m_object.GetPyhonObject(); }
+    private:
+        PythonRefCountedObject m_object;
+    };
+    
+    class PythonDataDictionary
+    {
+    public:
+        
+        PythonDataDictionary ();
+        PythonDataDictionary (PyObject* object);
+        ~PythonDataDictionary ();
+        
+        uint32_t GetSize();
+        
+        PythonDataObject*
+        GetItemForKey (PythonDataString* key);
+        
+        typedef bool (*DictionaryIteratorCallback)(PythonDataString* key, PythonDataDictionary* dict);
+        
+        PythonDataArray*
+        GetKeys ();
+        
+        PythonDataString*
+        GetKeyAtPosition (uint32_t pos);
+        
+        PythonDataObject*
+        GetValueAtPosition (uint32_t pos);
+        
+        void
+        SetItemForKey (PythonDataString* key, PythonDataObject* value);
+        
+        operator bool ()
+        {
+            return m_object.operator bool();
+        }
+        
+        PyObject*
+        GetPythonObject() { return m_object.GetPyhonObject(); }
+    private:
+        PythonRefCountedObject m_object;
+    };
+
+    class PythonDataObject
+    {
+    public:
+        
+        PythonDataObject (PyObject* object);
+        
+        ~PythonDataObject ();
+        
+        PythonDataString*
+        GetStringObject ();
+        
+        PythonDataInteger*
+        GetIntegerObject ();
+        
+        PythonDataArray*
+        GetArrayObject();
+        
+        PythonDataDictionary*
+        GetDictionaryObject();
+        
+        operator bool ()
+        {
+            return m_object.operator bool();
+        }
+        
+        PyObject*
+        GetPythonObject() { return m_object.GetPyhonObject(); }
+        
+    private:
+        PythonRefCountedObject m_object;
+    };
+    
+} // namespace lldb_private
+
+#endif  // liblldb_PythonDataObjects_h_
diff --git a/include/lldb/lldb-forward.h b/include/lldb/lldb-forward.h
index b69593b..7607385 100644
--- a/include/lldb/lldb-forward.h
+++ b/include/lldb/lldb-forward.h
@@ -162,6 +162,11 @@
 class   ProcessLaunchInfo;
 class   Property;
 struct  PropertyDefinition;
+class   PythonDataArray;
+class   PythonDataDictionary;
+class   PythonDataInteger;
+class   PythonDataObject;
+class   PythonDataString;
 class   RegisterContext;
 class   RegisterLocation;
 class   RegisterLocationList;
diff --git a/lldb.xcodeproj/project.pbxproj b/lldb.xcodeproj/project.pbxproj
index 8ffc0cd..75bcda7 100644
--- a/lldb.xcodeproj/project.pbxproj
+++ b/lldb.xcodeproj/project.pbxproj
@@ -528,6 +528,7 @@
 		9475C18F14E5F858001BFC6D /* SBTypeNameSpecifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 9475C18C14E5F826001BFC6D /* SBTypeNameSpecifier.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		949ADF031406F648004833E1 /* ValueObjectConstResultImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949ADF021406F648004833E1 /* ValueObjectConstResultImpl.cpp */; };
 		94B6E76213D88365005F417F /* ValueObjectSyntheticFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */; };
+		94EA1D5C15E6C9B400D4171A /* PythonDataObjects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94EA1D5B15E6C9B400D4171A /* PythonDataObjects.cpp */; };
 		94FA3DE01405D50400833217 /* ValueObjectConstResultChild.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94FA3DDF1405D50300833217 /* ValueObjectConstResultChild.cpp */; };
 		9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A19A6A51163BB7E00E0D453 /* SBValue.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		9A19A6B01163BBB300E0D453 /* SBValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A19A6AD1163BB9800E0D453 /* SBValue.cpp */; };
@@ -1534,6 +1535,8 @@
 		94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectSyntheticFilter.cpp; path = source/Core/ValueObjectSyntheticFilter.cpp; sourceTree = "<group>"; };
 		94E367CC140C4EC4001C7A5A /* modify-python-lldb.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = "modify-python-lldb.py"; sourceTree = "<group>"; };
 		94E367CE140C4EEA001C7A5A /* python-typemaps.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-typemaps.swig"; sourceTree = "<group>"; };
+		94EA1D5A15E6C99B00D4171A /* PythonDataObjects.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PythonDataObjects.h; path = include/lldb/Interpreter/PythonDataObjects.h; sourceTree = "<group>"; };
+		94EA1D5B15E6C9B400D4171A /* PythonDataObjects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PythonDataObjects.cpp; path = source/Interpreter/PythonDataObjects.cpp; sourceTree = "<group>"; };
 		94EBAC8313D9EE26009BA64E /* PythonPointer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PythonPointer.h; path = include/lldb/Utility/PythonPointer.h; sourceTree = "<group>"; };
 		94FA3DDD1405D4E500833217 /* ValueObjectConstResultChild.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectConstResultChild.h; path = include/lldb/Core/ValueObjectConstResultChild.h; sourceTree = "<group>"; };
 		94FA3DDF1405D50300833217 /* ValueObjectConstResultChild.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectConstResultChild.cpp; path = source/Core/ValueObjectConstResultChild.cpp; sourceTree = "<group>"; };
@@ -2907,6 +2910,8 @@
 				B2462246141AD37D00F3D409 /* OptionGroupWatchpoint.cpp */,
 				26ACEC2715E077AE00E94760 /* Property.h */,
 				2640E19E15DC78FD00F23B50 /* Property.cpp */,
+				94EA1D5A15E6C99B00D4171A /* PythonDataObjects.h */,
+				94EA1D5B15E6C9B400D4171A /* PythonDataObjects.cpp */,
 				26BC7DE510F1B7F900F91463 /* ScriptInterpreter.h */,
 				9A82010B10FFB49800182560 /* ScriptInterpreter.cpp */,
 				9A2771FB1135A35C00E6ADB6 /* ScriptInterpreterNone.h */,
@@ -4100,6 +4105,7 @@
 				2640E19F15DC78FD00F23B50 /* Property.cpp in Sources */,
 				26491E3E15E1DB9F00CBFFC2 /* OptionValueRegex.cpp in Sources */,
 				2697A39315E404B1003E682C /* OptionValueArch.cpp in Sources */,
+				94EA1D5C15E6C9B400D4171A /* PythonDataObjects.cpp in Sources */,
 				2698699B15E6CBD0002415FF /* OperatingSystemPython.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
diff --git a/source/Interpreter/PythonDataObjects.cpp b/source/Interpreter/PythonDataObjects.cpp
new file mode 100644
index 0000000..ba4ba23
--- /dev/null
+++ b/source/Interpreter/PythonDataObjects.cpp
@@ -0,0 +1,234 @@
+//===-- PythonDataObjects.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// In order to guarantee correct working with Python, Python.h *MUST* be
+// the *FIRST* header file included here.
+#ifdef LLDB_DISABLE_PYTHON
+
+// Python is disabled in this build
+
+#else
+
+#if defined (__APPLE__)
+#include <Python/Python.h>
+#else
+#include <Python.h>
+#endif
+
+#include "PythonDataObjects.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+PythonDataObject::PythonDataObject (PyObject* object) : m_object(object)
+{
+}
+
+PythonDataString*
+PythonDataObject::GetStringObject ()
+{
+    return new PythonDataString(GetPythonObject());
+}
+    
+PythonDataInteger*
+PythonDataObject::GetIntegerObject ()
+{
+    return new PythonDataInteger(GetPythonObject());
+}
+
+PythonDataArray*
+PythonDataObject::GetArrayObject()
+{
+    return new PythonDataArray(GetPythonObject());
+}
+
+PythonDataDictionary*
+PythonDataObject::GetDictionaryObject()
+{
+    return new PythonDataDictionary(GetPythonObject());
+}
+
+PythonDataInteger::PythonDataInteger (PyObject* object) : m_object(object)
+{
+    if (!PyInt_Check(GetPythonObject()))
+        m_object.Reset();
+}
+
+PythonDataInteger::~PythonDataInteger ()
+{
+}
+
+PythonDataInteger::PythonDataInteger (int64_t value) : m_object(PyInt_FromLong(value))
+{
+}
+
+int64_t
+PythonDataInteger::GetInteger()
+{
+    if (m_object)
+        return PyInt_AsLong(GetPythonObject());
+    else
+        return UINT64_MAX;
+}
+
+void
+PythonDataInteger::SetInteger (int64_t value)
+{
+    m_object.Reset(PyInt_FromLong(value));
+}
+
+PythonDataString::PythonDataString (PyObject* object) : m_object(object)
+{
+    if (!PyString_Check(GetPythonObject()))
+        m_object.Reset();}
+
+PythonDataString::PythonDataString (const char* string) : m_object(PyString_FromString(string))
+{
+}
+
+PythonDataString::~PythonDataString ()
+{
+}
+
+const char*
+PythonDataString::GetString()
+{
+    if (m_object)
+        return PyString_AsString(GetPythonObject());
+    return NULL;
+}
+
+void
+PythonDataString::SetString (const char* string)
+{
+    m_object.Reset(PyString_FromString(string));
+}
+
+PythonDataArray::PythonDataArray (uint32_t count) : m_object(PyList_New(count))
+{
+}
+
+PythonDataArray::PythonDataArray (PyObject* object) : m_object(object)
+{
+    if (!PyList_Check(GetPythonObject()))
+        m_object.Reset();
+}
+
+PythonDataArray::~PythonDataArray ()
+{
+}
+
+uint32_t
+PythonDataArray::GetSize()
+{
+    if (m_object)
+        return PyList_GET_SIZE(GetPythonObject());
+    return 0;
+}
+
+PythonDataObject*
+PythonDataArray::GetItemAtIndex (uint32_t index)
+{
+    if (m_object)
+        return new PythonDataObject(PyList_GetItem(GetPythonObject(), index));
+    return NULL;
+}
+
+void
+PythonDataArray::SetItemAtIndex (uint32_t index, PythonDataObject* object)
+{
+    if (m_object && object && *object)
+        PyList_SetItem(GetPythonObject(), index, object->GetPythonObject());
+}
+
+void
+PythonDataArray::AppendItem (PythonDataObject* object)
+{
+    if (m_object && object && *object)
+        PyList_Append(GetPythonObject(), object->GetPythonObject());
+}
+
+PythonDataDictionary::PythonDataDictionary () : m_object(PyDict_New())
+{
+}
+
+PythonDataDictionary::PythonDataDictionary (PyObject* object) : m_object(object)
+{
+    if (!PyDict_Check(GetPythonObject()))
+        m_object.Reset();
+}
+
+PythonDataDictionary::~PythonDataDictionary ()
+{
+}
+
+uint32_t
+PythonDataDictionary::GetSize()
+{
+    if (m_object)
+        return PyDict_Size(GetPythonObject());
+    return 0;
+}
+
+PythonDataObject*
+PythonDataDictionary::GetItemForKey (PythonDataString* key)
+{
+    if (m_object && key && *key)
+        return new PythonDataObject(PyDict_GetItem(GetPythonObject(), key->GetPythonObject()));
+    return NULL;
+}
+
+PythonDataArray*
+PythonDataDictionary::GetKeys ()
+{
+    if (m_object)
+        return new PythonDataArray(PyDict_Keys(GetPythonObject()));
+    return NULL;
+}
+
+PythonDataString*
+PythonDataDictionary::GetKeyAtPosition (uint32_t pos)
+{
+    PyObject *key, *value;
+    Py_ssize_t pos_iter = 0;
+    
+    if (!m_object)
+        return NULL;
+    
+    while (PyDict_Next(GetPythonObject(), &pos_iter, &key, &value)) {
+        if (pos-- == 0)
+            return new PythonDataString(key);
+    }
+    return NULL;
+}
+
+PythonDataObject*
+PythonDataDictionary::GetValueAtPosition (uint32_t pos)
+{
+    PyObject *key, *value;
+    Py_ssize_t pos_iter = 0;
+    
+    if (!m_object)
+        return NULL;
+    
+    while (PyDict_Next(GetPythonObject(), &pos_iter, &key, &value)) {
+        if (pos-- == 0)
+            return new PythonDataObject(value);
+    }
+    return NULL;
+}
+
+void
+PythonDataDictionary::SetItemForKey (PythonDataString* key, PythonDataObject* value)
+{
+    if (m_object && key && value && *key && *value)
+        PyDict_SetItem(GetPythonObject(), key->GetPythonObject(), value->GetPythonObject());
+}
+
+#endif