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 {
67f8b22f8fSZachary Turner     if (!IsAllocated())
682c1f46dcSZachary Turner         return PyObjectType::None;
692c1f46dcSZachary Turner 
7018426935SZachary Turner     if (PythonList::Check(m_py_obj))
712c1f46dcSZachary Turner         return PyObjectType::List;
7218426935SZachary Turner     if (PythonDictionary::Check(m_py_obj))
732c1f46dcSZachary Turner         return PyObjectType::Dictionary;
7418426935SZachary Turner     if (PythonString::Check(m_py_obj))
7522c8efcdSZachary Turner         return PyObjectType::String;
7618426935SZachary Turner     if (PythonInteger::Check(m_py_obj))
7722c8efcdSZachary Turner         return PyObjectType::Integer;
789c40264fSZachary Turner     if (PythonFile::Check(m_py_obj))
799c40264fSZachary Turner         return PyObjectType::File;
802c1f46dcSZachary Turner     return PyObjectType::Unknown;
812c1f46dcSZachary Turner }
822c1f46dcSZachary Turner 
832c1f46dcSZachary Turner PythonString
842c1f46dcSZachary Turner PythonObject::Repr()
852c1f46dcSZachary Turner {
862c1f46dcSZachary Turner     if (!m_py_obj)
872c1f46dcSZachary Turner         return PythonString();
882c1f46dcSZachary Turner     PyObject *repr = PyObject_Repr(m_py_obj);
892c1f46dcSZachary Turner     if (!repr)
902c1f46dcSZachary Turner         return PythonString();
91f8b22f8fSZachary Turner     return PythonString(PyRefType::Owned, repr);
922c1f46dcSZachary Turner }
932c1f46dcSZachary Turner 
942c1f46dcSZachary Turner PythonString
952c1f46dcSZachary Turner PythonObject::Str()
962c1f46dcSZachary Turner {
972c1f46dcSZachary Turner     if (!m_py_obj)
982c1f46dcSZachary Turner         return PythonString();
992c1f46dcSZachary Turner     PyObject *str = PyObject_Str(m_py_obj);
1002c1f46dcSZachary Turner     if (!str)
1012c1f46dcSZachary Turner         return PythonString();
102f8b22f8fSZachary Turner     return PythonString(PyRefType::Owned, str);
1032c1f46dcSZachary Turner }
1042c1f46dcSZachary Turner 
1052c1f46dcSZachary Turner bool
1069c40264fSZachary Turner PythonObject::HasAttribute(llvm::StringRef attr) const
1079c40264fSZachary Turner {
1089c40264fSZachary Turner     if (!IsValid())
1099c40264fSZachary Turner         return false;
1109c40264fSZachary Turner     PythonString py_attr(attr);
1119c40264fSZachary Turner     return !!PyObject_HasAttr(m_py_obj, py_attr.get());
1129c40264fSZachary Turner }
1139c40264fSZachary Turner 
1147d6d218eSZachary Turner PythonObject
1157d6d218eSZachary Turner PythonObject::GetAttributeValue(llvm::StringRef attr) const
1167d6d218eSZachary Turner {
1177d6d218eSZachary Turner     if (!IsValid())
1187d6d218eSZachary Turner         return PythonObject();
1197d6d218eSZachary Turner 
1207d6d218eSZachary Turner     PythonString py_attr(attr);
1217d6d218eSZachary Turner     if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
1227d6d218eSZachary Turner         return PythonObject();
1237d6d218eSZachary Turner 
1247d6d218eSZachary Turner     return PythonObject(PyRefType::Owned,
1257d6d218eSZachary Turner         PyObject_GetAttr(m_py_obj, py_attr.get()));
1267d6d218eSZachary Turner }
1277d6d218eSZachary Turner 
1289c40264fSZachary Turner bool
129f8b22f8fSZachary Turner PythonObject::IsNone() const
1302c1f46dcSZachary Turner {
131f8b22f8fSZachary Turner     return m_py_obj == Py_None;
132f8b22f8fSZachary Turner }
133f8b22f8fSZachary Turner 
134f8b22f8fSZachary Turner bool
135f8b22f8fSZachary Turner PythonObject::IsValid() const
136f8b22f8fSZachary Turner {
137f8b22f8fSZachary Turner     return m_py_obj != nullptr;
138f8b22f8fSZachary Turner }
139f8b22f8fSZachary Turner 
140f8b22f8fSZachary Turner bool
141f8b22f8fSZachary Turner PythonObject::IsAllocated() const
142f8b22f8fSZachary Turner {
143f8b22f8fSZachary Turner     return IsValid() && !IsNone();
1442c1f46dcSZachary Turner }
1452c1f46dcSZachary Turner 
1462c1f46dcSZachary Turner StructuredData::ObjectSP
1472c1f46dcSZachary Turner PythonObject::CreateStructuredObject() const
1482c1f46dcSZachary Turner {
1492c1f46dcSZachary Turner     switch (GetObjectType())
1502c1f46dcSZachary Turner     {
1512c1f46dcSZachary Turner         case PyObjectType::Dictionary:
152f8b22f8fSZachary Turner             return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary();
1532c1f46dcSZachary Turner         case PyObjectType::Integer:
154f8b22f8fSZachary Turner             return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger();
1552c1f46dcSZachary Turner         case PyObjectType::List:
156f8b22f8fSZachary Turner             return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
1572c1f46dcSZachary Turner         case PyObjectType::String:
158f8b22f8fSZachary Turner             return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
1592c1f46dcSZachary Turner         case PyObjectType::None:
1602c1f46dcSZachary Turner             return StructuredData::ObjectSP();
1612c1f46dcSZachary Turner         default:
1622c1f46dcSZachary Turner             return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
1632c1f46dcSZachary Turner     }
1642c1f46dcSZachary Turner }
1652c1f46dcSZachary Turner 
1662c1f46dcSZachary Turner //----------------------------------------------------------------------
1672c1f46dcSZachary Turner // PythonString
1682c1f46dcSZachary Turner //----------------------------------------------------------------------
1692c1f46dcSZachary Turner 
170f8b22f8fSZachary Turner PythonString::PythonString(PyRefType type, PyObject *py_obj)
171f8b22f8fSZachary Turner     : PythonObject()
1722c1f46dcSZachary Turner {
173f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
1742c1f46dcSZachary Turner }
1752c1f46dcSZachary Turner 
176f8b22f8fSZachary Turner PythonString::PythonString(const PythonString &object)
177f8b22f8fSZachary Turner     : PythonObject(object)
1782c1f46dcSZachary Turner {
1792c1f46dcSZachary Turner }
1802c1f46dcSZachary Turner 
18122c8efcdSZachary Turner PythonString::PythonString(llvm::StringRef string)
18222c8efcdSZachary Turner     : PythonObject()
1832c1f46dcSZachary Turner {
18422c8efcdSZachary Turner     SetString(string);
1852c1f46dcSZachary Turner }
1862c1f46dcSZachary Turner 
18722c8efcdSZachary Turner PythonString::PythonString(const char *string)
18822c8efcdSZachary Turner     : PythonObject()
1892c1f46dcSZachary Turner {
19022c8efcdSZachary Turner     SetString(llvm::StringRef(string));
1912c1f46dcSZachary Turner }
1922c1f46dcSZachary Turner 
193f8b22f8fSZachary Turner PythonString::PythonString()
194f8b22f8fSZachary Turner     : PythonObject()
1952c1f46dcSZachary Turner {
1962c1f46dcSZachary Turner }
1972c1f46dcSZachary Turner 
1982c1f46dcSZachary Turner PythonString::~PythonString ()
1992c1f46dcSZachary Turner {
2002c1f46dcSZachary Turner }
2012c1f46dcSZachary Turner 
2022c1f46dcSZachary Turner bool
20322c8efcdSZachary Turner PythonString::Check(PyObject *py_obj)
20422c8efcdSZachary Turner {
20522c8efcdSZachary Turner     if (!py_obj)
20622c8efcdSZachary Turner         return false;
20718426935SZachary Turner 
2087d6d218eSZachary Turner     if (PyUnicode_Check(py_obj))
2097d6d218eSZachary Turner         return true;
2107d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
2117d6d218eSZachary Turner     if (PyString_Check(py_obj))
2127d6d218eSZachary Turner         return true;
21322c8efcdSZachary Turner #endif
2147d6d218eSZachary Turner     return false;
21522c8efcdSZachary Turner }
21622c8efcdSZachary Turner 
217f8b22f8fSZachary Turner void
218f8b22f8fSZachary Turner PythonString::Reset(PyRefType type, PyObject *py_obj)
2192c1f46dcSZachary Turner {
220f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
221f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
222f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
223f8b22f8fSZachary Turner 
22422c8efcdSZachary Turner     if (!PythonString::Check(py_obj))
22522c8efcdSZachary Turner     {
226f8b22f8fSZachary Turner         PythonObject::Reset();
227f8b22f8fSZachary Turner         return;
22822c8efcdSZachary Turner     }
2297d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
2307d6d218eSZachary Turner     // In Python 2, Don't store PyUnicode objects directly, because we need
2317d6d218eSZachary Turner     // access to their underlying character buffers which Python 2 doesn't
2327d6d218eSZachary Turner     // provide.
2337d6d218eSZachary Turner     if (PyUnicode_Check(py_obj))
2347d6d218eSZachary Turner         result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
2357d6d218eSZachary Turner #endif
236f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
237f8b22f8fSZachary Turner     // back into the virtual implementation.
238f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
2392c1f46dcSZachary Turner }
2402c1f46dcSZachary Turner 
2412c1f46dcSZachary Turner llvm::StringRef
2422c1f46dcSZachary Turner PythonString::GetString() const
2432c1f46dcSZachary Turner {
24418426935SZachary Turner     if (!IsValid())
24518426935SZachary Turner         return llvm::StringRef();
24618426935SZachary Turner 
24722c8efcdSZachary Turner     Py_ssize_t size;
24822c8efcdSZachary Turner     char *c;
24918426935SZachary Turner 
25018426935SZachary Turner #if PY_MAJOR_VERSION >= 3
25118426935SZachary Turner     c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
25218426935SZachary Turner #else
25318426935SZachary Turner     PyString_AsStringAndSize(m_py_obj, &c, &size);
25418426935SZachary Turner #endif
25522c8efcdSZachary Turner     return llvm::StringRef(c, size);
25622c8efcdSZachary Turner }
2572c1f46dcSZachary Turner 
2582c1f46dcSZachary Turner size_t
2592c1f46dcSZachary Turner PythonString::GetSize() const
2602c1f46dcSZachary Turner {
261f8b22f8fSZachary Turner     if (IsValid())
26218426935SZachary Turner     {
26318426935SZachary Turner #if PY_MAJOR_VERSION >= 3
26418426935SZachary Turner         return PyUnicode_GetSize(m_py_obj);
26518426935SZachary Turner #else
26618426935SZachary Turner         return PyString_Size(m_py_obj);
26718426935SZachary Turner #endif
26818426935SZachary Turner     }
2692c1f46dcSZachary Turner     return 0;
2702c1f46dcSZachary Turner }
2712c1f46dcSZachary Turner 
2722c1f46dcSZachary Turner void
2732c1f46dcSZachary Turner PythonString::SetString (llvm::StringRef string)
2742c1f46dcSZachary Turner {
27522c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
27622c8efcdSZachary Turner     PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
27718426935SZachary Turner     PythonObject::Reset(PyRefType::Owned, unicode);
27822c8efcdSZachary Turner #else
27918426935SZachary Turner     PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
28018426935SZachary Turner     PythonObject::Reset(PyRefType::Owned, str);
28122c8efcdSZachary Turner #endif
2822c1f46dcSZachary Turner }
2832c1f46dcSZachary Turner 
2842c1f46dcSZachary Turner StructuredData::StringSP
2852c1f46dcSZachary Turner PythonString::CreateStructuredString() const
2862c1f46dcSZachary Turner {
2872c1f46dcSZachary Turner     StructuredData::StringSP result(new StructuredData::String);
2882c1f46dcSZachary Turner     result->SetValue(GetString());
2892c1f46dcSZachary Turner     return result;
2902c1f46dcSZachary Turner }
2912c1f46dcSZachary Turner 
2922c1f46dcSZachary Turner //----------------------------------------------------------------------
2932c1f46dcSZachary Turner // PythonInteger
2942c1f46dcSZachary Turner //----------------------------------------------------------------------
2952c1f46dcSZachary Turner 
2967d6d218eSZachary Turner PythonInteger::PythonInteger()
2977d6d218eSZachary Turner     : PythonObject()
2987d6d218eSZachary Turner {
2997d6d218eSZachary Turner 
3007d6d218eSZachary Turner }
3017d6d218eSZachary Turner 
302f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
303f8b22f8fSZachary Turner     : PythonObject()
3042c1f46dcSZachary Turner {
305f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
3062c1f46dcSZachary Turner }
3072c1f46dcSZachary Turner 
308f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object)
309f8b22f8fSZachary Turner     : PythonObject(object)
3102c1f46dcSZachary Turner {
3112c1f46dcSZachary Turner }
3122c1f46dcSZachary Turner 
313f8b22f8fSZachary Turner PythonInteger::PythonInteger(int64_t value)
314f8b22f8fSZachary Turner     : PythonObject()
3152c1f46dcSZachary Turner {
3162c1f46dcSZachary Turner     SetInteger(value);
3172c1f46dcSZachary Turner }
3182c1f46dcSZachary Turner 
3192c1f46dcSZachary Turner 
3202c1f46dcSZachary Turner PythonInteger::~PythonInteger ()
3212c1f46dcSZachary Turner {
3222c1f46dcSZachary Turner }
3232c1f46dcSZachary Turner 
3242c1f46dcSZachary Turner bool
32522c8efcdSZachary Turner PythonInteger::Check(PyObject *py_obj)
3262c1f46dcSZachary Turner {
32722c8efcdSZachary Turner     if (!py_obj)
32822c8efcdSZachary Turner         return false;
32922c8efcdSZachary Turner 
33022c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
33122c8efcdSZachary Turner     // Python 3 does not have PyInt_Check.  There is only one type of
33222c8efcdSZachary Turner     // integral value, long.
33322c8efcdSZachary Turner     return PyLong_Check(py_obj);
33422c8efcdSZachary Turner #else
33522c8efcdSZachary Turner     return PyLong_Check(py_obj) || PyInt_Check(py_obj);
33622c8efcdSZachary Turner #endif
3372c1f46dcSZachary Turner }
3382c1f46dcSZachary Turner 
339f8b22f8fSZachary Turner void
340f8b22f8fSZachary Turner PythonInteger::Reset(PyRefType type, PyObject *py_obj)
34122c8efcdSZachary Turner {
342f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
343f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
344f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
345f8b22f8fSZachary Turner 
34622c8efcdSZachary Turner     if (!PythonInteger::Check(py_obj))
34722c8efcdSZachary Turner     {
348f8b22f8fSZachary Turner         PythonObject::Reset();
349f8b22f8fSZachary Turner         return;
35022c8efcdSZachary Turner     }
35122c8efcdSZachary Turner 
35222c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
35322c8efcdSZachary Turner     // Always store this as a PyLong, which makes interoperability between
35422c8efcdSZachary Turner     // Python 2.x and Python 3.x easier.  This is only necessary in 2.x,
35522c8efcdSZachary Turner     // since 3.x doesn't even have a PyInt.
35622c8efcdSZachary Turner     if (PyInt_Check(py_obj))
35722c8efcdSZachary Turner     {
358f8b22f8fSZachary Turner         // Since we converted the original object to a different type, the new
359f8b22f8fSZachary Turner         // object is an owned object regardless of the ownership semantics requested
360f8b22f8fSZachary Turner         // by the user.
361f8b22f8fSZachary Turner         result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
36222c8efcdSZachary Turner     }
36322c8efcdSZachary Turner #endif
36422c8efcdSZachary Turner 
365f8b22f8fSZachary Turner     assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject");
36622c8efcdSZachary Turner 
367f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
368f8b22f8fSZachary Turner     // back into the virtual implementation.
369f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
3702c1f46dcSZachary Turner }
3712c1f46dcSZachary Turner 
3722c1f46dcSZachary Turner int64_t
3732c1f46dcSZachary Turner PythonInteger::GetInteger() const
3742c1f46dcSZachary Turner {
3752c1f46dcSZachary Turner     if (m_py_obj)
3762c1f46dcSZachary Turner     {
37722c8efcdSZachary Turner         assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
37822c8efcdSZachary Turner 
3792c1f46dcSZachary Turner         return PyLong_AsLongLong(m_py_obj);
3802c1f46dcSZachary Turner     }
3812c1f46dcSZachary Turner     return UINT64_MAX;
3822c1f46dcSZachary Turner }
3832c1f46dcSZachary Turner 
3842c1f46dcSZachary Turner void
3852c1f46dcSZachary Turner PythonInteger::SetInteger(int64_t value)
3862c1f46dcSZachary Turner {
387f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
3882c1f46dcSZachary Turner }
3892c1f46dcSZachary Turner 
3902c1f46dcSZachary Turner StructuredData::IntegerSP
3912c1f46dcSZachary Turner PythonInteger::CreateStructuredInteger() const
3922c1f46dcSZachary Turner {
3932c1f46dcSZachary Turner     StructuredData::IntegerSP result(new StructuredData::Integer);
3942c1f46dcSZachary Turner     result->SetValue(GetInteger());
3952c1f46dcSZachary Turner     return result;
3962c1f46dcSZachary Turner }
3972c1f46dcSZachary Turner 
3982c1f46dcSZachary Turner //----------------------------------------------------------------------
3992c1f46dcSZachary Turner // PythonList
4002c1f46dcSZachary Turner //----------------------------------------------------------------------
4012c1f46dcSZachary Turner 
402f8b22f8fSZachary Turner PythonList::PythonList(PyInitialValue value)
403f8b22f8fSZachary Turner     : PythonObject()
4042c1f46dcSZachary Turner {
405f8b22f8fSZachary Turner     if (value == PyInitialValue::Empty)
406f8b22f8fSZachary Turner         Reset(PyRefType::Owned, PyList_New(0));
4072c1f46dcSZachary Turner }
4082c1f46dcSZachary Turner 
40987f47729SZachary Turner PythonList::PythonList(int list_size)
41087f47729SZachary Turner     : PythonObject()
41187f47729SZachary Turner {
41287f47729SZachary Turner     Reset(PyRefType::Owned, PyList_New(list_size));
41387f47729SZachary Turner }
41487f47729SZachary Turner 
415f8b22f8fSZachary Turner PythonList::PythonList(PyRefType type, PyObject *py_obj)
416f8b22f8fSZachary Turner     : PythonObject()
4172c1f46dcSZachary Turner {
418f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
4192c1f46dcSZachary Turner }
4202c1f46dcSZachary Turner 
421f8b22f8fSZachary Turner PythonList::PythonList(const PythonList &list)
422f8b22f8fSZachary Turner     : PythonObject(list)
4232c1f46dcSZachary Turner {
4242c1f46dcSZachary Turner }
4252c1f46dcSZachary Turner 
4262c1f46dcSZachary Turner PythonList::~PythonList ()
4272c1f46dcSZachary Turner {
4282c1f46dcSZachary Turner }
4292c1f46dcSZachary Turner 
4302c1f46dcSZachary Turner bool
43122c8efcdSZachary Turner PythonList::Check(PyObject *py_obj)
43222c8efcdSZachary Turner {
43322c8efcdSZachary Turner     if (!py_obj)
43422c8efcdSZachary Turner         return false;
43522c8efcdSZachary Turner     return PyList_Check(py_obj);
43622c8efcdSZachary Turner }
43722c8efcdSZachary Turner 
438f8b22f8fSZachary Turner void
439f8b22f8fSZachary Turner PythonList::Reset(PyRefType type, PyObject *py_obj)
4402c1f46dcSZachary Turner {
441f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
442f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
443f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
444f8b22f8fSZachary Turner 
44522c8efcdSZachary Turner     if (!PythonList::Check(py_obj))
44622c8efcdSZachary Turner     {
447f8b22f8fSZachary Turner         PythonObject::Reset();
448f8b22f8fSZachary Turner         return;
44922c8efcdSZachary Turner     }
45022c8efcdSZachary Turner 
451f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
452f8b22f8fSZachary Turner     // back into the virtual implementation.
453f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
4542c1f46dcSZachary Turner }
4552c1f46dcSZachary Turner 
4562c1f46dcSZachary Turner uint32_t
4572c1f46dcSZachary Turner PythonList::GetSize() const
4582c1f46dcSZachary Turner {
459f8b22f8fSZachary Turner     if (IsValid())
4602c1f46dcSZachary Turner         return PyList_GET_SIZE(m_py_obj);
4612c1f46dcSZachary Turner     return 0;
4622c1f46dcSZachary Turner }
4632c1f46dcSZachary Turner 
4642c1f46dcSZachary Turner PythonObject
4652c1f46dcSZachary Turner PythonList::GetItemAtIndex(uint32_t index) const
4662c1f46dcSZachary Turner {
467f8b22f8fSZachary Turner     if (IsValid())
468f8b22f8fSZachary Turner         return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
4692c1f46dcSZachary Turner     return PythonObject();
4702c1f46dcSZachary Turner }
4712c1f46dcSZachary Turner 
4722c1f46dcSZachary Turner void
4732c1f46dcSZachary Turner PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object)
4742c1f46dcSZachary Turner {
475f8b22f8fSZachary Turner     if (IsAllocated() && object.IsValid())
476f8b22f8fSZachary Turner     {
477f8b22f8fSZachary Turner         // PyList_SetItem is documented to "steal" a reference, so we need to
478f8b22f8fSZachary Turner         // convert it to an owned reference by incrementing it.
479f8b22f8fSZachary Turner         Py_INCREF(object.get());
4802c1f46dcSZachary Turner         PyList_SetItem(m_py_obj, index, object.get());
4812c1f46dcSZachary Turner     }
482f8b22f8fSZachary Turner }
4832c1f46dcSZachary Turner 
4842c1f46dcSZachary Turner void
4852c1f46dcSZachary Turner PythonList::AppendItem(const PythonObject &object)
4862c1f46dcSZachary Turner {
487f8b22f8fSZachary Turner     if (IsAllocated() && object.IsValid())
488f8b22f8fSZachary Turner     {
489f8b22f8fSZachary Turner         // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
490f8b22f8fSZachary Turner         // here like we do with `PyList_SetItem`.
4912c1f46dcSZachary Turner         PyList_Append(m_py_obj, object.get());
4922c1f46dcSZachary Turner     }
493f8b22f8fSZachary Turner }
4942c1f46dcSZachary Turner 
4952c1f46dcSZachary Turner StructuredData::ArraySP
4962c1f46dcSZachary Turner PythonList::CreateStructuredArray() const
4972c1f46dcSZachary Turner {
4982c1f46dcSZachary Turner     StructuredData::ArraySP result(new StructuredData::Array);
4992c1f46dcSZachary Turner     uint32_t count = GetSize();
5002c1f46dcSZachary Turner     for (uint32_t i = 0; i < count; ++i)
5012c1f46dcSZachary Turner     {
5022c1f46dcSZachary Turner         PythonObject obj = GetItemAtIndex(i);
5032c1f46dcSZachary Turner         result->AddItem(obj.CreateStructuredObject());
5042c1f46dcSZachary Turner     }
5052c1f46dcSZachary Turner     return result;
5062c1f46dcSZachary Turner }
5072c1f46dcSZachary Turner 
5082c1f46dcSZachary Turner //----------------------------------------------------------------------
5092c1f46dcSZachary Turner // PythonDictionary
5102c1f46dcSZachary Turner //----------------------------------------------------------------------
5112c1f46dcSZachary Turner 
512f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyInitialValue value)
513f8b22f8fSZachary Turner     : PythonObject()
5142c1f46dcSZachary Turner {
515f8b22f8fSZachary Turner     if (value == PyInitialValue::Empty)
516f8b22f8fSZachary Turner         Reset(PyRefType::Owned, PyDict_New());
5172c1f46dcSZachary Turner }
5182c1f46dcSZachary Turner 
519f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
520f8b22f8fSZachary Turner     : PythonObject()
5212c1f46dcSZachary Turner {
522f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
5232c1f46dcSZachary Turner }
5242c1f46dcSZachary Turner 
525f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object)
526f8b22f8fSZachary Turner     : PythonObject(object)
5272c1f46dcSZachary Turner {
5282c1f46dcSZachary Turner }
5292c1f46dcSZachary Turner 
5302c1f46dcSZachary Turner PythonDictionary::~PythonDictionary ()
5312c1f46dcSZachary Turner {
5322c1f46dcSZachary Turner }
5332c1f46dcSZachary Turner 
5342c1f46dcSZachary Turner bool
53522c8efcdSZachary Turner PythonDictionary::Check(PyObject *py_obj)
53622c8efcdSZachary Turner {
53722c8efcdSZachary Turner     if (!py_obj)
53822c8efcdSZachary Turner         return false;
53922c8efcdSZachary Turner 
54022c8efcdSZachary Turner     return PyDict_Check(py_obj);
54122c8efcdSZachary Turner }
54222c8efcdSZachary Turner 
543f8b22f8fSZachary Turner void
544f8b22f8fSZachary Turner PythonDictionary::Reset(PyRefType type, PyObject *py_obj)
5452c1f46dcSZachary Turner {
546f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
547f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
548f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
549f8b22f8fSZachary Turner 
55022c8efcdSZachary Turner     if (!PythonDictionary::Check(py_obj))
55122c8efcdSZachary Turner     {
552f8b22f8fSZachary Turner         PythonObject::Reset();
553f8b22f8fSZachary Turner         return;
55422c8efcdSZachary Turner     }
55522c8efcdSZachary Turner 
556f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
557f8b22f8fSZachary Turner     // back into the virtual implementation.
558f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
5592c1f46dcSZachary Turner }
5602c1f46dcSZachary Turner 
5612c1f46dcSZachary Turner uint32_t
5622c1f46dcSZachary Turner PythonDictionary::GetSize() const
5632c1f46dcSZachary Turner {
564f8b22f8fSZachary Turner     if (IsValid())
5652c1f46dcSZachary Turner         return PyDict_Size(m_py_obj);
5662c1f46dcSZachary Turner     return 0;
5672c1f46dcSZachary Turner }
5682c1f46dcSZachary Turner 
5692c1f46dcSZachary Turner PythonList
5702c1f46dcSZachary Turner PythonDictionary::GetKeys() const
5712c1f46dcSZachary Turner {
572f8b22f8fSZachary Turner     if (IsValid())
573f8b22f8fSZachary Turner         return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
574f8b22f8fSZachary Turner     return PythonList(PyInitialValue::Invalid);
5752c1f46dcSZachary Turner }
5762c1f46dcSZachary Turner 
5772c1f46dcSZachary Turner PythonObject
578f8b22f8fSZachary Turner PythonDictionary::GetItemForKey(const PythonObject &key) const
5792c1f46dcSZachary Turner {
580f8b22f8fSZachary Turner     if (IsAllocated() && key.IsValid())
581f8b22f8fSZachary Turner         return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get()));
5822c1f46dcSZachary Turner     return PythonObject();
5832c1f46dcSZachary Turner }
5842c1f46dcSZachary Turner 
5852c1f46dcSZachary Turner void
586f8b22f8fSZachary Turner PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value)
5872c1f46dcSZachary Turner {
588f8b22f8fSZachary Turner     if (IsAllocated() && key.IsValid() && value.IsValid())
5892c1f46dcSZachary Turner         PyDict_SetItem(m_py_obj, key.get(), value.get());
5902c1f46dcSZachary Turner }
5912c1f46dcSZachary Turner 
5922c1f46dcSZachary Turner StructuredData::DictionarySP
5932c1f46dcSZachary Turner PythonDictionary::CreateStructuredDictionary() const
5942c1f46dcSZachary Turner {
5952c1f46dcSZachary Turner     StructuredData::DictionarySP result(new StructuredData::Dictionary);
5962c1f46dcSZachary Turner     PythonList keys(GetKeys());
5972c1f46dcSZachary Turner     uint32_t num_keys = keys.GetSize();
5982c1f46dcSZachary Turner     for (uint32_t i = 0; i < num_keys; ++i)
5992c1f46dcSZachary Turner     {
6002c1f46dcSZachary Turner         PythonObject key = keys.GetItemAtIndex(i);
6012c1f46dcSZachary Turner         PythonObject value = GetItemForKey(key);
6022c1f46dcSZachary Turner         StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
603f8b22f8fSZachary Turner         result->AddItem(key.Str().GetString(), structured_value);
6042c1f46dcSZachary Turner     }
6052c1f46dcSZachary Turner     return result;
6062c1f46dcSZachary Turner }
6072c1f46dcSZachary Turner 
608*32064024SZachary Turner PythonFile::PythonFile()
609*32064024SZachary Turner     : PythonObject()
610*32064024SZachary Turner {
611*32064024SZachary Turner }
612*32064024SZachary Turner 
6139c40264fSZachary Turner PythonFile::PythonFile(File &file, const char *mode)
6149c40264fSZachary Turner {
6159c40264fSZachary Turner     Reset(file, mode);
6169c40264fSZachary Turner }
6179c40264fSZachary Turner 
618eda01c31SZachary Turner PythonFile::PythonFile(const char *path, const char *mode)
619eda01c31SZachary Turner {
620eda01c31SZachary Turner     FILE *fp = nullptr;
621eda01c31SZachary Turner     fp = fopen(path, mode);
622eda01c31SZachary Turner     lldb_private::File file(fp, true);
623eda01c31SZachary Turner     Reset(file, mode);
624eda01c31SZachary Turner }
625eda01c31SZachary Turner 
6269c40264fSZachary Turner PythonFile::PythonFile(PyRefType type, PyObject *o)
6279c40264fSZachary Turner {
6289c40264fSZachary Turner     Reset(type, o);
6299c40264fSZachary Turner }
6309c40264fSZachary Turner 
6319c40264fSZachary Turner PythonFile::~PythonFile()
6329c40264fSZachary Turner {
6339c40264fSZachary Turner }
6349c40264fSZachary Turner 
6359c40264fSZachary Turner bool
6369c40264fSZachary Turner PythonFile::Check(PyObject *py_obj)
6379c40264fSZachary Turner {
6389c40264fSZachary Turner #if PY_MAJOR_VERSION < 3
6399c40264fSZachary Turner     return PyFile_Check(py_obj);
6409c40264fSZachary Turner #else
6419c40264fSZachary Turner     // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
6429c40264fSZachary Turner     // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
6439c40264fSZachary Turner     // over `io.open()`, which returns some object derived from `io.IOBase`.
6449c40264fSZachary Turner     // As a result, the only way to detect a file in Python 3 is to check whether
6459c40264fSZachary Turner     // it inherits from `io.IOBase`.  Since it is possible for non-files to also
6469c40264fSZachary Turner     // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
6479c40264fSZachary Turner     // attribute, which should guarantee that it is backed by the file system.
6489c40264fSZachary Turner     PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
6499c40264fSZachary Turner     PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get()));
6509c40264fSZachary Turner     PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
6519c40264fSZachary Turner 
6529c40264fSZachary Turner     PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
6539c40264fSZachary Turner 
6549c40264fSZachary Turner     if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
6559c40264fSZachary Turner         return false;
6569c40264fSZachary Turner     if (!object_type.HasAttribute("fileno"))
6579c40264fSZachary Turner         return false;
6589c40264fSZachary Turner 
6599c40264fSZachary Turner     return true;
6609c40264fSZachary Turner #endif
6619c40264fSZachary Turner }
6629c40264fSZachary Turner 
6639c40264fSZachary Turner void
6649c40264fSZachary Turner PythonFile::Reset(PyRefType type, PyObject *py_obj)
6659c40264fSZachary Turner {
6669c40264fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
6679c40264fSZachary Turner     // `py_obj` it still gets decremented if necessary.
6689c40264fSZachary Turner     PythonObject result(type, py_obj);
6699c40264fSZachary Turner 
6709c40264fSZachary Turner     if (!PythonFile::Check(py_obj))
6719c40264fSZachary Turner     {
6729c40264fSZachary Turner         PythonObject::Reset();
6739c40264fSZachary Turner         return;
6749c40264fSZachary Turner     }
6759c40264fSZachary Turner 
6769c40264fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack
6779c40264fSZachary Turner     // overflow since it calls back into the virtual implementation.
6789c40264fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
6799c40264fSZachary Turner }
6809c40264fSZachary Turner 
6819c40264fSZachary Turner void
6829c40264fSZachary Turner PythonFile::Reset(File &file, const char *mode)
6839c40264fSZachary Turner {
6849c40264fSZachary Turner     char *cmode = const_cast<char *>(mode);
6859c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3
6869c40264fSZachary Turner     Reset(PyRefType::Owned,
6879c40264fSZachary Turner         PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0));
6889c40264fSZachary Turner #else
6899c40264fSZachary Turner     // Read through the Python source, doesn't seem to modify these strings
6909c40264fSZachary Turner     Reset(PyRefType::Owned,
6919c40264fSZachary Turner         PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr));
6929c40264fSZachary Turner #endif
6939c40264fSZachary Turner }
6949c40264fSZachary Turner 
695eda01c31SZachary Turner bool
696eda01c31SZachary Turner PythonFile::GetUnderlyingFile(File &file) const
697eda01c31SZachary Turner {
698eda01c31SZachary Turner     if (!IsValid())
699eda01c31SZachary Turner         return false;
700eda01c31SZachary Turner 
701eda01c31SZachary Turner     file.Close();
702eda01c31SZachary Turner     // We don't own the file descriptor returned by this function, make sure the
703eda01c31SZachary Turner     // File object knows about that.
704eda01c31SZachary Turner     file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
705eda01c31SZachary Turner     return file.IsValid();
706eda01c31SZachary Turner }
707eda01c31SZachary Turner 
708eda01c31SZachary Turner 
7092c1f46dcSZachary Turner #endif
710