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 114*7d6d218eSZachary Turner PythonObject 115*7d6d218eSZachary Turner PythonObject::GetAttributeValue(llvm::StringRef attr) const 116*7d6d218eSZachary Turner { 117*7d6d218eSZachary Turner if (!IsValid()) 118*7d6d218eSZachary Turner return PythonObject(); 119*7d6d218eSZachary Turner 120*7d6d218eSZachary Turner PythonString py_attr(attr); 121*7d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 122*7d6d218eSZachary Turner return PythonObject(); 123*7d6d218eSZachary Turner 124*7d6d218eSZachary Turner return PythonObject(PyRefType::Owned, 125*7d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get())); 126*7d6d218eSZachary Turner } 127*7d6d218eSZachary 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 208*7d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 209*7d6d218eSZachary Turner return true; 210*7d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 211*7d6d218eSZachary Turner if (PyString_Check(py_obj)) 212*7d6d218eSZachary Turner return true; 21322c8efcdSZachary Turner #endif 214*7d6d218eSZachary 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 } 229*7d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 230*7d6d218eSZachary Turner // In Python 2, Don't store PyUnicode objects directly, because we need 231*7d6d218eSZachary Turner // access to their underlying character buffers which Python 2 doesn't 232*7d6d218eSZachary Turner // provide. 233*7d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 234*7d6d218eSZachary Turner result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get())); 235*7d6d218eSZachary 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 296*7d6d218eSZachary Turner PythonInteger::PythonInteger() 297*7d6d218eSZachary Turner : PythonObject() 298*7d6d218eSZachary Turner { 299*7d6d218eSZachary Turner 300*7d6d218eSZachary Turner } 301*7d6d218eSZachary 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 6089c40264fSZachary Turner PythonFile::PythonFile(File &file, const char *mode) 6099c40264fSZachary Turner { 6109c40264fSZachary Turner Reset(file, mode); 6119c40264fSZachary Turner } 6129c40264fSZachary Turner 613eda01c31SZachary Turner PythonFile::PythonFile(const char *path, const char *mode) 614eda01c31SZachary Turner { 615eda01c31SZachary Turner FILE *fp = nullptr; 616eda01c31SZachary Turner fp = fopen(path, mode); 617eda01c31SZachary Turner lldb_private::File file(fp, true); 618eda01c31SZachary Turner Reset(file, mode); 619eda01c31SZachary Turner } 620eda01c31SZachary Turner 6219c40264fSZachary Turner PythonFile::PythonFile(PyRefType type, PyObject *o) 6229c40264fSZachary Turner { 6239c40264fSZachary Turner Reset(type, o); 6249c40264fSZachary Turner } 6259c40264fSZachary Turner 6269c40264fSZachary Turner PythonFile::~PythonFile() 6279c40264fSZachary Turner { 6289c40264fSZachary Turner } 6299c40264fSZachary Turner 6309c40264fSZachary Turner bool 6319c40264fSZachary Turner PythonFile::Check(PyObject *py_obj) 6329c40264fSZachary Turner { 6339c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 6349c40264fSZachary Turner return PyFile_Check(py_obj); 6359c40264fSZachary Turner #else 6369c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 6379c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 6389c40264fSZachary Turner // over `io.open()`, which returns some object derived from `io.IOBase`. 6399c40264fSZachary Turner // As a result, the only way to detect a file in Python 3 is to check whether 6409c40264fSZachary Turner // it inherits from `io.IOBase`. Since it is possible for non-files to also 6419c40264fSZachary Turner // inherit from `io.IOBase`, we additionally verify that it has the `fileno` 6429c40264fSZachary Turner // attribute, which should guarantee that it is backed by the file system. 6439c40264fSZachary Turner PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); 6449c40264fSZachary Turner PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get())); 6459c40264fSZachary Turner PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); 6469c40264fSZachary Turner 6479c40264fSZachary Turner PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); 6489c40264fSZachary Turner 6499c40264fSZachary Turner if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) 6509c40264fSZachary Turner return false; 6519c40264fSZachary Turner if (!object_type.HasAttribute("fileno")) 6529c40264fSZachary Turner return false; 6539c40264fSZachary Turner 6549c40264fSZachary Turner return true; 6559c40264fSZachary Turner #endif 6569c40264fSZachary Turner } 6579c40264fSZachary Turner 6589c40264fSZachary Turner void 6599c40264fSZachary Turner PythonFile::Reset(PyRefType type, PyObject *py_obj) 6609c40264fSZachary Turner { 6619c40264fSZachary Turner // Grab the desired reference type so that if we end up rejecting 6629c40264fSZachary Turner // `py_obj` it still gets decremented if necessary. 6639c40264fSZachary Turner PythonObject result(type, py_obj); 6649c40264fSZachary Turner 6659c40264fSZachary Turner if (!PythonFile::Check(py_obj)) 6669c40264fSZachary Turner { 6679c40264fSZachary Turner PythonObject::Reset(); 6689c40264fSZachary Turner return; 6699c40264fSZachary Turner } 6709c40264fSZachary Turner 6719c40264fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack 6729c40264fSZachary Turner // overflow since it calls back into the virtual implementation. 6739c40264fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 6749c40264fSZachary Turner } 6759c40264fSZachary Turner 6769c40264fSZachary Turner void 6779c40264fSZachary Turner PythonFile::Reset(File &file, const char *mode) 6789c40264fSZachary Turner { 6799c40264fSZachary Turner char *cmode = const_cast<char *>(mode); 6809c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3 6819c40264fSZachary Turner Reset(PyRefType::Owned, 6829c40264fSZachary Turner PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0)); 6839c40264fSZachary Turner #else 6849c40264fSZachary Turner // Read through the Python source, doesn't seem to modify these strings 6859c40264fSZachary Turner Reset(PyRefType::Owned, 6869c40264fSZachary Turner PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr)); 6879c40264fSZachary Turner #endif 6889c40264fSZachary Turner } 6899c40264fSZachary Turner 690eda01c31SZachary Turner bool 691eda01c31SZachary Turner PythonFile::GetUnderlyingFile(File &file) const 692eda01c31SZachary Turner { 693eda01c31SZachary Turner if (!IsValid()) 694eda01c31SZachary Turner return false; 695eda01c31SZachary Turner 696eda01c31SZachary Turner file.Close(); 697eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 698eda01c31SZachary Turner // File object knows about that. 699eda01c31SZachary Turner file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); 700eda01c31SZachary Turner return file.IsValid(); 701eda01c31SZachary Turner } 702eda01c31SZachary Turner 703eda01c31SZachary Turner 7042c1f46dcSZachary Turner #endif 705