12c1f46dcSZachary Turner //===-- PythonDataObjects.cpp ------------------------------------*- C++ -*-===//
22c1f46dcSZachary Turner //
32c1f46dcSZachary Turner //                     The LLVM Compiler Infrastructure
42c1f46dcSZachary Turner //
52c1f46dcSZachary Turner // This file is distributed under the University of Illinois Open Source
62c1f46dcSZachary Turner // License. See LICENSE.TXT for details.
72c1f46dcSZachary Turner //
82c1f46dcSZachary Turner //===----------------------------------------------------------------------===//
92c1f46dcSZachary Turner 
102c1f46dcSZachary Turner #ifdef LLDB_DISABLE_PYTHON
112c1f46dcSZachary Turner 
122c1f46dcSZachary Turner // Python is disabled in this build
132c1f46dcSZachary Turner 
142c1f46dcSZachary Turner #else
152c1f46dcSZachary Turner 
162c1f46dcSZachary Turner #include "lldb-python.h"
172c1f46dcSZachary Turner #include "PythonDataObjects.h"
182c1f46dcSZachary Turner #include "ScriptInterpreterPython.h"
192c1f46dcSZachary Turner 
202c1f46dcSZachary Turner #include "lldb/Core/Stream.h"
212c1f46dcSZachary Turner #include "lldb/Host/File.h"
222c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h"
232c1f46dcSZachary Turner 
242c1f46dcSZachary Turner #include <stdio.h>
252c1f46dcSZachary Turner 
262c1f46dcSZachary Turner using namespace lldb_private;
272c1f46dcSZachary Turner using namespace lldb;
282c1f46dcSZachary Turner 
292c1f46dcSZachary Turner void
302c1f46dcSZachary Turner StructuredPythonObject::Dump(Stream &s) const
312c1f46dcSZachary Turner {
322c1f46dcSZachary Turner     s << "Python Obj: 0x" << GetValue();
332c1f46dcSZachary Turner }
342c1f46dcSZachary Turner 
352c1f46dcSZachary Turner //----------------------------------------------------------------------
362c1f46dcSZachary Turner // PythonObject
372c1f46dcSZachary Turner //----------------------------------------------------------------------
382c1f46dcSZachary Turner 
392c1f46dcSZachary Turner void
402c1f46dcSZachary Turner PythonObject::Dump (Stream &strm) const
412c1f46dcSZachary Turner {
422c1f46dcSZachary Turner     if (m_py_obj)
432c1f46dcSZachary Turner     {
442c1f46dcSZachary Turner         FILE *file = ::tmpfile();
452c1f46dcSZachary Turner         if (file)
462c1f46dcSZachary Turner         {
472c1f46dcSZachary Turner             ::PyObject_Print (m_py_obj, file, 0);
482c1f46dcSZachary Turner             const long length = ftell (file);
492c1f46dcSZachary Turner             if (length)
502c1f46dcSZachary Turner             {
512c1f46dcSZachary Turner                 ::rewind(file);
522c1f46dcSZachary Turner                 std::vector<char> file_contents (length,'\0');
532c1f46dcSZachary Turner                 const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file);
542c1f46dcSZachary Turner                 if (length_read > 0)
552c1f46dcSZachary Turner                     strm.Write (file_contents.data(), length_read);
562c1f46dcSZachary Turner             }
572c1f46dcSZachary Turner             ::fclose (file);
582c1f46dcSZachary Turner         }
592c1f46dcSZachary Turner     }
602c1f46dcSZachary Turner     else
612c1f46dcSZachary Turner         strm.PutCString ("NULL");
622c1f46dcSZachary Turner }
632c1f46dcSZachary Turner 
642c1f46dcSZachary Turner PyObjectType
652c1f46dcSZachary Turner PythonObject::GetObjectType() const
662c1f46dcSZachary Turner {
672c1f46dcSZachary Turner     if (IsNULLOrNone())
682c1f46dcSZachary Turner         return PyObjectType::None;
692c1f46dcSZachary Turner 
702c1f46dcSZachary Turner     if (PyList_Check(m_py_obj))
712c1f46dcSZachary Turner         return PyObjectType::List;
722c1f46dcSZachary Turner     if (PyDict_Check(m_py_obj))
732c1f46dcSZachary Turner         return PyObjectType::Dictionary;
74*22c8efcdSZachary Turner     if (PyUnicode_Check(m_py_obj))
75*22c8efcdSZachary Turner         return PyObjectType::String;
76*22c8efcdSZachary Turner     if (PyLong_Check(m_py_obj))
77*22c8efcdSZachary Turner         return PyObjectType::Integer;
78*22c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
79*22c8efcdSZachary Turner     // These functions don't exist in Python 3.x.  PyString is PyUnicode
80*22c8efcdSZachary Turner     // and PyInt is PyLong.
812c1f46dcSZachary Turner     if (PyString_Check(m_py_obj))
822c1f46dcSZachary Turner         return PyObjectType::String;
83*22c8efcdSZachary Turner     if (PyInt_Check(m_py_obj))
842c1f46dcSZachary Turner         return PyObjectType::Integer;
85*22c8efcdSZachary Turner #endif
862c1f46dcSZachary Turner     return PyObjectType::Unknown;
872c1f46dcSZachary Turner }
882c1f46dcSZachary Turner 
892c1f46dcSZachary Turner PythonString
902c1f46dcSZachary Turner PythonObject::Repr ()
912c1f46dcSZachary Turner {
922c1f46dcSZachary Turner     if (!m_py_obj)
932c1f46dcSZachary Turner         return PythonString ();
942c1f46dcSZachary Turner     PyObject *repr = PyObject_Repr(m_py_obj);
952c1f46dcSZachary Turner     if (!repr)
962c1f46dcSZachary Turner         return PythonString ();
972c1f46dcSZachary Turner     return PythonString(repr);
982c1f46dcSZachary Turner }
992c1f46dcSZachary Turner 
1002c1f46dcSZachary Turner PythonString
1012c1f46dcSZachary Turner PythonObject::Str ()
1022c1f46dcSZachary Turner {
1032c1f46dcSZachary Turner     if (!m_py_obj)
1042c1f46dcSZachary Turner         return PythonString ();
1052c1f46dcSZachary Turner     PyObject *str = PyObject_Str(m_py_obj);
1062c1f46dcSZachary Turner     if (!str)
1072c1f46dcSZachary Turner         return PythonString ();
1082c1f46dcSZachary Turner     return PythonString(str);
1092c1f46dcSZachary Turner }
1102c1f46dcSZachary Turner 
1112c1f46dcSZachary Turner bool
1122c1f46dcSZachary Turner PythonObject::IsNULLOrNone () const
1132c1f46dcSZachary Turner {
1142c1f46dcSZachary Turner     return ((m_py_obj == nullptr) || (m_py_obj == Py_None));
1152c1f46dcSZachary Turner }
1162c1f46dcSZachary Turner 
1172c1f46dcSZachary Turner StructuredData::ObjectSP
1182c1f46dcSZachary Turner PythonObject::CreateStructuredObject() const
1192c1f46dcSZachary Turner {
1202c1f46dcSZachary Turner     switch (GetObjectType())
1212c1f46dcSZachary Turner     {
1222c1f46dcSZachary Turner         case PyObjectType::Dictionary:
1232c1f46dcSZachary Turner             return PythonDictionary(m_py_obj).CreateStructuredDictionary();
1242c1f46dcSZachary Turner         case PyObjectType::Integer:
1252c1f46dcSZachary Turner             return PythonInteger(m_py_obj).CreateStructuredInteger();
1262c1f46dcSZachary Turner         case PyObjectType::List:
1272c1f46dcSZachary Turner             return PythonList(m_py_obj).CreateStructuredArray();
1282c1f46dcSZachary Turner         case PyObjectType::String:
1292c1f46dcSZachary Turner             return PythonString(m_py_obj).CreateStructuredString();
1302c1f46dcSZachary Turner         case PyObjectType::None:
1312c1f46dcSZachary Turner             return StructuredData::ObjectSP();
1322c1f46dcSZachary Turner         default:
1332c1f46dcSZachary Turner             return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
1342c1f46dcSZachary Turner     }
1352c1f46dcSZachary Turner }
1362c1f46dcSZachary Turner 
1372c1f46dcSZachary Turner //----------------------------------------------------------------------
1382c1f46dcSZachary Turner // PythonString
1392c1f46dcSZachary Turner //----------------------------------------------------------------------
1402c1f46dcSZachary Turner 
1412c1f46dcSZachary Turner PythonString::PythonString (PyObject *py_obj) :
1422c1f46dcSZachary Turner     PythonObject()
1432c1f46dcSZachary Turner {
1442c1f46dcSZachary Turner     Reset(py_obj); // Use "Reset()" to ensure that py_obj is a string
1452c1f46dcSZachary Turner }
1462c1f46dcSZachary Turner 
1472c1f46dcSZachary Turner PythonString::PythonString (const PythonObject &object) :
1482c1f46dcSZachary Turner     PythonObject()
1492c1f46dcSZachary Turner {
1502c1f46dcSZachary Turner     Reset(object.get()); // Use "Reset()" to ensure that py_obj is a string
1512c1f46dcSZachary Turner }
1522c1f46dcSZachary Turner 
153*22c8efcdSZachary Turner PythonString::PythonString(llvm::StringRef string)
154*22c8efcdSZachary Turner     : PythonObject()
1552c1f46dcSZachary Turner {
156*22c8efcdSZachary Turner     SetString(string);
1572c1f46dcSZachary Turner }
1582c1f46dcSZachary Turner 
159*22c8efcdSZachary Turner PythonString::PythonString(const char *string)
160*22c8efcdSZachary Turner     : PythonObject()
1612c1f46dcSZachary Turner {
162*22c8efcdSZachary Turner     SetString(llvm::StringRef(string));
1632c1f46dcSZachary Turner }
1642c1f46dcSZachary Turner 
1652c1f46dcSZachary Turner PythonString::PythonString () :
1662c1f46dcSZachary Turner     PythonObject()
1672c1f46dcSZachary Turner {
1682c1f46dcSZachary Turner }
1692c1f46dcSZachary Turner 
1702c1f46dcSZachary Turner PythonString::~PythonString ()
1712c1f46dcSZachary Turner {
1722c1f46dcSZachary Turner }
1732c1f46dcSZachary Turner 
1742c1f46dcSZachary Turner bool
175*22c8efcdSZachary Turner PythonString::Check(PyObject *py_obj)
176*22c8efcdSZachary Turner {
177*22c8efcdSZachary Turner     if (!py_obj)
178*22c8efcdSZachary Turner         return false;
179*22c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
180*22c8efcdSZachary Turner     // Python 3 does not have PyString objects, only PyUnicode.
181*22c8efcdSZachary Turner     return PyUnicode_Check(py_obj);
182*22c8efcdSZachary Turner #else
183*22c8efcdSZachary Turner     return PyUnicode_Check(py_obj) || PyString_Check(py_obj);
184*22c8efcdSZachary Turner #endif
185*22c8efcdSZachary Turner }
186*22c8efcdSZachary Turner 
187*22c8efcdSZachary Turner bool
1882c1f46dcSZachary Turner PythonString::Reset(PyObject *py_obj)
1892c1f46dcSZachary Turner {
190*22c8efcdSZachary Turner     if (!PythonString::Check(py_obj))
191*22c8efcdSZachary Turner     {
1922c1f46dcSZachary Turner         PythonObject::Reset(nullptr);
193*22c8efcdSZachary Turner         return false;
194*22c8efcdSZachary Turner     }
195*22c8efcdSZachary Turner 
196*22c8efcdSZachary Turner // Convert this to a PyBytes object, and only store the PyBytes.  Note that in
197*22c8efcdSZachary Turner // Python 2.x, PyString and PyUnicode are interchangeable, and PyBytes is an alias
198*22c8efcdSZachary Turner // of PyString.  So on 2.x, if we get into this branch, we already have a PyBytes.
199*22c8efcdSZachary Turner     //#if PY_MAJOR_VERSION >= 3
200*22c8efcdSZachary Turner     if (PyUnicode_Check(py_obj))
201*22c8efcdSZachary Turner     {
202*22c8efcdSZachary Turner         PyObject *unicode = py_obj;
203*22c8efcdSZachary Turner         py_obj = PyUnicode_AsUTF8String(py_obj);
204*22c8efcdSZachary Turner         Py_XDECREF(unicode);
205*22c8efcdSZachary Turner     }
206*22c8efcdSZachary Turner     //#endif
207*22c8efcdSZachary Turner 
208*22c8efcdSZachary Turner     assert(PyBytes_Check(py_obj) && "PythonString::Reset received a non-string");
209*22c8efcdSZachary Turner     return PythonObject::Reset(py_obj);
2102c1f46dcSZachary Turner }
2112c1f46dcSZachary Turner 
2122c1f46dcSZachary Turner llvm::StringRef
2132c1f46dcSZachary Turner PythonString::GetString() const
2142c1f46dcSZachary Turner {
2152c1f46dcSZachary Turner     if (m_py_obj)
216*22c8efcdSZachary Turner     {
217*22c8efcdSZachary Turner         Py_ssize_t size;
218*22c8efcdSZachary Turner         char *c;
219*22c8efcdSZachary Turner         PyBytes_AsStringAndSize(m_py_obj, &c, &size);
220*22c8efcdSZachary Turner         return llvm::StringRef(c, size);
221*22c8efcdSZachary Turner     }
2222c1f46dcSZachary Turner     return llvm::StringRef();
2232c1f46dcSZachary Turner }
2242c1f46dcSZachary Turner 
2252c1f46dcSZachary Turner size_t
2262c1f46dcSZachary Turner PythonString::GetSize() const
2272c1f46dcSZachary Turner {
2282c1f46dcSZachary Turner     if (m_py_obj)
229*22c8efcdSZachary Turner         return PyBytes_Size(m_py_obj);
2302c1f46dcSZachary Turner     return 0;
2312c1f46dcSZachary Turner }
2322c1f46dcSZachary Turner 
2332c1f46dcSZachary Turner void
2342c1f46dcSZachary Turner PythonString::SetString (llvm::StringRef string)
2352c1f46dcSZachary Turner {
236*22c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
237*22c8efcdSZachary Turner     PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
238*22c8efcdSZachary Turner     PyObject *bytes = PyUnicode_AsUTF8String(unicode);
239*22c8efcdSZachary Turner     PythonObject::Reset(bytes);
240*22c8efcdSZachary Turner     Py_XDECREF(unicode);
241*22c8efcdSZachary Turner #else
2422c1f46dcSZachary Turner     PythonObject::Reset(PyString_FromStringAndSize(string.data(), string.size()));
243*22c8efcdSZachary Turner #endif
2442c1f46dcSZachary Turner }
2452c1f46dcSZachary Turner 
2462c1f46dcSZachary Turner StructuredData::StringSP
2472c1f46dcSZachary Turner PythonString::CreateStructuredString() const
2482c1f46dcSZachary Turner {
2492c1f46dcSZachary Turner     StructuredData::StringSP result(new StructuredData::String);
2502c1f46dcSZachary Turner     result->SetValue(GetString());
2512c1f46dcSZachary Turner     return result;
2522c1f46dcSZachary Turner }
2532c1f46dcSZachary Turner 
2542c1f46dcSZachary Turner //----------------------------------------------------------------------
2552c1f46dcSZachary Turner // PythonInteger
2562c1f46dcSZachary Turner //----------------------------------------------------------------------
2572c1f46dcSZachary Turner 
2582c1f46dcSZachary Turner PythonInteger::PythonInteger (PyObject *py_obj) :
2592c1f46dcSZachary Turner     PythonObject()
2602c1f46dcSZachary Turner {
2612c1f46dcSZachary Turner     Reset(py_obj); // Use "Reset()" to ensure that py_obj is a integer type
2622c1f46dcSZachary Turner }
2632c1f46dcSZachary Turner 
2642c1f46dcSZachary Turner PythonInteger::PythonInteger (const PythonObject &object) :
2652c1f46dcSZachary Turner     PythonObject()
2662c1f46dcSZachary Turner {
2672c1f46dcSZachary Turner     Reset(object.get()); // Use "Reset()" to ensure that py_obj is a integer type
2682c1f46dcSZachary Turner }
2692c1f46dcSZachary Turner 
2702c1f46dcSZachary Turner PythonInteger::PythonInteger (int64_t value) :
2712c1f46dcSZachary Turner     PythonObject()
2722c1f46dcSZachary Turner {
2732c1f46dcSZachary Turner     SetInteger (value);
2742c1f46dcSZachary Turner }
2752c1f46dcSZachary Turner 
2762c1f46dcSZachary Turner 
2772c1f46dcSZachary Turner PythonInteger::~PythonInteger ()
2782c1f46dcSZachary Turner {
2792c1f46dcSZachary Turner }
2802c1f46dcSZachary Turner 
2812c1f46dcSZachary Turner bool
282*22c8efcdSZachary Turner PythonInteger::Check(PyObject *py_obj)
2832c1f46dcSZachary Turner {
284*22c8efcdSZachary Turner     if (!py_obj)
285*22c8efcdSZachary Turner         return false;
286*22c8efcdSZachary Turner 
287*22c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
288*22c8efcdSZachary Turner     // Python 3 does not have PyInt_Check.  There is only one type of
289*22c8efcdSZachary Turner     // integral value, long.
290*22c8efcdSZachary Turner     return PyLong_Check(py_obj);
291*22c8efcdSZachary Turner #else
292*22c8efcdSZachary Turner     return PyLong_Check(py_obj) || PyInt_Check(py_obj);
293*22c8efcdSZachary Turner #endif
2942c1f46dcSZachary Turner }
2952c1f46dcSZachary Turner 
296*22c8efcdSZachary Turner bool
297*22c8efcdSZachary Turner PythonInteger::Reset(PyObject *py_obj)
298*22c8efcdSZachary Turner {
299*22c8efcdSZachary Turner     if (!PythonInteger::Check(py_obj))
300*22c8efcdSZachary Turner     {
3012c1f46dcSZachary Turner         PythonObject::Reset(nullptr);
302*22c8efcdSZachary Turner         return false;
303*22c8efcdSZachary Turner     }
304*22c8efcdSZachary Turner 
305*22c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
306*22c8efcdSZachary Turner     // Always store this as a PyLong, which makes interoperability between
307*22c8efcdSZachary Turner     // Python 2.x and Python 3.x easier.  This is only necessary in 2.x,
308*22c8efcdSZachary Turner     // since 3.x doesn't even have a PyInt.
309*22c8efcdSZachary Turner     if (PyInt_Check(py_obj))
310*22c8efcdSZachary Turner     {
311*22c8efcdSZachary Turner         PyObject *py_long = PyLong_FromLongLong(PyInt_AsLong(py_obj));
312*22c8efcdSZachary Turner         Py_XDECREF(py_obj);
313*22c8efcdSZachary Turner         py_obj = py_long;
314*22c8efcdSZachary Turner     }
315*22c8efcdSZachary Turner #endif
316*22c8efcdSZachary Turner 
317*22c8efcdSZachary Turner     assert(PyLong_Check(py_obj) && "Couldn't get a PyLong from this PyObject");
318*22c8efcdSZachary Turner 
319*22c8efcdSZachary Turner     return PythonObject::Reset(py_obj);
3202c1f46dcSZachary Turner }
3212c1f46dcSZachary Turner 
3222c1f46dcSZachary Turner int64_t
3232c1f46dcSZachary Turner PythonInteger::GetInteger() const
3242c1f46dcSZachary Turner {
3252c1f46dcSZachary Turner     if (m_py_obj)
3262c1f46dcSZachary Turner     {
327*22c8efcdSZachary Turner         assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
328*22c8efcdSZachary Turner 
3292c1f46dcSZachary Turner         return PyLong_AsLongLong(m_py_obj);
3302c1f46dcSZachary Turner     }
3312c1f46dcSZachary Turner     return UINT64_MAX;
3322c1f46dcSZachary Turner }
3332c1f46dcSZachary Turner 
3342c1f46dcSZachary Turner void
3352c1f46dcSZachary Turner PythonInteger::SetInteger (int64_t value)
3362c1f46dcSZachary Turner {
3372c1f46dcSZachary Turner     PythonObject::Reset(PyLong_FromLongLong(value));
3382c1f46dcSZachary Turner }
3392c1f46dcSZachary Turner 
3402c1f46dcSZachary Turner StructuredData::IntegerSP
3412c1f46dcSZachary Turner PythonInteger::CreateStructuredInteger() const
3422c1f46dcSZachary Turner {
3432c1f46dcSZachary Turner     StructuredData::IntegerSP result(new StructuredData::Integer);
3442c1f46dcSZachary Turner     result->SetValue(GetInteger());
3452c1f46dcSZachary Turner     return result;
3462c1f46dcSZachary Turner }
3472c1f46dcSZachary Turner 
3482c1f46dcSZachary Turner //----------------------------------------------------------------------
3492c1f46dcSZachary Turner // PythonList
3502c1f46dcSZachary Turner //----------------------------------------------------------------------
3512c1f46dcSZachary Turner 
352*22c8efcdSZachary Turner PythonList::PythonList()
353*22c8efcdSZachary Turner     : PythonObject(PyList_New(0))
3542c1f46dcSZachary Turner {
3552c1f46dcSZachary Turner }
3562c1f46dcSZachary Turner 
3572c1f46dcSZachary Turner PythonList::PythonList (PyObject *py_obj) :
3582c1f46dcSZachary Turner     PythonObject()
3592c1f46dcSZachary Turner {
3602c1f46dcSZachary Turner     Reset(py_obj); // Use "Reset()" to ensure that py_obj is a list
3612c1f46dcSZachary Turner }
3622c1f46dcSZachary Turner 
3632c1f46dcSZachary Turner 
3642c1f46dcSZachary Turner PythonList::PythonList (const PythonObject &object) :
3652c1f46dcSZachary Turner     PythonObject()
3662c1f46dcSZachary Turner {
3672c1f46dcSZachary Turner     Reset(object.get()); // Use "Reset()" to ensure that py_obj is a list
3682c1f46dcSZachary Turner }
3692c1f46dcSZachary Turner 
3702c1f46dcSZachary Turner PythonList::~PythonList ()
3712c1f46dcSZachary Turner {
3722c1f46dcSZachary Turner }
3732c1f46dcSZachary Turner 
3742c1f46dcSZachary Turner bool
375*22c8efcdSZachary Turner PythonList::Check(PyObject *py_obj)
376*22c8efcdSZachary Turner {
377*22c8efcdSZachary Turner     if (!py_obj)
378*22c8efcdSZachary Turner         return false;
379*22c8efcdSZachary Turner     return PyList_Check(py_obj);
380*22c8efcdSZachary Turner }
381*22c8efcdSZachary Turner 
382*22c8efcdSZachary Turner bool
3832c1f46dcSZachary Turner PythonList::Reset(PyObject *py_obj)
3842c1f46dcSZachary Turner {
385*22c8efcdSZachary Turner     if (!PythonList::Check(py_obj))
386*22c8efcdSZachary Turner     {
3872c1f46dcSZachary Turner         PythonObject::Reset(nullptr);
388*22c8efcdSZachary Turner         return false;
389*22c8efcdSZachary Turner     }
390*22c8efcdSZachary Turner 
391*22c8efcdSZachary Turner     return PythonObject::Reset(py_obj);
3922c1f46dcSZachary Turner }
3932c1f46dcSZachary Turner 
3942c1f46dcSZachary Turner uint32_t
3952c1f46dcSZachary Turner PythonList::GetSize() const
3962c1f46dcSZachary Turner {
3972c1f46dcSZachary Turner     if (m_py_obj)
3982c1f46dcSZachary Turner         return PyList_GET_SIZE(m_py_obj);
3992c1f46dcSZachary Turner     return 0;
4002c1f46dcSZachary Turner }
4012c1f46dcSZachary Turner 
4022c1f46dcSZachary Turner PythonObject
4032c1f46dcSZachary Turner PythonList::GetItemAtIndex(uint32_t index) const
4042c1f46dcSZachary Turner {
4052c1f46dcSZachary Turner     if (m_py_obj)
4062c1f46dcSZachary Turner         return PythonObject(PyList_GetItem(m_py_obj, index));
4072c1f46dcSZachary Turner     return PythonObject();
4082c1f46dcSZachary Turner }
4092c1f46dcSZachary Turner 
4102c1f46dcSZachary Turner void
4112c1f46dcSZachary Turner PythonList::SetItemAtIndex (uint32_t index, const PythonObject & object)
4122c1f46dcSZachary Turner {
4132c1f46dcSZachary Turner     if (m_py_obj && object)
4142c1f46dcSZachary Turner         PyList_SetItem(m_py_obj, index, object.get());
4152c1f46dcSZachary Turner }
4162c1f46dcSZachary Turner 
4172c1f46dcSZachary Turner void
4182c1f46dcSZachary Turner PythonList::AppendItem (const PythonObject &object)
4192c1f46dcSZachary Turner {
4202c1f46dcSZachary Turner     if (m_py_obj && object)
4212c1f46dcSZachary Turner         PyList_Append(m_py_obj, object.get());
4222c1f46dcSZachary Turner }
4232c1f46dcSZachary Turner 
4242c1f46dcSZachary Turner StructuredData::ArraySP
4252c1f46dcSZachary Turner PythonList::CreateStructuredArray() const
4262c1f46dcSZachary Turner {
4272c1f46dcSZachary Turner     StructuredData::ArraySP result(new StructuredData::Array);
4282c1f46dcSZachary Turner     uint32_t count = GetSize();
4292c1f46dcSZachary Turner     for (uint32_t i = 0; i < count; ++i)
4302c1f46dcSZachary Turner     {
4312c1f46dcSZachary Turner         PythonObject obj = GetItemAtIndex(i);
4322c1f46dcSZachary Turner         result->AddItem(obj.CreateStructuredObject());
4332c1f46dcSZachary Turner     }
4342c1f46dcSZachary Turner     return result;
4352c1f46dcSZachary Turner }
4362c1f46dcSZachary Turner 
4372c1f46dcSZachary Turner //----------------------------------------------------------------------
4382c1f46dcSZachary Turner // PythonDictionary
4392c1f46dcSZachary Turner //----------------------------------------------------------------------
4402c1f46dcSZachary Turner 
441*22c8efcdSZachary Turner PythonDictionary::PythonDictionary()
442*22c8efcdSZachary Turner     : PythonObject(PyDict_New())
4432c1f46dcSZachary Turner {
4442c1f46dcSZachary Turner }
4452c1f46dcSZachary Turner 
4462c1f46dcSZachary Turner PythonDictionary::PythonDictionary (PyObject *py_obj) :
4472c1f46dcSZachary Turner     PythonObject(py_obj)
4482c1f46dcSZachary Turner {
4492c1f46dcSZachary Turner     Reset(py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
4502c1f46dcSZachary Turner }
4512c1f46dcSZachary Turner 
4522c1f46dcSZachary Turner 
4532c1f46dcSZachary Turner PythonDictionary::PythonDictionary (const PythonObject &object) :
4542c1f46dcSZachary Turner     PythonObject()
4552c1f46dcSZachary Turner {
4562c1f46dcSZachary Turner     Reset(object.get()); // Use "Reset()" to ensure that py_obj is a dictionary
4572c1f46dcSZachary Turner }
4582c1f46dcSZachary Turner 
4592c1f46dcSZachary Turner PythonDictionary::~PythonDictionary ()
4602c1f46dcSZachary Turner {
4612c1f46dcSZachary Turner }
4622c1f46dcSZachary Turner 
4632c1f46dcSZachary Turner bool
464*22c8efcdSZachary Turner PythonDictionary::Check(PyObject *py_obj)
465*22c8efcdSZachary Turner {
466*22c8efcdSZachary Turner     if (!py_obj)
467*22c8efcdSZachary Turner         return false;
468*22c8efcdSZachary Turner 
469*22c8efcdSZachary Turner     return PyDict_Check(py_obj);
470*22c8efcdSZachary Turner }
471*22c8efcdSZachary Turner 
472*22c8efcdSZachary Turner bool
4732c1f46dcSZachary Turner PythonDictionary::Reset(PyObject *py_obj)
4742c1f46dcSZachary Turner {
475*22c8efcdSZachary Turner     if (!PythonDictionary::Check(py_obj))
476*22c8efcdSZachary Turner     {
4772c1f46dcSZachary Turner         PythonObject::Reset(nullptr);
478*22c8efcdSZachary Turner         return false;
479*22c8efcdSZachary Turner     }
480*22c8efcdSZachary Turner 
481*22c8efcdSZachary Turner     return PythonObject::Reset(py_obj);
4822c1f46dcSZachary Turner }
4832c1f46dcSZachary Turner 
4842c1f46dcSZachary Turner uint32_t
4852c1f46dcSZachary Turner PythonDictionary::GetSize() const
4862c1f46dcSZachary Turner {
4872c1f46dcSZachary Turner     if (m_py_obj)
4882c1f46dcSZachary Turner         return PyDict_Size(m_py_obj);
4892c1f46dcSZachary Turner     return 0;
4902c1f46dcSZachary Turner }
4912c1f46dcSZachary Turner 
4922c1f46dcSZachary Turner PythonObject
4932c1f46dcSZachary Turner PythonDictionary::GetItemForKey (const char *key) const
4942c1f46dcSZachary Turner {
4952c1f46dcSZachary Turner     if (key && key[0])
4962c1f46dcSZachary Turner     {
4972c1f46dcSZachary Turner         PythonString python_key(key);
4982c1f46dcSZachary Turner         return GetItemForKey(python_key);
4992c1f46dcSZachary Turner     }
5002c1f46dcSZachary Turner     return PythonObject();
5012c1f46dcSZachary Turner }
5022c1f46dcSZachary Turner 
5032c1f46dcSZachary Turner 
5042c1f46dcSZachary Turner PythonObject
5052c1f46dcSZachary Turner PythonDictionary::GetItemForKey (const PythonString &key) const
5062c1f46dcSZachary Turner {
5072c1f46dcSZachary Turner     if (m_py_obj && key)
5082c1f46dcSZachary Turner         return PythonObject(PyDict_GetItem(m_py_obj, key.get()));
5092c1f46dcSZachary Turner     return PythonObject();
5102c1f46dcSZachary Turner }
5112c1f46dcSZachary Turner 
5122c1f46dcSZachary Turner 
5132c1f46dcSZachary Turner const char *
5142c1f46dcSZachary Turner PythonDictionary::GetItemForKeyAsString (const PythonString &key, const char *fail_value) const
5152c1f46dcSZachary Turner {
5162c1f46dcSZachary Turner     if (m_py_obj && key)
5172c1f46dcSZachary Turner     {
5182c1f46dcSZachary Turner         PyObject *py_obj = PyDict_GetItem(m_py_obj, key.get());
519*22c8efcdSZachary Turner         if (py_obj && PythonString::Check(py_obj))
520*22c8efcdSZachary Turner         {
521*22c8efcdSZachary Turner             PythonString str(py_obj);
522*22c8efcdSZachary Turner             return str.GetString().data();
523*22c8efcdSZachary Turner         }
5242c1f46dcSZachary Turner     }
5252c1f46dcSZachary Turner     return fail_value;
5262c1f46dcSZachary Turner }
5272c1f46dcSZachary Turner 
5282c1f46dcSZachary Turner int64_t
5292c1f46dcSZachary Turner PythonDictionary::GetItemForKeyAsInteger (const PythonString &key, int64_t fail_value) const
5302c1f46dcSZachary Turner {
5312c1f46dcSZachary Turner     if (m_py_obj && key)
5322c1f46dcSZachary Turner     {
5332c1f46dcSZachary Turner         PyObject *py_obj = PyDict_GetItem(m_py_obj, key.get());
534*22c8efcdSZachary Turner         if (PythonInteger::Check(py_obj))
5352c1f46dcSZachary Turner         {
536*22c8efcdSZachary Turner             PythonInteger int_obj(py_obj);
537*22c8efcdSZachary Turner             return int_obj.GetInteger();
5382c1f46dcSZachary Turner         }
5392c1f46dcSZachary Turner     }
5402c1f46dcSZachary Turner     return fail_value;
5412c1f46dcSZachary Turner }
5422c1f46dcSZachary Turner 
5432c1f46dcSZachary Turner PythonList
5442c1f46dcSZachary Turner PythonDictionary::GetKeys () const
5452c1f46dcSZachary Turner {
5462c1f46dcSZachary Turner     if (m_py_obj)
5472c1f46dcSZachary Turner         return PythonList(PyDict_Keys(m_py_obj));
548*22c8efcdSZachary Turner     return PythonList();
5492c1f46dcSZachary Turner }
5502c1f46dcSZachary Turner 
5512c1f46dcSZachary Turner PythonString
5522c1f46dcSZachary Turner PythonDictionary::GetKeyAtPosition (uint32_t pos) const
5532c1f46dcSZachary Turner {
5542c1f46dcSZachary Turner     PyObject *key, *value;
5552c1f46dcSZachary Turner     Py_ssize_t pos_iter = 0;
5562c1f46dcSZachary Turner 
5572c1f46dcSZachary Turner     if (m_py_obj)
5582c1f46dcSZachary Turner     {
5592c1f46dcSZachary Turner         while (PyDict_Next(m_py_obj, &pos_iter, &key, &value))
5602c1f46dcSZachary Turner         {
5612c1f46dcSZachary Turner             if (pos-- == 0)
5622c1f46dcSZachary Turner                 return PythonString(key);
5632c1f46dcSZachary Turner         }
5642c1f46dcSZachary Turner     }
5652c1f46dcSZachary Turner     return PythonString();
5662c1f46dcSZachary Turner }
5672c1f46dcSZachary Turner 
5682c1f46dcSZachary Turner PythonObject
5692c1f46dcSZachary Turner PythonDictionary::GetValueAtPosition (uint32_t pos) const
5702c1f46dcSZachary Turner {
5712c1f46dcSZachary Turner     PyObject *key, *value;
5722c1f46dcSZachary Turner     Py_ssize_t pos_iter = 0;
5732c1f46dcSZachary Turner 
5742c1f46dcSZachary Turner     if (!m_py_obj)
5752c1f46dcSZachary Turner         return PythonObject();
5762c1f46dcSZachary Turner 
5772c1f46dcSZachary Turner     while (PyDict_Next(m_py_obj, &pos_iter, &key, &value)) {
5782c1f46dcSZachary Turner         if (pos-- == 0)
5792c1f46dcSZachary Turner             return PythonObject(value);
5802c1f46dcSZachary Turner     }
5812c1f46dcSZachary Turner     return PythonObject();
5822c1f46dcSZachary Turner }
5832c1f46dcSZachary Turner 
5842c1f46dcSZachary Turner void
5852c1f46dcSZachary Turner PythonDictionary::SetItemForKey (const PythonString &key, PyObject *value)
5862c1f46dcSZachary Turner {
5872c1f46dcSZachary Turner     if (m_py_obj && key && value)
5882c1f46dcSZachary Turner         PyDict_SetItem(m_py_obj, key.get(), value);
5892c1f46dcSZachary Turner }
5902c1f46dcSZachary Turner 
5912c1f46dcSZachary Turner void
5922c1f46dcSZachary Turner PythonDictionary::SetItemForKey (const PythonString &key, const PythonObject &value)
5932c1f46dcSZachary Turner {
5942c1f46dcSZachary Turner     if (m_py_obj && key && value)
5952c1f46dcSZachary Turner         PyDict_SetItem(m_py_obj, key.get(), value.get());
5962c1f46dcSZachary Turner }
5972c1f46dcSZachary Turner 
5982c1f46dcSZachary Turner StructuredData::DictionarySP
5992c1f46dcSZachary Turner PythonDictionary::CreateStructuredDictionary() const
6002c1f46dcSZachary Turner {
6012c1f46dcSZachary Turner     StructuredData::DictionarySP result(new StructuredData::Dictionary);
6022c1f46dcSZachary Turner     PythonList keys(GetKeys());
6032c1f46dcSZachary Turner     uint32_t num_keys = keys.GetSize();
6042c1f46dcSZachary Turner     for (uint32_t i = 0; i < num_keys; ++i)
6052c1f46dcSZachary Turner     {
6062c1f46dcSZachary Turner         PythonObject key = keys.GetItemAtIndex(i);
6072c1f46dcSZachary Turner         PythonString key_str = key.Str();
6082c1f46dcSZachary Turner         PythonObject value = GetItemForKey(key);
6092c1f46dcSZachary Turner         StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
6102c1f46dcSZachary Turner         result->AddItem(key_str.GetString(), structured_value);
6112c1f46dcSZachary Turner     }
6122c1f46dcSZachary Turner     return result;
6132c1f46dcSZachary Turner }
6142c1f46dcSZachary Turner 
6152c1f46dcSZachary Turner #endif
616