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" 22*190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 232c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h" 242c1f46dcSZachary Turner 25*190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h" 26*190fadcdSZachary Turner 272c1f46dcSZachary Turner #include <stdio.h> 282c1f46dcSZachary Turner 29744959b9SEnrico Granata #include "llvm/ADT/StringSwitch.h" 30744959b9SEnrico Granata 312c1f46dcSZachary Turner using namespace lldb_private; 322c1f46dcSZachary Turner using namespace lldb; 332c1f46dcSZachary Turner 342c1f46dcSZachary Turner void 352c1f46dcSZachary Turner StructuredPythonObject::Dump(Stream &s) const 362c1f46dcSZachary Turner { 372c1f46dcSZachary Turner s << "Python Obj: 0x" << GetValue(); 382c1f46dcSZachary Turner } 392c1f46dcSZachary Turner 402c1f46dcSZachary Turner //---------------------------------------------------------------------- 412c1f46dcSZachary Turner // PythonObject 422c1f46dcSZachary Turner //---------------------------------------------------------------------- 432c1f46dcSZachary Turner 442c1f46dcSZachary Turner void 452c1f46dcSZachary Turner PythonObject::Dump(Stream &strm) const 462c1f46dcSZachary Turner { 472c1f46dcSZachary Turner if (m_py_obj) 482c1f46dcSZachary Turner { 492c1f46dcSZachary Turner FILE *file = ::tmpfile(); 502c1f46dcSZachary Turner if (file) 512c1f46dcSZachary Turner { 522c1f46dcSZachary Turner ::PyObject_Print (m_py_obj, file, 0); 532c1f46dcSZachary Turner const long length = ftell (file); 542c1f46dcSZachary Turner if (length) 552c1f46dcSZachary Turner { 562c1f46dcSZachary Turner ::rewind(file); 572c1f46dcSZachary Turner std::vector<char> file_contents (length,'\0'); 582c1f46dcSZachary Turner const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file); 592c1f46dcSZachary Turner if (length_read > 0) 602c1f46dcSZachary Turner strm.Write (file_contents.data(), length_read); 612c1f46dcSZachary Turner } 622c1f46dcSZachary Turner ::fclose (file); 632c1f46dcSZachary Turner } 642c1f46dcSZachary Turner } 652c1f46dcSZachary Turner else 662c1f46dcSZachary Turner strm.PutCString ("NULL"); 672c1f46dcSZachary Turner } 682c1f46dcSZachary Turner 692c1f46dcSZachary Turner PyObjectType 702c1f46dcSZachary Turner PythonObject::GetObjectType() const 712c1f46dcSZachary Turner { 72f8b22f8fSZachary Turner if (!IsAllocated()) 732c1f46dcSZachary Turner return PyObjectType::None; 742c1f46dcSZachary Turner 757841efbbSZachary Turner if (PythonModule::Check(m_py_obj)) 767841efbbSZachary Turner return PyObjectType::Module; 7718426935SZachary Turner if (PythonList::Check(m_py_obj)) 782c1f46dcSZachary Turner return PyObjectType::List; 79a1405147SZachary Turner if (PythonTuple::Check(m_py_obj)) 80a1405147SZachary Turner return PyObjectType::Tuple; 8118426935SZachary Turner if (PythonDictionary::Check(m_py_obj)) 822c1f46dcSZachary Turner return PyObjectType::Dictionary; 8318426935SZachary Turner if (PythonString::Check(m_py_obj)) 8422c8efcdSZachary Turner return PyObjectType::String; 855a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3 865a72c02bSZachary Turner if (PythonBytes::Check(m_py_obj)) 875a72c02bSZachary Turner return PyObjectType::Bytes; 885a72c02bSZachary Turner #endif 89f9d6d204SZachary Turner if (PythonByteArray::Check(m_py_obj)) 90f9d6d204SZachary Turner return PyObjectType::ByteArray; 9118426935SZachary Turner if (PythonInteger::Check(m_py_obj)) 9222c8efcdSZachary Turner return PyObjectType::Integer; 939c40264fSZachary Turner if (PythonFile::Check(m_py_obj)) 949c40264fSZachary Turner return PyObjectType::File; 95a1405147SZachary Turner if (PythonCallable::Check(m_py_obj)) 96a1405147SZachary Turner return PyObjectType::Callable; 972c1f46dcSZachary Turner return PyObjectType::Unknown; 982c1f46dcSZachary Turner } 992c1f46dcSZachary Turner 1002c1f46dcSZachary Turner PythonString 1017841efbbSZachary Turner PythonObject::Repr() const 1022c1f46dcSZachary Turner { 1032c1f46dcSZachary Turner if (!m_py_obj) 1042c1f46dcSZachary Turner return PythonString(); 1052c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj); 1062c1f46dcSZachary Turner if (!repr) 1072c1f46dcSZachary Turner return PythonString(); 108f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr); 1092c1f46dcSZachary Turner } 1102c1f46dcSZachary Turner 1112c1f46dcSZachary Turner PythonString 1127841efbbSZachary Turner PythonObject::Str() const 1132c1f46dcSZachary Turner { 1142c1f46dcSZachary Turner if (!m_py_obj) 1152c1f46dcSZachary Turner return PythonString(); 1162c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj); 1172c1f46dcSZachary Turner if (!str) 1182c1f46dcSZachary Turner return PythonString(); 119f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str); 1202c1f46dcSZachary Turner } 1212c1f46dcSZachary Turner 1227841efbbSZachary Turner PythonObject 12302bf92d2SZachary Turner PythonObject::ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict) 1247841efbbSZachary Turner { 125a1405147SZachary Turner size_t dot_pos = name.find_first_of('.'); 126a1405147SZachary Turner llvm::StringRef piece = name.substr(0, dot_pos); 127a1405147SZachary Turner PythonObject result = dict.GetItemForKey(PythonString(piece)); 128a1405147SZachary Turner if (dot_pos == llvm::StringRef::npos) 129a1405147SZachary Turner { 130a1405147SZachary Turner // There was no dot, we're done. 131a1405147SZachary Turner return result; 132a1405147SZachary Turner } 133a1405147SZachary Turner 134a1405147SZachary Turner // There was a dot. The remaining portion of the name should be looked up in 135a1405147SZachary Turner // the context of the object that was found in the dictionary. 136a1405147SZachary Turner return result.ResolveName(name.substr(dot_pos + 1)); 1377841efbbSZachary Turner } 1387841efbbSZachary Turner 1397841efbbSZachary Turner PythonObject 1407841efbbSZachary Turner PythonObject::ResolveName(llvm::StringRef name) const 1417841efbbSZachary Turner { 1427841efbbSZachary Turner // Resolve the name in the context of the specified object. If, 1437841efbbSZachary Turner // for example, `this` refers to a PyModule, then this will look for 1447841efbbSZachary Turner // `name` in this module. If `this` refers to a PyType, then it will 1457841efbbSZachary Turner // resolve `name` as an attribute of that type. If `this` refers to 1467841efbbSZachary Turner // an instance of an object, then it will resolve `name` as the value 1477841efbbSZachary Turner // of the specified field. 1487841efbbSZachary Turner // 1497841efbbSZachary Turner // This function handles dotted names so that, for example, if `m_py_obj` 1507841efbbSZachary Turner // refers to the `sys` module, and `name` == "path.append", then it 1517841efbbSZachary Turner // will find the function `sys.path.append`. 1527841efbbSZachary Turner 1537841efbbSZachary Turner size_t dot_pos = name.find_first_of('.'); 1547841efbbSZachary Turner if (dot_pos == llvm::StringRef::npos) 1557841efbbSZachary Turner { 1567841efbbSZachary Turner // No dots in the name, we should be able to find the value immediately 157a1405147SZachary Turner // as an attribute of `m_py_obj`. 1587841efbbSZachary Turner return GetAttributeValue(name); 1597841efbbSZachary Turner } 1607841efbbSZachary Turner 1617841efbbSZachary Turner // Look up the first piece of the name, and resolve the rest as a child of that. 1627841efbbSZachary Turner PythonObject parent = ResolveName(name.substr(0, dot_pos)); 1637841efbbSZachary Turner if (!parent.IsAllocated()) 1647841efbbSZachary Turner return PythonObject(); 1657841efbbSZachary Turner 1667841efbbSZachary Turner // Tail recursion.. should be optimized by the compiler 1677841efbbSZachary Turner return parent.ResolveName(name.substr(dot_pos + 1)); 1687841efbbSZachary Turner } 1697841efbbSZachary Turner 1702c1f46dcSZachary Turner bool 1719c40264fSZachary Turner PythonObject::HasAttribute(llvm::StringRef attr) const 1729c40264fSZachary Turner { 1739c40264fSZachary Turner if (!IsValid()) 1749c40264fSZachary Turner return false; 1759c40264fSZachary Turner PythonString py_attr(attr); 1769c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 1779c40264fSZachary Turner } 1789c40264fSZachary Turner 1797d6d218eSZachary Turner PythonObject 1807d6d218eSZachary Turner PythonObject::GetAttributeValue(llvm::StringRef attr) const 1817d6d218eSZachary Turner { 1827d6d218eSZachary Turner if (!IsValid()) 1837d6d218eSZachary Turner return PythonObject(); 1847d6d218eSZachary Turner 1857d6d218eSZachary Turner PythonString py_attr(attr); 1867d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 1877d6d218eSZachary Turner return PythonObject(); 1887d6d218eSZachary Turner 1897d6d218eSZachary Turner return PythonObject(PyRefType::Owned, 1907d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get())); 1917d6d218eSZachary Turner } 1927d6d218eSZachary Turner 1939c40264fSZachary Turner bool 194f8b22f8fSZachary Turner PythonObject::IsNone() const 1952c1f46dcSZachary Turner { 196f8b22f8fSZachary Turner return m_py_obj == Py_None; 197f8b22f8fSZachary Turner } 198f8b22f8fSZachary Turner 199f8b22f8fSZachary Turner bool 200f8b22f8fSZachary Turner PythonObject::IsValid() const 201f8b22f8fSZachary Turner { 202f8b22f8fSZachary Turner return m_py_obj != nullptr; 203f8b22f8fSZachary Turner } 204f8b22f8fSZachary Turner 205f8b22f8fSZachary Turner bool 206f8b22f8fSZachary Turner PythonObject::IsAllocated() const 207f8b22f8fSZachary Turner { 208f8b22f8fSZachary Turner return IsValid() && !IsNone(); 2092c1f46dcSZachary Turner } 2102c1f46dcSZachary Turner 2112c1f46dcSZachary Turner StructuredData::ObjectSP 2122c1f46dcSZachary Turner PythonObject::CreateStructuredObject() const 2132c1f46dcSZachary Turner { 2142c1f46dcSZachary Turner switch (GetObjectType()) 2152c1f46dcSZachary Turner { 2162c1f46dcSZachary Turner case PyObjectType::Dictionary: 217f8b22f8fSZachary Turner return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary(); 2182c1f46dcSZachary Turner case PyObjectType::Integer: 219f8b22f8fSZachary Turner return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger(); 2202c1f46dcSZachary Turner case PyObjectType::List: 221f8b22f8fSZachary Turner return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 2222c1f46dcSZachary Turner case PyObjectType::String: 223f8b22f8fSZachary Turner return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 2245a72c02bSZachary Turner case PyObjectType::Bytes: 2255a72c02bSZachary Turner return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 226f9d6d204SZachary Turner case PyObjectType::ByteArray: 227f9d6d204SZachary Turner return PythonByteArray(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 2282c1f46dcSZachary Turner case PyObjectType::None: 2292c1f46dcSZachary Turner return StructuredData::ObjectSP(); 2302c1f46dcSZachary Turner default: 2312c1f46dcSZachary Turner return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); 2322c1f46dcSZachary Turner } 2332c1f46dcSZachary Turner } 2342c1f46dcSZachary Turner 2352c1f46dcSZachary Turner //---------------------------------------------------------------------- 2362c1f46dcSZachary Turner // PythonString 2372c1f46dcSZachary Turner //---------------------------------------------------------------------- 2385a72c02bSZachary Turner PythonBytes::PythonBytes() : PythonObject() 2395a72c02bSZachary Turner { 2405a72c02bSZachary Turner } 2415a72c02bSZachary Turner 2425a72c02bSZachary Turner PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() 2435a72c02bSZachary Turner { 2445a72c02bSZachary Turner SetBytes(bytes); 2455a72c02bSZachary Turner } 2465a72c02bSZachary Turner 2475a72c02bSZachary Turner PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() 2485a72c02bSZachary Turner { 2495a72c02bSZachary Turner SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); 2505a72c02bSZachary Turner } 2515a72c02bSZachary Turner 2525a72c02bSZachary Turner PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() 2535a72c02bSZachary Turner { 2545a72c02bSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 2555a72c02bSZachary Turner } 2565a72c02bSZachary Turner 2575a72c02bSZachary Turner PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object) 2585a72c02bSZachary Turner { 2595a72c02bSZachary Turner } 2605a72c02bSZachary Turner 2615a72c02bSZachary Turner PythonBytes::~PythonBytes() 2625a72c02bSZachary Turner { 2635a72c02bSZachary Turner } 2645a72c02bSZachary Turner 2655a72c02bSZachary Turner bool 2665a72c02bSZachary Turner PythonBytes::Check(PyObject *py_obj) 2675a72c02bSZachary Turner { 2685a72c02bSZachary Turner if (!py_obj) 2695a72c02bSZachary Turner return false; 2705a72c02bSZachary Turner if (PyBytes_Check(py_obj)) 2715a72c02bSZachary Turner return true; 2725a72c02bSZachary Turner return false; 2735a72c02bSZachary Turner } 2745a72c02bSZachary Turner 2755a72c02bSZachary Turner void 2765a72c02bSZachary Turner PythonBytes::Reset(PyRefType type, PyObject *py_obj) 2775a72c02bSZachary Turner { 2785a72c02bSZachary Turner // Grab the desired reference type so that if we end up rejecting 2795a72c02bSZachary Turner // `py_obj` it still gets decremented if necessary. 2805a72c02bSZachary Turner PythonObject result(type, py_obj); 2815a72c02bSZachary Turner 2825a72c02bSZachary Turner if (!PythonBytes::Check(py_obj)) 2835a72c02bSZachary Turner { 2845a72c02bSZachary Turner PythonObject::Reset(); 2855a72c02bSZachary Turner return; 2865a72c02bSZachary Turner } 2875a72c02bSZachary Turner 2885a72c02bSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 2895a72c02bSZachary Turner // back into the virtual implementation. 2905a72c02bSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 2915a72c02bSZachary Turner } 2925a72c02bSZachary Turner 2935a72c02bSZachary Turner llvm::ArrayRef<uint8_t> 2945a72c02bSZachary Turner PythonBytes::GetBytes() const 2955a72c02bSZachary Turner { 2965a72c02bSZachary Turner if (!IsValid()) 2975a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(); 2985a72c02bSZachary Turner 2995a72c02bSZachary Turner Py_ssize_t size; 3005a72c02bSZachary Turner char *c; 3015a72c02bSZachary Turner 3025a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 3035a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 3045a72c02bSZachary Turner } 3055a72c02bSZachary Turner 3065a72c02bSZachary Turner size_t 3075a72c02bSZachary Turner PythonBytes::GetSize() const 3085a72c02bSZachary Turner { 3095a72c02bSZachary Turner if (!IsValid()) 3105a72c02bSZachary Turner return 0; 3115a72c02bSZachary Turner return PyBytes_Size(m_py_obj); 3125a72c02bSZachary Turner } 3135a72c02bSZachary Turner 3145a72c02bSZachary Turner void 3155a72c02bSZachary Turner PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) 3165a72c02bSZachary Turner { 3175a72c02bSZachary Turner const char *data = reinterpret_cast<const char *>(bytes.data()); 3185a72c02bSZachary Turner PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size()); 3195a72c02bSZachary Turner PythonObject::Reset(PyRefType::Owned, py_bytes); 3205a72c02bSZachary Turner } 3215a72c02bSZachary Turner 3225a72c02bSZachary Turner StructuredData::StringSP 3235a72c02bSZachary Turner PythonBytes::CreateStructuredString() const 3245a72c02bSZachary Turner { 3255a72c02bSZachary Turner StructuredData::StringSP result(new StructuredData::String); 3265a72c02bSZachary Turner Py_ssize_t size; 3275a72c02bSZachary Turner char *c; 3285a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 3295a72c02bSZachary Turner result->SetValue(std::string(c, size)); 3305a72c02bSZachary Turner return result; 3315a72c02bSZachary Turner } 3325a72c02bSZachary Turner 333f9d6d204SZachary Turner PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) : PythonByteArray(bytes.data(), bytes.size()) 334f9d6d204SZachary Turner { 335f9d6d204SZachary Turner } 336f9d6d204SZachary Turner 337f9d6d204SZachary Turner PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) 338f9d6d204SZachary Turner { 339f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes); 340f9d6d204SZachary Turner Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length)); 341f9d6d204SZachary Turner } 342f9d6d204SZachary Turner 343f9d6d204SZachary Turner PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) 344f9d6d204SZachary Turner { 345f9d6d204SZachary Turner Reset(type, o); 346f9d6d204SZachary Turner } 347f9d6d204SZachary Turner 348f9d6d204SZachary Turner PythonByteArray::PythonByteArray(const PythonBytes &object) : PythonObject(object) 349f9d6d204SZachary Turner { 350f9d6d204SZachary Turner } 351f9d6d204SZachary Turner 352f9d6d204SZachary Turner PythonByteArray::~PythonByteArray() 353f9d6d204SZachary Turner { 354f9d6d204SZachary Turner } 355f9d6d204SZachary Turner 356f9d6d204SZachary Turner bool 357f9d6d204SZachary Turner PythonByteArray::Check(PyObject *py_obj) 358f9d6d204SZachary Turner { 359f9d6d204SZachary Turner if (!py_obj) 360f9d6d204SZachary Turner return false; 361f9d6d204SZachary Turner if (PyByteArray_Check(py_obj)) 362f9d6d204SZachary Turner return true; 363f9d6d204SZachary Turner return false; 364f9d6d204SZachary Turner } 365f9d6d204SZachary Turner 366f9d6d204SZachary Turner void 367f9d6d204SZachary Turner PythonByteArray::Reset(PyRefType type, PyObject *py_obj) 368f9d6d204SZachary Turner { 369f9d6d204SZachary Turner // Grab the desired reference type so that if we end up rejecting 370f9d6d204SZachary Turner // `py_obj` it still gets decremented if necessary. 371f9d6d204SZachary Turner PythonObject result(type, py_obj); 372f9d6d204SZachary Turner 373f9d6d204SZachary Turner if (!PythonByteArray::Check(py_obj)) 374f9d6d204SZachary Turner { 375f9d6d204SZachary Turner PythonObject::Reset(); 376f9d6d204SZachary Turner return; 377f9d6d204SZachary Turner } 378f9d6d204SZachary Turner 379f9d6d204SZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 380f9d6d204SZachary Turner // back into the virtual implementation. 381f9d6d204SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 382f9d6d204SZachary Turner } 383f9d6d204SZachary Turner 384f9d6d204SZachary Turner llvm::ArrayRef<uint8_t> 385f9d6d204SZachary Turner PythonByteArray::GetBytes() const 386f9d6d204SZachary Turner { 387f9d6d204SZachary Turner if (!IsValid()) 388f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(); 389f9d6d204SZachary Turner 390f9d6d204SZachary Turner char *c = PyByteArray_AsString(m_py_obj); 391f9d6d204SZachary Turner size_t size = GetSize(); 392f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 393f9d6d204SZachary Turner } 394f9d6d204SZachary Turner 395f9d6d204SZachary Turner size_t 396f9d6d204SZachary Turner PythonByteArray::GetSize() const 397f9d6d204SZachary Turner { 398f9d6d204SZachary Turner if (!IsValid()) 399f9d6d204SZachary Turner return 0; 400f9d6d204SZachary Turner 401f9d6d204SZachary Turner return PyByteArray_Size(m_py_obj); 402f9d6d204SZachary Turner } 403f9d6d204SZachary Turner 404f9d6d204SZachary Turner StructuredData::StringSP 405f9d6d204SZachary Turner PythonByteArray::CreateStructuredString() const 406f9d6d204SZachary Turner { 407f9d6d204SZachary Turner StructuredData::StringSP result(new StructuredData::String); 408f9d6d204SZachary Turner llvm::ArrayRef<uint8_t> bytes = GetBytes(); 409f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes.data()); 410f9d6d204SZachary Turner result->SetValue(std::string(str, bytes.size())); 411f9d6d204SZachary Turner return result; 412f9d6d204SZachary Turner } 413f9d6d204SZachary Turner 4145a72c02bSZachary Turner //---------------------------------------------------------------------- 4155a72c02bSZachary Turner // PythonString 4165a72c02bSZachary Turner //---------------------------------------------------------------------- 4172c1f46dcSZachary Turner 418f8b22f8fSZachary Turner PythonString::PythonString(PyRefType type, PyObject *py_obj) 419f8b22f8fSZachary Turner : PythonObject() 4202c1f46dcSZachary Turner { 421f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 4222c1f46dcSZachary Turner } 4232c1f46dcSZachary Turner 424f8b22f8fSZachary Turner PythonString::PythonString(const PythonString &object) 425f8b22f8fSZachary Turner : PythonObject(object) 4262c1f46dcSZachary Turner { 4272c1f46dcSZachary Turner } 4282c1f46dcSZachary Turner 42922c8efcdSZachary Turner PythonString::PythonString(llvm::StringRef string) 43022c8efcdSZachary Turner : PythonObject() 4312c1f46dcSZachary Turner { 43222c8efcdSZachary Turner SetString(string); 4332c1f46dcSZachary Turner } 4342c1f46dcSZachary Turner 43522c8efcdSZachary Turner PythonString::PythonString(const char *string) 43622c8efcdSZachary Turner : PythonObject() 4372c1f46dcSZachary Turner { 43822c8efcdSZachary Turner SetString(llvm::StringRef(string)); 4392c1f46dcSZachary Turner } 4402c1f46dcSZachary Turner 441f8b22f8fSZachary Turner PythonString::PythonString() 442f8b22f8fSZachary Turner : PythonObject() 4432c1f46dcSZachary Turner { 4442c1f46dcSZachary Turner } 4452c1f46dcSZachary Turner 4462c1f46dcSZachary Turner PythonString::~PythonString () 4472c1f46dcSZachary Turner { 4482c1f46dcSZachary Turner } 4492c1f46dcSZachary Turner 4502c1f46dcSZachary Turner bool 45122c8efcdSZachary Turner PythonString::Check(PyObject *py_obj) 45222c8efcdSZachary Turner { 45322c8efcdSZachary Turner if (!py_obj) 45422c8efcdSZachary Turner return false; 45518426935SZachary Turner 4567d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 4577d6d218eSZachary Turner return true; 4587d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 4597d6d218eSZachary Turner if (PyString_Check(py_obj)) 4607d6d218eSZachary Turner return true; 46122c8efcdSZachary Turner #endif 4627d6d218eSZachary Turner return false; 46322c8efcdSZachary Turner } 46422c8efcdSZachary Turner 465f8b22f8fSZachary Turner void 466f8b22f8fSZachary Turner PythonString::Reset(PyRefType type, PyObject *py_obj) 4672c1f46dcSZachary Turner { 468f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 469f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 470f8b22f8fSZachary Turner PythonObject result(type, py_obj); 471f8b22f8fSZachary Turner 47222c8efcdSZachary Turner if (!PythonString::Check(py_obj)) 47322c8efcdSZachary Turner { 474f8b22f8fSZachary Turner PythonObject::Reset(); 475f8b22f8fSZachary Turner return; 47622c8efcdSZachary Turner } 4777d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 4787d6d218eSZachary Turner // In Python 2, Don't store PyUnicode objects directly, because we need 4797d6d218eSZachary Turner // access to their underlying character buffers which Python 2 doesn't 4807d6d218eSZachary Turner // provide. 4817d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 4827d6d218eSZachary Turner result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get())); 4837d6d218eSZachary Turner #endif 484f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 485f8b22f8fSZachary Turner // back into the virtual implementation. 486f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 4872c1f46dcSZachary Turner } 4882c1f46dcSZachary Turner 4892c1f46dcSZachary Turner llvm::StringRef 4902c1f46dcSZachary Turner PythonString::GetString() const 4912c1f46dcSZachary Turner { 49218426935SZachary Turner if (!IsValid()) 49318426935SZachary Turner return llvm::StringRef(); 49418426935SZachary Turner 49522c8efcdSZachary Turner Py_ssize_t size; 49622c8efcdSZachary Turner char *c; 49718426935SZachary Turner 49818426935SZachary Turner #if PY_MAJOR_VERSION >= 3 49918426935SZachary Turner c = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 50018426935SZachary Turner #else 50118426935SZachary Turner PyString_AsStringAndSize(m_py_obj, &c, &size); 50218426935SZachary Turner #endif 50322c8efcdSZachary Turner return llvm::StringRef(c, size); 50422c8efcdSZachary Turner } 5052c1f46dcSZachary Turner 5062c1f46dcSZachary Turner size_t 5072c1f46dcSZachary Turner PythonString::GetSize() const 5082c1f46dcSZachary Turner { 509f8b22f8fSZachary Turner if (IsValid()) 51018426935SZachary Turner { 51118426935SZachary Turner #if PY_MAJOR_VERSION >= 3 51218426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 51318426935SZachary Turner #else 51418426935SZachary Turner return PyString_Size(m_py_obj); 51518426935SZachary Turner #endif 51618426935SZachary Turner } 5172c1f46dcSZachary Turner return 0; 5182c1f46dcSZachary Turner } 5192c1f46dcSZachary Turner 5202c1f46dcSZachary Turner void 5212c1f46dcSZachary Turner PythonString::SetString (llvm::StringRef string) 5222c1f46dcSZachary Turner { 52322c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 52422c8efcdSZachary Turner PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size()); 52518426935SZachary Turner PythonObject::Reset(PyRefType::Owned, unicode); 52622c8efcdSZachary Turner #else 52718426935SZachary Turner PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 52818426935SZachary Turner PythonObject::Reset(PyRefType::Owned, str); 52922c8efcdSZachary Turner #endif 5302c1f46dcSZachary Turner } 5312c1f46dcSZachary Turner 5322c1f46dcSZachary Turner StructuredData::StringSP 5332c1f46dcSZachary Turner PythonString::CreateStructuredString() const 5342c1f46dcSZachary Turner { 5352c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 5362c1f46dcSZachary Turner result->SetValue(GetString()); 5372c1f46dcSZachary Turner return result; 5382c1f46dcSZachary Turner } 5392c1f46dcSZachary Turner 5402c1f46dcSZachary Turner //---------------------------------------------------------------------- 5412c1f46dcSZachary Turner // PythonInteger 5422c1f46dcSZachary Turner //---------------------------------------------------------------------- 5432c1f46dcSZachary Turner 5447d6d218eSZachary Turner PythonInteger::PythonInteger() 5457d6d218eSZachary Turner : PythonObject() 5467d6d218eSZachary Turner { 5477d6d218eSZachary Turner 5487d6d218eSZachary Turner } 5497d6d218eSZachary Turner 550f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) 551f8b22f8fSZachary Turner : PythonObject() 5522c1f46dcSZachary Turner { 553f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type 5542c1f46dcSZachary Turner } 5552c1f46dcSZachary Turner 556f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object) 557f8b22f8fSZachary Turner : PythonObject(object) 5582c1f46dcSZachary Turner { 5592c1f46dcSZachary Turner } 5602c1f46dcSZachary Turner 561f8b22f8fSZachary Turner PythonInteger::PythonInteger(int64_t value) 562f8b22f8fSZachary Turner : PythonObject() 5632c1f46dcSZachary Turner { 5642c1f46dcSZachary Turner SetInteger(value); 5652c1f46dcSZachary Turner } 5662c1f46dcSZachary Turner 5672c1f46dcSZachary Turner 5682c1f46dcSZachary Turner PythonInteger::~PythonInteger () 5692c1f46dcSZachary Turner { 5702c1f46dcSZachary Turner } 5712c1f46dcSZachary Turner 5722c1f46dcSZachary Turner bool 57322c8efcdSZachary Turner PythonInteger::Check(PyObject *py_obj) 5742c1f46dcSZachary Turner { 57522c8efcdSZachary Turner if (!py_obj) 57622c8efcdSZachary Turner return false; 57722c8efcdSZachary Turner 57822c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 57922c8efcdSZachary Turner // Python 3 does not have PyInt_Check. There is only one type of 58022c8efcdSZachary Turner // integral value, long. 58122c8efcdSZachary Turner return PyLong_Check(py_obj); 58222c8efcdSZachary Turner #else 58322c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 58422c8efcdSZachary Turner #endif 5852c1f46dcSZachary Turner } 5862c1f46dcSZachary Turner 587f8b22f8fSZachary Turner void 588f8b22f8fSZachary Turner PythonInteger::Reset(PyRefType type, PyObject *py_obj) 58922c8efcdSZachary Turner { 590f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 591f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 592f8b22f8fSZachary Turner PythonObject result(type, py_obj); 593f8b22f8fSZachary Turner 59422c8efcdSZachary Turner if (!PythonInteger::Check(py_obj)) 59522c8efcdSZachary Turner { 596f8b22f8fSZachary Turner PythonObject::Reset(); 597f8b22f8fSZachary Turner return; 59822c8efcdSZachary Turner } 59922c8efcdSZachary Turner 60022c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 60122c8efcdSZachary Turner // Always store this as a PyLong, which makes interoperability between 60222c8efcdSZachary Turner // Python 2.x and Python 3.x easier. This is only necessary in 2.x, 60322c8efcdSZachary Turner // since 3.x doesn't even have a PyInt. 60422c8efcdSZachary Turner if (PyInt_Check(py_obj)) 60522c8efcdSZachary Turner { 606f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 607f8b22f8fSZachary Turner // object is an owned object regardless of the ownership semantics requested 608f8b22f8fSZachary Turner // by the user. 609f8b22f8fSZachary Turner result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); 61022c8efcdSZachary Turner } 61122c8efcdSZachary Turner #endif 61222c8efcdSZachary Turner 613f8b22f8fSZachary Turner assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject"); 61422c8efcdSZachary Turner 615f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 616f8b22f8fSZachary Turner // back into the virtual implementation. 617f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 6182c1f46dcSZachary Turner } 6192c1f46dcSZachary Turner 6202c1f46dcSZachary Turner int64_t 6212c1f46dcSZachary Turner PythonInteger::GetInteger() const 6222c1f46dcSZachary Turner { 6232c1f46dcSZachary Turner if (m_py_obj) 6242c1f46dcSZachary Turner { 62522c8efcdSZachary Turner assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 62622c8efcdSZachary Turner 6272c1f46dcSZachary Turner return PyLong_AsLongLong(m_py_obj); 6282c1f46dcSZachary Turner } 6292c1f46dcSZachary Turner return UINT64_MAX; 6302c1f46dcSZachary Turner } 6312c1f46dcSZachary Turner 6322c1f46dcSZachary Turner void 6332c1f46dcSZachary Turner PythonInteger::SetInteger(int64_t value) 6342c1f46dcSZachary Turner { 635f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); 6362c1f46dcSZachary Turner } 6372c1f46dcSZachary Turner 6382c1f46dcSZachary Turner StructuredData::IntegerSP 6392c1f46dcSZachary Turner PythonInteger::CreateStructuredInteger() const 6402c1f46dcSZachary Turner { 6412c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 6422c1f46dcSZachary Turner result->SetValue(GetInteger()); 6432c1f46dcSZachary Turner return result; 6442c1f46dcSZachary Turner } 6452c1f46dcSZachary Turner 6462c1f46dcSZachary Turner //---------------------------------------------------------------------- 6472c1f46dcSZachary Turner // PythonList 6482c1f46dcSZachary Turner //---------------------------------------------------------------------- 6492c1f46dcSZachary Turner 650f8b22f8fSZachary Turner PythonList::PythonList(PyInitialValue value) 651f8b22f8fSZachary Turner : PythonObject() 6522c1f46dcSZachary Turner { 653f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 654f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyList_New(0)); 6552c1f46dcSZachary Turner } 6562c1f46dcSZachary Turner 65787f47729SZachary Turner PythonList::PythonList(int list_size) 65887f47729SZachary Turner : PythonObject() 65987f47729SZachary Turner { 66087f47729SZachary Turner Reset(PyRefType::Owned, PyList_New(list_size)); 66187f47729SZachary Turner } 66287f47729SZachary Turner 663f8b22f8fSZachary Turner PythonList::PythonList(PyRefType type, PyObject *py_obj) 664f8b22f8fSZachary Turner : PythonObject() 6652c1f46dcSZachary Turner { 666f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list 6672c1f46dcSZachary Turner } 6682c1f46dcSZachary Turner 669f8b22f8fSZachary Turner PythonList::PythonList(const PythonList &list) 670f8b22f8fSZachary Turner : PythonObject(list) 6712c1f46dcSZachary Turner { 6722c1f46dcSZachary Turner } 6732c1f46dcSZachary Turner 6742c1f46dcSZachary Turner PythonList::~PythonList () 6752c1f46dcSZachary Turner { 6762c1f46dcSZachary Turner } 6772c1f46dcSZachary Turner 6782c1f46dcSZachary Turner bool 67922c8efcdSZachary Turner PythonList::Check(PyObject *py_obj) 68022c8efcdSZachary Turner { 68122c8efcdSZachary Turner if (!py_obj) 68222c8efcdSZachary Turner return false; 68322c8efcdSZachary Turner return PyList_Check(py_obj); 68422c8efcdSZachary Turner } 68522c8efcdSZachary Turner 686f8b22f8fSZachary Turner void 687f8b22f8fSZachary Turner PythonList::Reset(PyRefType type, PyObject *py_obj) 6882c1f46dcSZachary Turner { 689f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 690f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 691f8b22f8fSZachary Turner PythonObject result(type, py_obj); 692f8b22f8fSZachary Turner 69322c8efcdSZachary Turner if (!PythonList::Check(py_obj)) 69422c8efcdSZachary Turner { 695f8b22f8fSZachary Turner PythonObject::Reset(); 696f8b22f8fSZachary Turner return; 69722c8efcdSZachary Turner } 69822c8efcdSZachary Turner 699f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 700f8b22f8fSZachary Turner // back into the virtual implementation. 701f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 7022c1f46dcSZachary Turner } 7032c1f46dcSZachary Turner 7042c1f46dcSZachary Turner uint32_t 7052c1f46dcSZachary Turner PythonList::GetSize() const 7062c1f46dcSZachary Turner { 707f8b22f8fSZachary Turner if (IsValid()) 7082c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 7092c1f46dcSZachary Turner return 0; 7102c1f46dcSZachary Turner } 7112c1f46dcSZachary Turner 7122c1f46dcSZachary Turner PythonObject 7132c1f46dcSZachary Turner PythonList::GetItemAtIndex(uint32_t index) const 7142c1f46dcSZachary Turner { 715f8b22f8fSZachary Turner if (IsValid()) 716f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 7172c1f46dcSZachary Turner return PythonObject(); 7182c1f46dcSZachary Turner } 7192c1f46dcSZachary Turner 7202c1f46dcSZachary Turner void 7212c1f46dcSZachary Turner PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) 7222c1f46dcSZachary Turner { 723f8b22f8fSZachary Turner if (IsAllocated() && object.IsValid()) 724f8b22f8fSZachary Turner { 725f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 726f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 727f8b22f8fSZachary Turner Py_INCREF(object.get()); 7282c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 7292c1f46dcSZachary Turner } 730f8b22f8fSZachary Turner } 7312c1f46dcSZachary Turner 7322c1f46dcSZachary Turner void 7332c1f46dcSZachary Turner PythonList::AppendItem(const PythonObject &object) 7342c1f46dcSZachary Turner { 735f8b22f8fSZachary Turner if (IsAllocated() && object.IsValid()) 736f8b22f8fSZachary Turner { 737f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 738f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 7392c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 7402c1f46dcSZachary Turner } 741f8b22f8fSZachary Turner } 7422c1f46dcSZachary Turner 7432c1f46dcSZachary Turner StructuredData::ArraySP 7442c1f46dcSZachary Turner PythonList::CreateStructuredArray() const 7452c1f46dcSZachary Turner { 7462c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 7472c1f46dcSZachary Turner uint32_t count = GetSize(); 7482c1f46dcSZachary Turner for (uint32_t i = 0; i < count; ++i) 7492c1f46dcSZachary Turner { 7502c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 7512c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 7522c1f46dcSZachary Turner } 7532c1f46dcSZachary Turner return result; 7542c1f46dcSZachary Turner } 7552c1f46dcSZachary Turner 7562c1f46dcSZachary Turner //---------------------------------------------------------------------- 757a1405147SZachary Turner // PythonTuple 758a1405147SZachary Turner //---------------------------------------------------------------------- 759a1405147SZachary Turner 760a1405147SZachary Turner PythonTuple::PythonTuple(PyInitialValue value) 761a1405147SZachary Turner : PythonObject() 762a1405147SZachary Turner { 763a1405147SZachary Turner if (value == PyInitialValue::Empty) 764a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(0)); 765a1405147SZachary Turner } 766a1405147SZachary Turner 767a1405147SZachary Turner PythonTuple::PythonTuple(int tuple_size) 768a1405147SZachary Turner : PythonObject() 769a1405147SZachary Turner { 770a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(tuple_size)); 771a1405147SZachary Turner } 772a1405147SZachary Turner 773a1405147SZachary Turner PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) 774a1405147SZachary Turner : PythonObject() 775a1405147SZachary Turner { 776a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple 777a1405147SZachary Turner } 778a1405147SZachary Turner 779a1405147SZachary Turner PythonTuple::PythonTuple(const PythonTuple &tuple) 780a1405147SZachary Turner : PythonObject(tuple) 781a1405147SZachary Turner { 782a1405147SZachary Turner } 783a1405147SZachary Turner 784a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) 785a1405147SZachary Turner { 786a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 787a1405147SZachary Turner 788a1405147SZachary Turner uint32_t idx = 0; 789a1405147SZachary Turner for (auto object : objects) 790a1405147SZachary Turner { 791a1405147SZachary Turner if (object.IsValid()) 792a1405147SZachary Turner SetItemAtIndex(idx, object); 793a1405147SZachary Turner idx++; 794a1405147SZachary Turner } 795a1405147SZachary Turner } 796a1405147SZachary Turner 797a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PyObject*> objects) 798a1405147SZachary Turner { 799a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 800a1405147SZachary Turner 801a1405147SZachary Turner uint32_t idx = 0; 802a1405147SZachary Turner for (auto py_object : objects) 803a1405147SZachary Turner { 804a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object); 805a1405147SZachary Turner if (object.IsValid()) 806a1405147SZachary Turner SetItemAtIndex(idx, object); 807a1405147SZachary Turner idx++; 808a1405147SZachary Turner } 809a1405147SZachary Turner } 810a1405147SZachary Turner 811a1405147SZachary Turner PythonTuple::~PythonTuple() 812a1405147SZachary Turner { 813a1405147SZachary Turner } 814a1405147SZachary Turner 815a1405147SZachary Turner bool 816a1405147SZachary Turner PythonTuple::Check(PyObject *py_obj) 817a1405147SZachary Turner { 818a1405147SZachary Turner if (!py_obj) 819a1405147SZachary Turner return false; 820a1405147SZachary Turner return PyTuple_Check(py_obj); 821a1405147SZachary Turner } 822a1405147SZachary Turner 823a1405147SZachary Turner void 824a1405147SZachary Turner PythonTuple::Reset(PyRefType type, PyObject *py_obj) 825a1405147SZachary Turner { 826a1405147SZachary Turner // Grab the desired reference type so that if we end up rejecting 827a1405147SZachary Turner // `py_obj` it still gets decremented if necessary. 828a1405147SZachary Turner PythonObject result(type, py_obj); 829a1405147SZachary Turner 830a1405147SZachary Turner if (!PythonTuple::Check(py_obj)) 831a1405147SZachary Turner { 832a1405147SZachary Turner PythonObject::Reset(); 833a1405147SZachary Turner return; 834a1405147SZachary Turner } 835a1405147SZachary Turner 836a1405147SZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 837a1405147SZachary Turner // back into the virtual implementation. 838a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 839a1405147SZachary Turner } 840a1405147SZachary Turner 841a1405147SZachary Turner uint32_t 842a1405147SZachary Turner PythonTuple::GetSize() const 843a1405147SZachary Turner { 844a1405147SZachary Turner if (IsValid()) 845a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj); 846a1405147SZachary Turner return 0; 847a1405147SZachary Turner } 848a1405147SZachary Turner 849a1405147SZachary Turner PythonObject 850a1405147SZachary Turner PythonTuple::GetItemAtIndex(uint32_t index) const 851a1405147SZachary Turner { 852a1405147SZachary Turner if (IsValid()) 853a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 854a1405147SZachary Turner return PythonObject(); 855a1405147SZachary Turner } 856a1405147SZachary Turner 857a1405147SZachary Turner void 858a1405147SZachary Turner PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) 859a1405147SZachary Turner { 860a1405147SZachary Turner if (IsAllocated() && object.IsValid()) 861a1405147SZachary Turner { 862a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to 863a1405147SZachary Turner // convert it to an owned reference by incrementing it. 864a1405147SZachary Turner Py_INCREF(object.get()); 865a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get()); 866a1405147SZachary Turner } 867a1405147SZachary Turner } 868a1405147SZachary Turner 869a1405147SZachary Turner StructuredData::ArraySP 870a1405147SZachary Turner PythonTuple::CreateStructuredArray() const 871a1405147SZachary Turner { 872a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 873a1405147SZachary Turner uint32_t count = GetSize(); 874a1405147SZachary Turner for (uint32_t i = 0; i < count; ++i) 875a1405147SZachary Turner { 876a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i); 877a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject()); 878a1405147SZachary Turner } 879a1405147SZachary Turner return result; 880a1405147SZachary Turner } 881a1405147SZachary Turner 882a1405147SZachary Turner //---------------------------------------------------------------------- 8832c1f46dcSZachary Turner // PythonDictionary 8842c1f46dcSZachary Turner //---------------------------------------------------------------------- 8852c1f46dcSZachary Turner 886f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyInitialValue value) 887f8b22f8fSZachary Turner : PythonObject() 8882c1f46dcSZachary Turner { 889f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 890f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyDict_New()); 8912c1f46dcSZachary Turner } 8922c1f46dcSZachary Turner 893f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) 894f8b22f8fSZachary Turner : PythonObject() 8952c1f46dcSZachary Turner { 896f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary 8972c1f46dcSZachary Turner } 8982c1f46dcSZachary Turner 899f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object) 900f8b22f8fSZachary Turner : PythonObject(object) 9012c1f46dcSZachary Turner { 9022c1f46dcSZachary Turner } 9032c1f46dcSZachary Turner 9042c1f46dcSZachary Turner PythonDictionary::~PythonDictionary () 9052c1f46dcSZachary Turner { 9062c1f46dcSZachary Turner } 9072c1f46dcSZachary Turner 9082c1f46dcSZachary Turner bool 90922c8efcdSZachary Turner PythonDictionary::Check(PyObject *py_obj) 91022c8efcdSZachary Turner { 91122c8efcdSZachary Turner if (!py_obj) 91222c8efcdSZachary Turner return false; 91322c8efcdSZachary Turner 91422c8efcdSZachary Turner return PyDict_Check(py_obj); 91522c8efcdSZachary Turner } 91622c8efcdSZachary Turner 917f8b22f8fSZachary Turner void 918f8b22f8fSZachary Turner PythonDictionary::Reset(PyRefType type, PyObject *py_obj) 9192c1f46dcSZachary Turner { 920f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 921f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 922f8b22f8fSZachary Turner PythonObject result(type, py_obj); 923f8b22f8fSZachary Turner 92422c8efcdSZachary Turner if (!PythonDictionary::Check(py_obj)) 92522c8efcdSZachary Turner { 926f8b22f8fSZachary Turner PythonObject::Reset(); 927f8b22f8fSZachary Turner return; 92822c8efcdSZachary Turner } 92922c8efcdSZachary Turner 930f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 931f8b22f8fSZachary Turner // back into the virtual implementation. 932f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 9332c1f46dcSZachary Turner } 9342c1f46dcSZachary Turner 9352c1f46dcSZachary Turner uint32_t 9362c1f46dcSZachary Turner PythonDictionary::GetSize() const 9372c1f46dcSZachary Turner { 938f8b22f8fSZachary Turner if (IsValid()) 9392c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 9402c1f46dcSZachary Turner return 0; 9412c1f46dcSZachary Turner } 9422c1f46dcSZachary Turner 9432c1f46dcSZachary Turner PythonList 9442c1f46dcSZachary Turner PythonDictionary::GetKeys() const 9452c1f46dcSZachary Turner { 946f8b22f8fSZachary Turner if (IsValid()) 947f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 948f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 9492c1f46dcSZachary Turner } 9502c1f46dcSZachary Turner 9512c1f46dcSZachary Turner PythonObject 952f8b22f8fSZachary Turner PythonDictionary::GetItemForKey(const PythonObject &key) const 9532c1f46dcSZachary Turner { 954f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid()) 955f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get())); 9562c1f46dcSZachary Turner return PythonObject(); 9572c1f46dcSZachary Turner } 9582c1f46dcSZachary Turner 9592c1f46dcSZachary Turner void 960f8b22f8fSZachary Turner PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value) 9612c1f46dcSZachary Turner { 962f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid() && value.IsValid()) 9632c1f46dcSZachary Turner PyDict_SetItem(m_py_obj, key.get(), value.get()); 9642c1f46dcSZachary Turner } 9652c1f46dcSZachary Turner 9662c1f46dcSZachary Turner StructuredData::DictionarySP 9672c1f46dcSZachary Turner PythonDictionary::CreateStructuredDictionary() const 9682c1f46dcSZachary Turner { 9692c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 9702c1f46dcSZachary Turner PythonList keys(GetKeys()); 9712c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 9722c1f46dcSZachary Turner for (uint32_t i = 0; i < num_keys; ++i) 9732c1f46dcSZachary Turner { 9742c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 9752c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 9762c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 977f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 9782c1f46dcSZachary Turner } 9792c1f46dcSZachary Turner return result; 9802c1f46dcSZachary Turner } 9812c1f46dcSZachary Turner 9827841efbbSZachary Turner PythonModule::PythonModule() : PythonObject() 9837841efbbSZachary Turner { 9847841efbbSZachary Turner } 9857841efbbSZachary Turner 9867841efbbSZachary Turner PythonModule::PythonModule(PyRefType type, PyObject *py_obj) 9877841efbbSZachary Turner { 9887841efbbSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module 9897841efbbSZachary Turner } 9907841efbbSZachary Turner 9917841efbbSZachary Turner PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict) 9927841efbbSZachary Turner { 9937841efbbSZachary Turner } 9947841efbbSZachary Turner 9957841efbbSZachary Turner PythonModule::~PythonModule() 9967841efbbSZachary Turner { 9977841efbbSZachary Turner } 9987841efbbSZachary Turner 9997841efbbSZachary Turner PythonModule 1000a1405147SZachary Turner PythonModule::BuiltinsModule() 1001a1405147SZachary Turner { 1002a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3 1003a1405147SZachary Turner return AddModule("builtins"); 1004a1405147SZachary Turner #else 1005a1405147SZachary Turner return AddModule("__builtin__"); 1006a1405147SZachary Turner #endif 1007a1405147SZachary Turner } 1008a1405147SZachary Turner 1009a1405147SZachary Turner PythonModule 10107841efbbSZachary Turner PythonModule::MainModule() 10117841efbbSZachary Turner { 1012a1405147SZachary Turner return AddModule("__main__"); 1013a1405147SZachary Turner } 1014a1405147SZachary Turner 1015a1405147SZachary Turner PythonModule 1016a1405147SZachary Turner PythonModule::AddModule(llvm::StringRef module) 1017a1405147SZachary Turner { 1018a1405147SZachary Turner std::string str = module.str(); 1019a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 10207841efbbSZachary Turner } 10217841efbbSZachary Turner 10222419f1d5SZachary Turner 10232419f1d5SZachary Turner PythonModule 10242419f1d5SZachary Turner PythonModule::ImportModule(llvm::StringRef module) 10252419f1d5SZachary Turner { 10262419f1d5SZachary Turner std::string str = module.str(); 10272419f1d5SZachary Turner return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str())); 10282419f1d5SZachary Turner } 10292419f1d5SZachary Turner 10307841efbbSZachary Turner bool 10317841efbbSZachary Turner PythonModule::Check(PyObject *py_obj) 10327841efbbSZachary Turner { 10337841efbbSZachary Turner if (!py_obj) 10347841efbbSZachary Turner return false; 10357841efbbSZachary Turner 10367841efbbSZachary Turner return PyModule_Check(py_obj); 10377841efbbSZachary Turner } 10387841efbbSZachary Turner 10397841efbbSZachary Turner void 10407841efbbSZachary Turner PythonModule::Reset(PyRefType type, PyObject *py_obj) 10417841efbbSZachary Turner { 10427841efbbSZachary Turner // Grab the desired reference type so that if we end up rejecting 10437841efbbSZachary Turner // `py_obj` it still gets decremented if necessary. 10447841efbbSZachary Turner PythonObject result(type, py_obj); 10457841efbbSZachary Turner 10467841efbbSZachary Turner if (!PythonModule::Check(py_obj)) 10477841efbbSZachary Turner { 10487841efbbSZachary Turner PythonObject::Reset(); 10497841efbbSZachary Turner return; 10507841efbbSZachary Turner } 10517841efbbSZachary Turner 10527841efbbSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 10537841efbbSZachary Turner // back into the virtual implementation. 10547841efbbSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 10557841efbbSZachary Turner } 10567841efbbSZachary Turner 10577841efbbSZachary Turner PythonDictionary 10587841efbbSZachary Turner PythonModule::GetDictionary() const 10597841efbbSZachary Turner { 10607841efbbSZachary Turner return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); 10617841efbbSZachary Turner } 10627841efbbSZachary Turner 1063a1405147SZachary Turner PythonCallable::PythonCallable() : PythonObject() 1064a1405147SZachary Turner { 1065a1405147SZachary Turner } 1066a1405147SZachary Turner 1067a1405147SZachary Turner PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) 1068a1405147SZachary Turner { 1069a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable 1070a1405147SZachary Turner } 1071a1405147SZachary Turner 1072a1405147SZachary Turner PythonCallable::PythonCallable(const PythonCallable &callable) 1073a1405147SZachary Turner : PythonObject(callable) 1074a1405147SZachary Turner { 1075a1405147SZachary Turner } 1076a1405147SZachary Turner 1077a1405147SZachary Turner PythonCallable::~PythonCallable() 1078a1405147SZachary Turner { 1079a1405147SZachary Turner } 1080a1405147SZachary Turner 1081a1405147SZachary Turner bool 1082a1405147SZachary Turner PythonCallable::Check(PyObject *py_obj) 1083a1405147SZachary Turner { 1084a1405147SZachary Turner if (!py_obj) 1085a1405147SZachary Turner return false; 1086a1405147SZachary Turner 1087a1405147SZachary Turner return PyCallable_Check(py_obj); 1088a1405147SZachary Turner } 1089a1405147SZachary Turner 1090a1405147SZachary Turner void 1091a1405147SZachary Turner PythonCallable::Reset(PyRefType type, PyObject *py_obj) 1092a1405147SZachary Turner { 1093a1405147SZachary Turner // Grab the desired reference type so that if we end up rejecting 1094a1405147SZachary Turner // `py_obj` it still gets decremented if necessary. 1095a1405147SZachary Turner PythonObject result(type, py_obj); 1096a1405147SZachary Turner 1097a1405147SZachary Turner if (!PythonCallable::Check(py_obj)) 1098a1405147SZachary Turner { 1099a1405147SZachary Turner PythonObject::Reset(); 1100a1405147SZachary Turner return; 1101a1405147SZachary Turner } 1102a1405147SZachary Turner 1103a1405147SZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 1104a1405147SZachary Turner // back into the virtual implementation. 1105a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 1106a1405147SZachary Turner } 1107a1405147SZachary Turner 1108a1405147SZachary Turner 1109b58fb2f4SZachary Turner PythonCallable::ArgInfo 1110b58fb2f4SZachary Turner PythonCallable::GetNumArguments() const 1111a1405147SZachary Turner { 1112b58fb2f4SZachary Turner ArgInfo result = { 0, false, false }; 1113a1405147SZachary Turner if (!IsValid()) 1114b58fb2f4SZachary Turner return result; 1115a1405147SZachary Turner 1116a1405147SZachary Turner PyObject *py_func_obj = m_py_obj; 1117a1405147SZachary Turner if (PyMethod_Check(py_func_obj)) 1118a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 1119a1405147SZachary Turner 1120a1405147SZachary Turner if (!py_func_obj) 1121b58fb2f4SZachary Turner return result; 1122a1405147SZachary Turner 1123a1405147SZachary Turner PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj); 1124a1405147SZachary Turner if (!code) 1125b58fb2f4SZachary Turner return result; 1126a1405147SZachary Turner 1127b58fb2f4SZachary Turner result.count = code->co_argcount; 1128b58fb2f4SZachary Turner result.has_varargs = !!(code->co_flags & CO_VARARGS); 1129b58fb2f4SZachary Turner result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); 1130b58fb2f4SZachary Turner return result; 1131b58fb2f4SZachary Turner } 1132b58fb2f4SZachary Turner 1133b58fb2f4SZachary Turner PythonObject 1134b58fb2f4SZachary Turner PythonCallable::operator ()() 1135b58fb2f4SZachary Turner { 1136b58fb2f4SZachary Turner return PythonObject(PyRefType::Owned, 1137b58fb2f4SZachary Turner PyObject_CallObject(m_py_obj, nullptr)); 1138a1405147SZachary Turner } 1139a1405147SZachary Turner 1140a1405147SZachary Turner PythonObject 1141a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PyObject*> args) 1142a1405147SZachary Turner { 1143a1405147SZachary Turner PythonTuple arg_tuple(args); 1144a1405147SZachary Turner return PythonObject(PyRefType::Owned, 1145a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 1146a1405147SZachary Turner } 1147a1405147SZachary Turner 1148a1405147SZachary Turner PythonObject 1149a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PythonObject> args) 1150a1405147SZachary Turner { 1151a1405147SZachary Turner PythonTuple arg_tuple(args); 1152a1405147SZachary Turner return PythonObject(PyRefType::Owned, 1153a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 1154a1405147SZachary Turner } 1155a1405147SZachary Turner 115632064024SZachary Turner PythonFile::PythonFile() 115732064024SZachary Turner : PythonObject() 115832064024SZachary Turner { 115932064024SZachary Turner } 116032064024SZachary Turner 11619c40264fSZachary Turner PythonFile::PythonFile(File &file, const char *mode) 11629c40264fSZachary Turner { 11639c40264fSZachary Turner Reset(file, mode); 11649c40264fSZachary Turner } 11659c40264fSZachary Turner 1166eda01c31SZachary Turner PythonFile::PythonFile(const char *path, const char *mode) 1167eda01c31SZachary Turner { 1168*190fadcdSZachary Turner lldb_private::File file(path, GetOptionsFromMode(mode)); 1169eda01c31SZachary Turner Reset(file, mode); 1170eda01c31SZachary Turner } 1171eda01c31SZachary Turner 11729c40264fSZachary Turner PythonFile::PythonFile(PyRefType type, PyObject *o) 11739c40264fSZachary Turner { 11749c40264fSZachary Turner Reset(type, o); 11759c40264fSZachary Turner } 11769c40264fSZachary Turner 11779c40264fSZachary Turner PythonFile::~PythonFile() 11789c40264fSZachary Turner { 11799c40264fSZachary Turner } 11809c40264fSZachary Turner 11819c40264fSZachary Turner bool 11829c40264fSZachary Turner PythonFile::Check(PyObject *py_obj) 11839c40264fSZachary Turner { 11849c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 11859c40264fSZachary Turner return PyFile_Check(py_obj); 11869c40264fSZachary Turner #else 11879c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 11889c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 11899c40264fSZachary Turner // over `io.open()`, which returns some object derived from `io.IOBase`. 11909c40264fSZachary Turner // As a result, the only way to detect a file in Python 3 is to check whether 11919c40264fSZachary Turner // it inherits from `io.IOBase`. Since it is possible for non-files to also 11929c40264fSZachary Turner // inherit from `io.IOBase`, we additionally verify that it has the `fileno` 11939c40264fSZachary Turner // attribute, which should guarantee that it is backed by the file system. 11949c40264fSZachary Turner PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); 11959c40264fSZachary Turner PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get())); 11969c40264fSZachary Turner PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); 11979c40264fSZachary Turner 11989c40264fSZachary Turner PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); 11999c40264fSZachary Turner 12009c40264fSZachary Turner if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) 12019c40264fSZachary Turner return false; 12029c40264fSZachary Turner if (!object_type.HasAttribute("fileno")) 12039c40264fSZachary Turner return false; 12049c40264fSZachary Turner 12059c40264fSZachary Turner return true; 12069c40264fSZachary Turner #endif 12079c40264fSZachary Turner } 12089c40264fSZachary Turner 12099c40264fSZachary Turner void 12109c40264fSZachary Turner PythonFile::Reset(PyRefType type, PyObject *py_obj) 12119c40264fSZachary Turner { 12129c40264fSZachary Turner // Grab the desired reference type so that if we end up rejecting 12139c40264fSZachary Turner // `py_obj` it still gets decremented if necessary. 12149c40264fSZachary Turner PythonObject result(type, py_obj); 12159c40264fSZachary Turner 12169c40264fSZachary Turner if (!PythonFile::Check(py_obj)) 12179c40264fSZachary Turner { 12189c40264fSZachary Turner PythonObject::Reset(); 12199c40264fSZachary Turner return; 12209c40264fSZachary Turner } 12219c40264fSZachary Turner 12229c40264fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack 12239c40264fSZachary Turner // overflow since it calls back into the virtual implementation. 12249c40264fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 12259c40264fSZachary Turner } 12269c40264fSZachary Turner 12279c40264fSZachary Turner void 12289c40264fSZachary Turner PythonFile::Reset(File &file, const char *mode) 12299c40264fSZachary Turner { 123032ac147bSZachary Turner if (!file.IsValid()) 123132ac147bSZachary Turner { 123232ac147bSZachary Turner Reset(); 123332ac147bSZachary Turner return; 123432ac147bSZachary Turner } 123532ac147bSZachary Turner 12369c40264fSZachary Turner char *cmode = const_cast<char *>(mode); 12379c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3 12389c40264fSZachary Turner Reset(PyRefType::Owned, 12399c40264fSZachary Turner PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0)); 12409c40264fSZachary Turner #else 12419c40264fSZachary Turner // Read through the Python source, doesn't seem to modify these strings 12429c40264fSZachary Turner Reset(PyRefType::Owned, 12439c40264fSZachary Turner PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr)); 12449c40264fSZachary Turner #endif 12459c40264fSZachary Turner } 12469c40264fSZachary Turner 1247744959b9SEnrico Granata uint32_t 1248744959b9SEnrico Granata PythonFile::GetOptionsFromMode(llvm::StringRef mode) 1249744959b9SEnrico Granata { 1250744959b9SEnrico Granata if (mode.empty()) 1251744959b9SEnrico Granata return 0; 1252744959b9SEnrico Granata 1253744959b9SEnrico Granata return llvm::StringSwitch<uint32_t>(mode.str().c_str()) 1254744959b9SEnrico Granata .Case("r", File::eOpenOptionRead) 1255744959b9SEnrico Granata .Case("w", File::eOpenOptionWrite) 1256744959b9SEnrico Granata .Case("a", File::eOpenOptionAppend|File::eOpenOptionCanCreate) 1257744959b9SEnrico Granata .Case("r+", File::eOpenOptionRead|File::eOpenOptionWrite) 1258744959b9SEnrico Granata .Case("w+", File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionCanCreate|File::eOpenOptionTruncate) 1259744959b9SEnrico Granata .Case("a+", File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionCanCreate) 1260744959b9SEnrico Granata .Default(0); 1261744959b9SEnrico Granata } 1262744959b9SEnrico Granata 1263eda01c31SZachary Turner bool 1264eda01c31SZachary Turner PythonFile::GetUnderlyingFile(File &file) const 1265eda01c31SZachary Turner { 1266eda01c31SZachary Turner if (!IsValid()) 1267eda01c31SZachary Turner return false; 1268eda01c31SZachary Turner 1269eda01c31SZachary Turner file.Close(); 1270eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 1271eda01c31SZachary Turner // File object knows about that. 1272eda01c31SZachary Turner file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); 1273744959b9SEnrico Granata PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); 1274744959b9SEnrico Granata file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString())); 1275eda01c31SZachary Turner return file.IsValid(); 1276eda01c31SZachary Turner } 1277eda01c31SZachary Turner 1278eda01c31SZachary Turner 12792c1f46dcSZachary Turner #endif 1280