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 26744959b9SEnrico Granata #include "llvm/ADT/StringSwitch.h" 27744959b9SEnrico Granata 282c1f46dcSZachary Turner using namespace lldb_private; 292c1f46dcSZachary Turner using namespace lldb; 302c1f46dcSZachary Turner 312c1f46dcSZachary Turner void 322c1f46dcSZachary Turner StructuredPythonObject::Dump(Stream &s) const 332c1f46dcSZachary Turner { 342c1f46dcSZachary Turner s << "Python Obj: 0x" << GetValue(); 352c1f46dcSZachary Turner } 362c1f46dcSZachary Turner 372c1f46dcSZachary Turner //---------------------------------------------------------------------- 382c1f46dcSZachary Turner // PythonObject 392c1f46dcSZachary Turner //---------------------------------------------------------------------- 402c1f46dcSZachary Turner 412c1f46dcSZachary Turner void 422c1f46dcSZachary Turner PythonObject::Dump(Stream &strm) const 432c1f46dcSZachary Turner { 442c1f46dcSZachary Turner if (m_py_obj) 452c1f46dcSZachary Turner { 462c1f46dcSZachary Turner FILE *file = ::tmpfile(); 472c1f46dcSZachary Turner if (file) 482c1f46dcSZachary Turner { 492c1f46dcSZachary Turner ::PyObject_Print (m_py_obj, file, 0); 502c1f46dcSZachary Turner const long length = ftell (file); 512c1f46dcSZachary Turner if (length) 522c1f46dcSZachary Turner { 532c1f46dcSZachary Turner ::rewind(file); 542c1f46dcSZachary Turner std::vector<char> file_contents (length,'\0'); 552c1f46dcSZachary Turner const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file); 562c1f46dcSZachary Turner if (length_read > 0) 572c1f46dcSZachary Turner strm.Write (file_contents.data(), length_read); 582c1f46dcSZachary Turner } 592c1f46dcSZachary Turner ::fclose (file); 602c1f46dcSZachary Turner } 612c1f46dcSZachary Turner } 622c1f46dcSZachary Turner else 632c1f46dcSZachary Turner strm.PutCString ("NULL"); 642c1f46dcSZachary Turner } 652c1f46dcSZachary Turner 662c1f46dcSZachary Turner PyObjectType 672c1f46dcSZachary Turner PythonObject::GetObjectType() const 682c1f46dcSZachary Turner { 69f8b22f8fSZachary Turner if (!IsAllocated()) 702c1f46dcSZachary Turner return PyObjectType::None; 712c1f46dcSZachary Turner 727841efbbSZachary Turner if (PythonModule::Check(m_py_obj)) 737841efbbSZachary Turner return PyObjectType::Module; 7418426935SZachary Turner if (PythonList::Check(m_py_obj)) 752c1f46dcSZachary Turner return PyObjectType::List; 76a1405147SZachary Turner if (PythonTuple::Check(m_py_obj)) 77a1405147SZachary Turner return PyObjectType::Tuple; 7818426935SZachary Turner if (PythonDictionary::Check(m_py_obj)) 792c1f46dcSZachary Turner return PyObjectType::Dictionary; 8018426935SZachary Turner if (PythonString::Check(m_py_obj)) 8122c8efcdSZachary Turner return PyObjectType::String; 825a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3 835a72c02bSZachary Turner if (PythonBytes::Check(m_py_obj)) 845a72c02bSZachary Turner return PyObjectType::Bytes; 855a72c02bSZachary Turner #endif 86*f9d6d204SZachary Turner if (PythonByteArray::Check(m_py_obj)) 87*f9d6d204SZachary Turner return PyObjectType::ByteArray; 8818426935SZachary Turner if (PythonInteger::Check(m_py_obj)) 8922c8efcdSZachary Turner return PyObjectType::Integer; 909c40264fSZachary Turner if (PythonFile::Check(m_py_obj)) 919c40264fSZachary Turner return PyObjectType::File; 92a1405147SZachary Turner if (PythonCallable::Check(m_py_obj)) 93a1405147SZachary Turner return PyObjectType::Callable; 942c1f46dcSZachary Turner return PyObjectType::Unknown; 952c1f46dcSZachary Turner } 962c1f46dcSZachary Turner 972c1f46dcSZachary Turner PythonString 987841efbbSZachary Turner PythonObject::Repr() const 992c1f46dcSZachary Turner { 1002c1f46dcSZachary Turner if (!m_py_obj) 1012c1f46dcSZachary Turner return PythonString(); 1022c1f46dcSZachary Turner PyObject *repr = PyObject_Repr(m_py_obj); 1032c1f46dcSZachary Turner if (!repr) 1042c1f46dcSZachary Turner return PythonString(); 105f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, repr); 1062c1f46dcSZachary Turner } 1072c1f46dcSZachary Turner 1082c1f46dcSZachary Turner PythonString 1097841efbbSZachary Turner PythonObject::Str() const 1102c1f46dcSZachary Turner { 1112c1f46dcSZachary Turner if (!m_py_obj) 1122c1f46dcSZachary Turner return PythonString(); 1132c1f46dcSZachary Turner PyObject *str = PyObject_Str(m_py_obj); 1142c1f46dcSZachary Turner if (!str) 1152c1f46dcSZachary Turner return PythonString(); 116f8b22f8fSZachary Turner return PythonString(PyRefType::Owned, str); 1172c1f46dcSZachary Turner } 1182c1f46dcSZachary Turner 1197841efbbSZachary Turner PythonObject 12002bf92d2SZachary Turner PythonObject::ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict) 1217841efbbSZachary Turner { 122a1405147SZachary Turner size_t dot_pos = name.find_first_of('.'); 123a1405147SZachary Turner llvm::StringRef piece = name.substr(0, dot_pos); 124a1405147SZachary Turner PythonObject result = dict.GetItemForKey(PythonString(piece)); 125a1405147SZachary Turner if (dot_pos == llvm::StringRef::npos) 126a1405147SZachary Turner { 127a1405147SZachary Turner // There was no dot, we're done. 128a1405147SZachary Turner return result; 129a1405147SZachary Turner } 130a1405147SZachary Turner 131a1405147SZachary Turner // There was a dot. The remaining portion of the name should be looked up in 132a1405147SZachary Turner // the context of the object that was found in the dictionary. 133a1405147SZachary Turner return result.ResolveName(name.substr(dot_pos + 1)); 1347841efbbSZachary Turner } 1357841efbbSZachary Turner 1367841efbbSZachary Turner PythonObject 1377841efbbSZachary Turner PythonObject::ResolveName(llvm::StringRef name) const 1387841efbbSZachary Turner { 1397841efbbSZachary Turner // Resolve the name in the context of the specified object. If, 1407841efbbSZachary Turner // for example, `this` refers to a PyModule, then this will look for 1417841efbbSZachary Turner // `name` in this module. If `this` refers to a PyType, then it will 1427841efbbSZachary Turner // resolve `name` as an attribute of that type. If `this` refers to 1437841efbbSZachary Turner // an instance of an object, then it will resolve `name` as the value 1447841efbbSZachary Turner // of the specified field. 1457841efbbSZachary Turner // 1467841efbbSZachary Turner // This function handles dotted names so that, for example, if `m_py_obj` 1477841efbbSZachary Turner // refers to the `sys` module, and `name` == "path.append", then it 1487841efbbSZachary Turner // will find the function `sys.path.append`. 1497841efbbSZachary Turner 1507841efbbSZachary Turner size_t dot_pos = name.find_first_of('.'); 1517841efbbSZachary Turner if (dot_pos == llvm::StringRef::npos) 1527841efbbSZachary Turner { 1537841efbbSZachary Turner // No dots in the name, we should be able to find the value immediately 154a1405147SZachary Turner // as an attribute of `m_py_obj`. 1557841efbbSZachary Turner return GetAttributeValue(name); 1567841efbbSZachary Turner } 1577841efbbSZachary Turner 1587841efbbSZachary Turner // Look up the first piece of the name, and resolve the rest as a child of that. 1597841efbbSZachary Turner PythonObject parent = ResolveName(name.substr(0, dot_pos)); 1607841efbbSZachary Turner if (!parent.IsAllocated()) 1617841efbbSZachary Turner return PythonObject(); 1627841efbbSZachary Turner 1637841efbbSZachary Turner // Tail recursion.. should be optimized by the compiler 1647841efbbSZachary Turner return parent.ResolveName(name.substr(dot_pos + 1)); 1657841efbbSZachary Turner } 1667841efbbSZachary Turner 1672c1f46dcSZachary Turner bool 1689c40264fSZachary Turner PythonObject::HasAttribute(llvm::StringRef attr) const 1699c40264fSZachary Turner { 1709c40264fSZachary Turner if (!IsValid()) 1719c40264fSZachary Turner return false; 1729c40264fSZachary Turner PythonString py_attr(attr); 1739c40264fSZachary Turner return !!PyObject_HasAttr(m_py_obj, py_attr.get()); 1749c40264fSZachary Turner } 1759c40264fSZachary Turner 1767d6d218eSZachary Turner PythonObject 1777d6d218eSZachary Turner PythonObject::GetAttributeValue(llvm::StringRef attr) const 1787d6d218eSZachary Turner { 1797d6d218eSZachary Turner if (!IsValid()) 1807d6d218eSZachary Turner return PythonObject(); 1817d6d218eSZachary Turner 1827d6d218eSZachary Turner PythonString py_attr(attr); 1837d6d218eSZachary Turner if (!PyObject_HasAttr(m_py_obj, py_attr.get())) 1847d6d218eSZachary Turner return PythonObject(); 1857d6d218eSZachary Turner 1867d6d218eSZachary Turner return PythonObject(PyRefType::Owned, 1877d6d218eSZachary Turner PyObject_GetAttr(m_py_obj, py_attr.get())); 1887d6d218eSZachary Turner } 1897d6d218eSZachary Turner 1909c40264fSZachary Turner bool 191f8b22f8fSZachary Turner PythonObject::IsNone() const 1922c1f46dcSZachary Turner { 193f8b22f8fSZachary Turner return m_py_obj == Py_None; 194f8b22f8fSZachary Turner } 195f8b22f8fSZachary Turner 196f8b22f8fSZachary Turner bool 197f8b22f8fSZachary Turner PythonObject::IsValid() const 198f8b22f8fSZachary Turner { 199f8b22f8fSZachary Turner return m_py_obj != nullptr; 200f8b22f8fSZachary Turner } 201f8b22f8fSZachary Turner 202f8b22f8fSZachary Turner bool 203f8b22f8fSZachary Turner PythonObject::IsAllocated() const 204f8b22f8fSZachary Turner { 205f8b22f8fSZachary Turner return IsValid() && !IsNone(); 2062c1f46dcSZachary Turner } 2072c1f46dcSZachary Turner 2082c1f46dcSZachary Turner StructuredData::ObjectSP 2092c1f46dcSZachary Turner PythonObject::CreateStructuredObject() const 2102c1f46dcSZachary Turner { 2112c1f46dcSZachary Turner switch (GetObjectType()) 2122c1f46dcSZachary Turner { 2132c1f46dcSZachary Turner case PyObjectType::Dictionary: 214f8b22f8fSZachary Turner return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary(); 2152c1f46dcSZachary Turner case PyObjectType::Integer: 216f8b22f8fSZachary Turner return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger(); 2172c1f46dcSZachary Turner case PyObjectType::List: 218f8b22f8fSZachary Turner return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); 2192c1f46dcSZachary Turner case PyObjectType::String: 220f8b22f8fSZachary Turner return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 2215a72c02bSZachary Turner case PyObjectType::Bytes: 2225a72c02bSZachary Turner return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 223*f9d6d204SZachary Turner case PyObjectType::ByteArray: 224*f9d6d204SZachary Turner return PythonByteArray(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); 2252c1f46dcSZachary Turner case PyObjectType::None: 2262c1f46dcSZachary Turner return StructuredData::ObjectSP(); 2272c1f46dcSZachary Turner default: 2282c1f46dcSZachary Turner return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); 2292c1f46dcSZachary Turner } 2302c1f46dcSZachary Turner } 2312c1f46dcSZachary Turner 2322c1f46dcSZachary Turner //---------------------------------------------------------------------- 2332c1f46dcSZachary Turner // PythonString 2342c1f46dcSZachary Turner //---------------------------------------------------------------------- 2355a72c02bSZachary Turner PythonBytes::PythonBytes() : PythonObject() 2365a72c02bSZachary Turner { 2375a72c02bSZachary Turner } 2385a72c02bSZachary Turner 2395a72c02bSZachary Turner PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() 2405a72c02bSZachary Turner { 2415a72c02bSZachary Turner SetBytes(bytes); 2425a72c02bSZachary Turner } 2435a72c02bSZachary Turner 2445a72c02bSZachary Turner PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() 2455a72c02bSZachary Turner { 2465a72c02bSZachary Turner SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); 2475a72c02bSZachary Turner } 2485a72c02bSZachary Turner 2495a72c02bSZachary Turner PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() 2505a72c02bSZachary Turner { 2515a72c02bSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string 2525a72c02bSZachary Turner } 2535a72c02bSZachary Turner 2545a72c02bSZachary Turner PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object) 2555a72c02bSZachary Turner { 2565a72c02bSZachary Turner } 2575a72c02bSZachary Turner 2585a72c02bSZachary Turner PythonBytes::~PythonBytes() 2595a72c02bSZachary Turner { 2605a72c02bSZachary Turner } 2615a72c02bSZachary Turner 2625a72c02bSZachary Turner bool 2635a72c02bSZachary Turner PythonBytes::Check(PyObject *py_obj) 2645a72c02bSZachary Turner { 2655a72c02bSZachary Turner if (!py_obj) 2665a72c02bSZachary Turner return false; 2675a72c02bSZachary Turner if (PyBytes_Check(py_obj)) 2685a72c02bSZachary Turner return true; 2695a72c02bSZachary Turner return false; 2705a72c02bSZachary Turner } 2715a72c02bSZachary Turner 2725a72c02bSZachary Turner void 2735a72c02bSZachary Turner PythonBytes::Reset(PyRefType type, PyObject *py_obj) 2745a72c02bSZachary Turner { 2755a72c02bSZachary Turner // Grab the desired reference type so that if we end up rejecting 2765a72c02bSZachary Turner // `py_obj` it still gets decremented if necessary. 2775a72c02bSZachary Turner PythonObject result(type, py_obj); 2785a72c02bSZachary Turner 2795a72c02bSZachary Turner if (!PythonBytes::Check(py_obj)) 2805a72c02bSZachary Turner { 2815a72c02bSZachary Turner PythonObject::Reset(); 2825a72c02bSZachary Turner return; 2835a72c02bSZachary Turner } 2845a72c02bSZachary Turner 2855a72c02bSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 2865a72c02bSZachary Turner // back into the virtual implementation. 2875a72c02bSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 2885a72c02bSZachary Turner } 2895a72c02bSZachary Turner 2905a72c02bSZachary Turner llvm::ArrayRef<uint8_t> 2915a72c02bSZachary Turner PythonBytes::GetBytes() const 2925a72c02bSZachary Turner { 2935a72c02bSZachary Turner if (!IsValid()) 2945a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(); 2955a72c02bSZachary Turner 2965a72c02bSZachary Turner Py_ssize_t size; 2975a72c02bSZachary Turner char *c; 2985a72c02bSZachary Turner 2995a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 3005a72c02bSZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 3015a72c02bSZachary Turner } 3025a72c02bSZachary Turner 3035a72c02bSZachary Turner size_t 3045a72c02bSZachary Turner PythonBytes::GetSize() const 3055a72c02bSZachary Turner { 3065a72c02bSZachary Turner if (!IsValid()) 3075a72c02bSZachary Turner return 0; 3085a72c02bSZachary Turner return PyBytes_Size(m_py_obj); 3095a72c02bSZachary Turner } 3105a72c02bSZachary Turner 3115a72c02bSZachary Turner void 3125a72c02bSZachary Turner PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) 3135a72c02bSZachary Turner { 3145a72c02bSZachary Turner const char *data = reinterpret_cast<const char *>(bytes.data()); 3155a72c02bSZachary Turner PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size()); 3165a72c02bSZachary Turner PythonObject::Reset(PyRefType::Owned, py_bytes); 3175a72c02bSZachary Turner } 3185a72c02bSZachary Turner 3195a72c02bSZachary Turner StructuredData::StringSP 3205a72c02bSZachary Turner PythonBytes::CreateStructuredString() const 3215a72c02bSZachary Turner { 3225a72c02bSZachary Turner StructuredData::StringSP result(new StructuredData::String); 3235a72c02bSZachary Turner Py_ssize_t size; 3245a72c02bSZachary Turner char *c; 3255a72c02bSZachary Turner PyBytes_AsStringAndSize(m_py_obj, &c, &size); 3265a72c02bSZachary Turner result->SetValue(std::string(c, size)); 3275a72c02bSZachary Turner return result; 3285a72c02bSZachary Turner } 3295a72c02bSZachary Turner 330*f9d6d204SZachary Turner PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) : PythonByteArray(bytes.data(), bytes.size()) 331*f9d6d204SZachary Turner { 332*f9d6d204SZachary Turner } 333*f9d6d204SZachary Turner 334*f9d6d204SZachary Turner PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) 335*f9d6d204SZachary Turner { 336*f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes); 337*f9d6d204SZachary Turner Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length)); 338*f9d6d204SZachary Turner } 339*f9d6d204SZachary Turner 340*f9d6d204SZachary Turner PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) 341*f9d6d204SZachary Turner { 342*f9d6d204SZachary Turner Reset(type, o); 343*f9d6d204SZachary Turner } 344*f9d6d204SZachary Turner 345*f9d6d204SZachary Turner PythonByteArray::PythonByteArray(const PythonBytes &object) : PythonObject(object) 346*f9d6d204SZachary Turner { 347*f9d6d204SZachary Turner } 348*f9d6d204SZachary Turner 349*f9d6d204SZachary Turner PythonByteArray::~PythonByteArray() 350*f9d6d204SZachary Turner { 351*f9d6d204SZachary Turner } 352*f9d6d204SZachary Turner 353*f9d6d204SZachary Turner bool 354*f9d6d204SZachary Turner PythonByteArray::Check(PyObject *py_obj) 355*f9d6d204SZachary Turner { 356*f9d6d204SZachary Turner if (!py_obj) 357*f9d6d204SZachary Turner return false; 358*f9d6d204SZachary Turner if (PyByteArray_Check(py_obj)) 359*f9d6d204SZachary Turner return true; 360*f9d6d204SZachary Turner return false; 361*f9d6d204SZachary Turner } 362*f9d6d204SZachary Turner 363*f9d6d204SZachary Turner void 364*f9d6d204SZachary Turner PythonByteArray::Reset(PyRefType type, PyObject *py_obj) 365*f9d6d204SZachary Turner { 366*f9d6d204SZachary Turner // Grab the desired reference type so that if we end up rejecting 367*f9d6d204SZachary Turner // `py_obj` it still gets decremented if necessary. 368*f9d6d204SZachary Turner PythonObject result(type, py_obj); 369*f9d6d204SZachary Turner 370*f9d6d204SZachary Turner if (!PythonByteArray::Check(py_obj)) 371*f9d6d204SZachary Turner { 372*f9d6d204SZachary Turner PythonObject::Reset(); 373*f9d6d204SZachary Turner return; 374*f9d6d204SZachary Turner } 375*f9d6d204SZachary Turner 376*f9d6d204SZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 377*f9d6d204SZachary Turner // back into the virtual implementation. 378*f9d6d204SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 379*f9d6d204SZachary Turner } 380*f9d6d204SZachary Turner 381*f9d6d204SZachary Turner llvm::ArrayRef<uint8_t> 382*f9d6d204SZachary Turner PythonByteArray::GetBytes() const 383*f9d6d204SZachary Turner { 384*f9d6d204SZachary Turner if (!IsValid()) 385*f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(); 386*f9d6d204SZachary Turner 387*f9d6d204SZachary Turner char *c = PyByteArray_AsString(m_py_obj); 388*f9d6d204SZachary Turner size_t size = GetSize(); 389*f9d6d204SZachary Turner return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); 390*f9d6d204SZachary Turner } 391*f9d6d204SZachary Turner 392*f9d6d204SZachary Turner size_t 393*f9d6d204SZachary Turner PythonByteArray::GetSize() const 394*f9d6d204SZachary Turner { 395*f9d6d204SZachary Turner if (!IsValid()) 396*f9d6d204SZachary Turner return 0; 397*f9d6d204SZachary Turner 398*f9d6d204SZachary Turner return PyByteArray_Size(m_py_obj); 399*f9d6d204SZachary Turner } 400*f9d6d204SZachary Turner 401*f9d6d204SZachary Turner StructuredData::StringSP 402*f9d6d204SZachary Turner PythonByteArray::CreateStructuredString() const 403*f9d6d204SZachary Turner { 404*f9d6d204SZachary Turner StructuredData::StringSP result(new StructuredData::String); 405*f9d6d204SZachary Turner llvm::ArrayRef<uint8_t> bytes = GetBytes(); 406*f9d6d204SZachary Turner const char *str = reinterpret_cast<const char *>(bytes.data()); 407*f9d6d204SZachary Turner result->SetValue(std::string(str, bytes.size())); 408*f9d6d204SZachary Turner return result; 409*f9d6d204SZachary Turner } 410*f9d6d204SZachary Turner 4115a72c02bSZachary Turner //---------------------------------------------------------------------- 4125a72c02bSZachary Turner // PythonString 4135a72c02bSZachary Turner //---------------------------------------------------------------------- 4142c1f46dcSZachary Turner 415f8b22f8fSZachary Turner PythonString::PythonString(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 string 4192c1f46dcSZachary Turner } 4202c1f46dcSZachary Turner 421f8b22f8fSZachary Turner PythonString::PythonString(const PythonString &object) 422f8b22f8fSZachary Turner : PythonObject(object) 4232c1f46dcSZachary Turner { 4242c1f46dcSZachary Turner } 4252c1f46dcSZachary Turner 42622c8efcdSZachary Turner PythonString::PythonString(llvm::StringRef string) 42722c8efcdSZachary Turner : PythonObject() 4282c1f46dcSZachary Turner { 42922c8efcdSZachary Turner SetString(string); 4302c1f46dcSZachary Turner } 4312c1f46dcSZachary Turner 43222c8efcdSZachary Turner PythonString::PythonString(const char *string) 43322c8efcdSZachary Turner : PythonObject() 4342c1f46dcSZachary Turner { 43522c8efcdSZachary Turner SetString(llvm::StringRef(string)); 4362c1f46dcSZachary Turner } 4372c1f46dcSZachary Turner 438f8b22f8fSZachary Turner PythonString::PythonString() 439f8b22f8fSZachary Turner : PythonObject() 4402c1f46dcSZachary Turner { 4412c1f46dcSZachary Turner } 4422c1f46dcSZachary Turner 4432c1f46dcSZachary Turner PythonString::~PythonString () 4442c1f46dcSZachary Turner { 4452c1f46dcSZachary Turner } 4462c1f46dcSZachary Turner 4472c1f46dcSZachary Turner bool 44822c8efcdSZachary Turner PythonString::Check(PyObject *py_obj) 44922c8efcdSZachary Turner { 45022c8efcdSZachary Turner if (!py_obj) 45122c8efcdSZachary Turner return false; 45218426935SZachary Turner 4537d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 4547d6d218eSZachary Turner return true; 4557d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 4567d6d218eSZachary Turner if (PyString_Check(py_obj)) 4577d6d218eSZachary Turner return true; 45822c8efcdSZachary Turner #endif 4597d6d218eSZachary Turner return false; 46022c8efcdSZachary Turner } 46122c8efcdSZachary Turner 462f8b22f8fSZachary Turner void 463f8b22f8fSZachary Turner PythonString::Reset(PyRefType type, PyObject *py_obj) 4642c1f46dcSZachary Turner { 465f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 466f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 467f8b22f8fSZachary Turner PythonObject result(type, py_obj); 468f8b22f8fSZachary Turner 46922c8efcdSZachary Turner if (!PythonString::Check(py_obj)) 47022c8efcdSZachary Turner { 471f8b22f8fSZachary Turner PythonObject::Reset(); 472f8b22f8fSZachary Turner return; 47322c8efcdSZachary Turner } 4747d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3 4757d6d218eSZachary Turner // In Python 2, Don't store PyUnicode objects directly, because we need 4767d6d218eSZachary Turner // access to their underlying character buffers which Python 2 doesn't 4777d6d218eSZachary Turner // provide. 4787d6d218eSZachary Turner if (PyUnicode_Check(py_obj)) 4797d6d218eSZachary Turner result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get())); 4807d6d218eSZachary Turner #endif 481f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 482f8b22f8fSZachary Turner // back into the virtual implementation. 483f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 4842c1f46dcSZachary Turner } 4852c1f46dcSZachary Turner 4862c1f46dcSZachary Turner llvm::StringRef 4872c1f46dcSZachary Turner PythonString::GetString() const 4882c1f46dcSZachary Turner { 48918426935SZachary Turner if (!IsValid()) 49018426935SZachary Turner return llvm::StringRef(); 49118426935SZachary Turner 49222c8efcdSZachary Turner Py_ssize_t size; 49322c8efcdSZachary Turner char *c; 49418426935SZachary Turner 49518426935SZachary Turner #if PY_MAJOR_VERSION >= 3 49618426935SZachary Turner c = PyUnicode_AsUTF8AndSize(m_py_obj, &size); 49718426935SZachary Turner #else 49818426935SZachary Turner PyString_AsStringAndSize(m_py_obj, &c, &size); 49918426935SZachary Turner #endif 50022c8efcdSZachary Turner return llvm::StringRef(c, size); 50122c8efcdSZachary Turner } 5022c1f46dcSZachary Turner 5032c1f46dcSZachary Turner size_t 5042c1f46dcSZachary Turner PythonString::GetSize() const 5052c1f46dcSZachary Turner { 506f8b22f8fSZachary Turner if (IsValid()) 50718426935SZachary Turner { 50818426935SZachary Turner #if PY_MAJOR_VERSION >= 3 50918426935SZachary Turner return PyUnicode_GetSize(m_py_obj); 51018426935SZachary Turner #else 51118426935SZachary Turner return PyString_Size(m_py_obj); 51218426935SZachary Turner #endif 51318426935SZachary Turner } 5142c1f46dcSZachary Turner return 0; 5152c1f46dcSZachary Turner } 5162c1f46dcSZachary Turner 5172c1f46dcSZachary Turner void 5182c1f46dcSZachary Turner PythonString::SetString (llvm::StringRef string) 5192c1f46dcSZachary Turner { 52022c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 52122c8efcdSZachary Turner PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size()); 52218426935SZachary Turner PythonObject::Reset(PyRefType::Owned, unicode); 52322c8efcdSZachary Turner #else 52418426935SZachary Turner PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); 52518426935SZachary Turner PythonObject::Reset(PyRefType::Owned, str); 52622c8efcdSZachary Turner #endif 5272c1f46dcSZachary Turner } 5282c1f46dcSZachary Turner 5292c1f46dcSZachary Turner StructuredData::StringSP 5302c1f46dcSZachary Turner PythonString::CreateStructuredString() const 5312c1f46dcSZachary Turner { 5322c1f46dcSZachary Turner StructuredData::StringSP result(new StructuredData::String); 5332c1f46dcSZachary Turner result->SetValue(GetString()); 5342c1f46dcSZachary Turner return result; 5352c1f46dcSZachary Turner } 5362c1f46dcSZachary Turner 5372c1f46dcSZachary Turner //---------------------------------------------------------------------- 5382c1f46dcSZachary Turner // PythonInteger 5392c1f46dcSZachary Turner //---------------------------------------------------------------------- 5402c1f46dcSZachary Turner 5417d6d218eSZachary Turner PythonInteger::PythonInteger() 5427d6d218eSZachary Turner : PythonObject() 5437d6d218eSZachary Turner { 5447d6d218eSZachary Turner 5457d6d218eSZachary Turner } 5467d6d218eSZachary Turner 547f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) 548f8b22f8fSZachary Turner : PythonObject() 5492c1f46dcSZachary Turner { 550f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type 5512c1f46dcSZachary Turner } 5522c1f46dcSZachary Turner 553f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object) 554f8b22f8fSZachary Turner : PythonObject(object) 5552c1f46dcSZachary Turner { 5562c1f46dcSZachary Turner } 5572c1f46dcSZachary Turner 558f8b22f8fSZachary Turner PythonInteger::PythonInteger(int64_t value) 559f8b22f8fSZachary Turner : PythonObject() 5602c1f46dcSZachary Turner { 5612c1f46dcSZachary Turner SetInteger(value); 5622c1f46dcSZachary Turner } 5632c1f46dcSZachary Turner 5642c1f46dcSZachary Turner 5652c1f46dcSZachary Turner PythonInteger::~PythonInteger () 5662c1f46dcSZachary Turner { 5672c1f46dcSZachary Turner } 5682c1f46dcSZachary Turner 5692c1f46dcSZachary Turner bool 57022c8efcdSZachary Turner PythonInteger::Check(PyObject *py_obj) 5712c1f46dcSZachary Turner { 57222c8efcdSZachary Turner if (!py_obj) 57322c8efcdSZachary Turner return false; 57422c8efcdSZachary Turner 57522c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3 57622c8efcdSZachary Turner // Python 3 does not have PyInt_Check. There is only one type of 57722c8efcdSZachary Turner // integral value, long. 57822c8efcdSZachary Turner return PyLong_Check(py_obj); 57922c8efcdSZachary Turner #else 58022c8efcdSZachary Turner return PyLong_Check(py_obj) || PyInt_Check(py_obj); 58122c8efcdSZachary Turner #endif 5822c1f46dcSZachary Turner } 5832c1f46dcSZachary Turner 584f8b22f8fSZachary Turner void 585f8b22f8fSZachary Turner PythonInteger::Reset(PyRefType type, PyObject *py_obj) 58622c8efcdSZachary Turner { 587f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 588f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 589f8b22f8fSZachary Turner PythonObject result(type, py_obj); 590f8b22f8fSZachary Turner 59122c8efcdSZachary Turner if (!PythonInteger::Check(py_obj)) 59222c8efcdSZachary Turner { 593f8b22f8fSZachary Turner PythonObject::Reset(); 594f8b22f8fSZachary Turner return; 59522c8efcdSZachary Turner } 59622c8efcdSZachary Turner 59722c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3 59822c8efcdSZachary Turner // Always store this as a PyLong, which makes interoperability between 59922c8efcdSZachary Turner // Python 2.x and Python 3.x easier. This is only necessary in 2.x, 60022c8efcdSZachary Turner // since 3.x doesn't even have a PyInt. 60122c8efcdSZachary Turner if (PyInt_Check(py_obj)) 60222c8efcdSZachary Turner { 603f8b22f8fSZachary Turner // Since we converted the original object to a different type, the new 604f8b22f8fSZachary Turner // object is an owned object regardless of the ownership semantics requested 605f8b22f8fSZachary Turner // by the user. 606f8b22f8fSZachary Turner result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); 60722c8efcdSZachary Turner } 60822c8efcdSZachary Turner #endif 60922c8efcdSZachary Turner 610f8b22f8fSZachary Turner assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject"); 61122c8efcdSZachary Turner 612f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 613f8b22f8fSZachary Turner // back into the virtual implementation. 614f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 6152c1f46dcSZachary Turner } 6162c1f46dcSZachary Turner 6172c1f46dcSZachary Turner int64_t 6182c1f46dcSZachary Turner PythonInteger::GetInteger() const 6192c1f46dcSZachary Turner { 6202c1f46dcSZachary Turner if (m_py_obj) 6212c1f46dcSZachary Turner { 62222c8efcdSZachary Turner assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); 62322c8efcdSZachary Turner 6242c1f46dcSZachary Turner return PyLong_AsLongLong(m_py_obj); 6252c1f46dcSZachary Turner } 6262c1f46dcSZachary Turner return UINT64_MAX; 6272c1f46dcSZachary Turner } 6282c1f46dcSZachary Turner 6292c1f46dcSZachary Turner void 6302c1f46dcSZachary Turner PythonInteger::SetInteger(int64_t value) 6312c1f46dcSZachary Turner { 632f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); 6332c1f46dcSZachary Turner } 6342c1f46dcSZachary Turner 6352c1f46dcSZachary Turner StructuredData::IntegerSP 6362c1f46dcSZachary Turner PythonInteger::CreateStructuredInteger() const 6372c1f46dcSZachary Turner { 6382c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 6392c1f46dcSZachary Turner result->SetValue(GetInteger()); 6402c1f46dcSZachary Turner return result; 6412c1f46dcSZachary Turner } 6422c1f46dcSZachary Turner 6432c1f46dcSZachary Turner //---------------------------------------------------------------------- 6442c1f46dcSZachary Turner // PythonList 6452c1f46dcSZachary Turner //---------------------------------------------------------------------- 6462c1f46dcSZachary Turner 647f8b22f8fSZachary Turner PythonList::PythonList(PyInitialValue value) 648f8b22f8fSZachary Turner : PythonObject() 6492c1f46dcSZachary Turner { 650f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 651f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyList_New(0)); 6522c1f46dcSZachary Turner } 6532c1f46dcSZachary Turner 65487f47729SZachary Turner PythonList::PythonList(int list_size) 65587f47729SZachary Turner : PythonObject() 65687f47729SZachary Turner { 65787f47729SZachary Turner Reset(PyRefType::Owned, PyList_New(list_size)); 65887f47729SZachary Turner } 65987f47729SZachary Turner 660f8b22f8fSZachary Turner PythonList::PythonList(PyRefType type, PyObject *py_obj) 661f8b22f8fSZachary Turner : PythonObject() 6622c1f46dcSZachary Turner { 663f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list 6642c1f46dcSZachary Turner } 6652c1f46dcSZachary Turner 666f8b22f8fSZachary Turner PythonList::PythonList(const PythonList &list) 667f8b22f8fSZachary Turner : PythonObject(list) 6682c1f46dcSZachary Turner { 6692c1f46dcSZachary Turner } 6702c1f46dcSZachary Turner 6712c1f46dcSZachary Turner PythonList::~PythonList () 6722c1f46dcSZachary Turner { 6732c1f46dcSZachary Turner } 6742c1f46dcSZachary Turner 6752c1f46dcSZachary Turner bool 67622c8efcdSZachary Turner PythonList::Check(PyObject *py_obj) 67722c8efcdSZachary Turner { 67822c8efcdSZachary Turner if (!py_obj) 67922c8efcdSZachary Turner return false; 68022c8efcdSZachary Turner return PyList_Check(py_obj); 68122c8efcdSZachary Turner } 68222c8efcdSZachary Turner 683f8b22f8fSZachary Turner void 684f8b22f8fSZachary Turner PythonList::Reset(PyRefType type, PyObject *py_obj) 6852c1f46dcSZachary Turner { 686f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 687f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 688f8b22f8fSZachary Turner PythonObject result(type, py_obj); 689f8b22f8fSZachary Turner 69022c8efcdSZachary Turner if (!PythonList::Check(py_obj)) 69122c8efcdSZachary Turner { 692f8b22f8fSZachary Turner PythonObject::Reset(); 693f8b22f8fSZachary Turner return; 69422c8efcdSZachary Turner } 69522c8efcdSZachary Turner 696f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 697f8b22f8fSZachary Turner // back into the virtual implementation. 698f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 6992c1f46dcSZachary Turner } 7002c1f46dcSZachary Turner 7012c1f46dcSZachary Turner uint32_t 7022c1f46dcSZachary Turner PythonList::GetSize() const 7032c1f46dcSZachary Turner { 704f8b22f8fSZachary Turner if (IsValid()) 7052c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 7062c1f46dcSZachary Turner return 0; 7072c1f46dcSZachary Turner } 7082c1f46dcSZachary Turner 7092c1f46dcSZachary Turner PythonObject 7102c1f46dcSZachary Turner PythonList::GetItemAtIndex(uint32_t index) const 7112c1f46dcSZachary Turner { 712f8b22f8fSZachary Turner if (IsValid()) 713f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 7142c1f46dcSZachary Turner return PythonObject(); 7152c1f46dcSZachary Turner } 7162c1f46dcSZachary Turner 7172c1f46dcSZachary Turner void 7182c1f46dcSZachary Turner PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) 7192c1f46dcSZachary Turner { 720f8b22f8fSZachary Turner if (IsAllocated() && object.IsValid()) 721f8b22f8fSZachary Turner { 722f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 723f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 724f8b22f8fSZachary Turner Py_INCREF(object.get()); 7252c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 7262c1f46dcSZachary Turner } 727f8b22f8fSZachary Turner } 7282c1f46dcSZachary Turner 7292c1f46dcSZachary Turner void 7302c1f46dcSZachary Turner PythonList::AppendItem(const PythonObject &object) 7312c1f46dcSZachary Turner { 732f8b22f8fSZachary Turner if (IsAllocated() && object.IsValid()) 733f8b22f8fSZachary Turner { 734f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 735f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 7362c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 7372c1f46dcSZachary Turner } 738f8b22f8fSZachary Turner } 7392c1f46dcSZachary Turner 7402c1f46dcSZachary Turner StructuredData::ArraySP 7412c1f46dcSZachary Turner PythonList::CreateStructuredArray() const 7422c1f46dcSZachary Turner { 7432c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 7442c1f46dcSZachary Turner uint32_t count = GetSize(); 7452c1f46dcSZachary Turner for (uint32_t i = 0; i < count; ++i) 7462c1f46dcSZachary Turner { 7472c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 7482c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 7492c1f46dcSZachary Turner } 7502c1f46dcSZachary Turner return result; 7512c1f46dcSZachary Turner } 7522c1f46dcSZachary Turner 7532c1f46dcSZachary Turner //---------------------------------------------------------------------- 754a1405147SZachary Turner // PythonTuple 755a1405147SZachary Turner //---------------------------------------------------------------------- 756a1405147SZachary Turner 757a1405147SZachary Turner PythonTuple::PythonTuple(PyInitialValue value) 758a1405147SZachary Turner : PythonObject() 759a1405147SZachary Turner { 760a1405147SZachary Turner if (value == PyInitialValue::Empty) 761a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(0)); 762a1405147SZachary Turner } 763a1405147SZachary Turner 764a1405147SZachary Turner PythonTuple::PythonTuple(int tuple_size) 765a1405147SZachary Turner : PythonObject() 766a1405147SZachary Turner { 767a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(tuple_size)); 768a1405147SZachary Turner } 769a1405147SZachary Turner 770a1405147SZachary Turner PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) 771a1405147SZachary Turner : PythonObject() 772a1405147SZachary Turner { 773a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple 774a1405147SZachary Turner } 775a1405147SZachary Turner 776a1405147SZachary Turner PythonTuple::PythonTuple(const PythonTuple &tuple) 777a1405147SZachary Turner : PythonObject(tuple) 778a1405147SZachary Turner { 779a1405147SZachary Turner } 780a1405147SZachary Turner 781a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) 782a1405147SZachary Turner { 783a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 784a1405147SZachary Turner 785a1405147SZachary Turner uint32_t idx = 0; 786a1405147SZachary Turner for (auto object : objects) 787a1405147SZachary Turner { 788a1405147SZachary Turner if (object.IsValid()) 789a1405147SZachary Turner SetItemAtIndex(idx, object); 790a1405147SZachary Turner idx++; 791a1405147SZachary Turner } 792a1405147SZachary Turner } 793a1405147SZachary Turner 794a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PyObject*> objects) 795a1405147SZachary Turner { 796a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 797a1405147SZachary Turner 798a1405147SZachary Turner uint32_t idx = 0; 799a1405147SZachary Turner for (auto py_object : objects) 800a1405147SZachary Turner { 801a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object); 802a1405147SZachary Turner if (object.IsValid()) 803a1405147SZachary Turner SetItemAtIndex(idx, object); 804a1405147SZachary Turner idx++; 805a1405147SZachary Turner } 806a1405147SZachary Turner } 807a1405147SZachary Turner 808a1405147SZachary Turner PythonTuple::~PythonTuple() 809a1405147SZachary Turner { 810a1405147SZachary Turner } 811a1405147SZachary Turner 812a1405147SZachary Turner bool 813a1405147SZachary Turner PythonTuple::Check(PyObject *py_obj) 814a1405147SZachary Turner { 815a1405147SZachary Turner if (!py_obj) 816a1405147SZachary Turner return false; 817a1405147SZachary Turner return PyTuple_Check(py_obj); 818a1405147SZachary Turner } 819a1405147SZachary Turner 820a1405147SZachary Turner void 821a1405147SZachary Turner PythonTuple::Reset(PyRefType type, PyObject *py_obj) 822a1405147SZachary Turner { 823a1405147SZachary Turner // Grab the desired reference type so that if we end up rejecting 824a1405147SZachary Turner // `py_obj` it still gets decremented if necessary. 825a1405147SZachary Turner PythonObject result(type, py_obj); 826a1405147SZachary Turner 827a1405147SZachary Turner if (!PythonTuple::Check(py_obj)) 828a1405147SZachary Turner { 829a1405147SZachary Turner PythonObject::Reset(); 830a1405147SZachary Turner return; 831a1405147SZachary Turner } 832a1405147SZachary Turner 833a1405147SZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 834a1405147SZachary Turner // back into the virtual implementation. 835a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 836a1405147SZachary Turner } 837a1405147SZachary Turner 838a1405147SZachary Turner uint32_t 839a1405147SZachary Turner PythonTuple::GetSize() const 840a1405147SZachary Turner { 841a1405147SZachary Turner if (IsValid()) 842a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj); 843a1405147SZachary Turner return 0; 844a1405147SZachary Turner } 845a1405147SZachary Turner 846a1405147SZachary Turner PythonObject 847a1405147SZachary Turner PythonTuple::GetItemAtIndex(uint32_t index) const 848a1405147SZachary Turner { 849a1405147SZachary Turner if (IsValid()) 850a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 851a1405147SZachary Turner return PythonObject(); 852a1405147SZachary Turner } 853a1405147SZachary Turner 854a1405147SZachary Turner void 855a1405147SZachary Turner PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) 856a1405147SZachary Turner { 857a1405147SZachary Turner if (IsAllocated() && object.IsValid()) 858a1405147SZachary Turner { 859a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to 860a1405147SZachary Turner // convert it to an owned reference by incrementing it. 861a1405147SZachary Turner Py_INCREF(object.get()); 862a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get()); 863a1405147SZachary Turner } 864a1405147SZachary Turner } 865a1405147SZachary Turner 866a1405147SZachary Turner StructuredData::ArraySP 867a1405147SZachary Turner PythonTuple::CreateStructuredArray() const 868a1405147SZachary Turner { 869a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 870a1405147SZachary Turner uint32_t count = GetSize(); 871a1405147SZachary Turner for (uint32_t i = 0; i < count; ++i) 872a1405147SZachary Turner { 873a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i); 874a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject()); 875a1405147SZachary Turner } 876a1405147SZachary Turner return result; 877a1405147SZachary Turner } 878a1405147SZachary Turner 879a1405147SZachary Turner //---------------------------------------------------------------------- 8802c1f46dcSZachary Turner // PythonDictionary 8812c1f46dcSZachary Turner //---------------------------------------------------------------------- 8822c1f46dcSZachary Turner 883f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyInitialValue value) 884f8b22f8fSZachary Turner : PythonObject() 8852c1f46dcSZachary Turner { 886f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 887f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyDict_New()); 8882c1f46dcSZachary Turner } 8892c1f46dcSZachary Turner 890f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) 891f8b22f8fSZachary Turner : PythonObject() 8922c1f46dcSZachary Turner { 893f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary 8942c1f46dcSZachary Turner } 8952c1f46dcSZachary Turner 896f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object) 897f8b22f8fSZachary Turner : PythonObject(object) 8982c1f46dcSZachary Turner { 8992c1f46dcSZachary Turner } 9002c1f46dcSZachary Turner 9012c1f46dcSZachary Turner PythonDictionary::~PythonDictionary () 9022c1f46dcSZachary Turner { 9032c1f46dcSZachary Turner } 9042c1f46dcSZachary Turner 9052c1f46dcSZachary Turner bool 90622c8efcdSZachary Turner PythonDictionary::Check(PyObject *py_obj) 90722c8efcdSZachary Turner { 90822c8efcdSZachary Turner if (!py_obj) 90922c8efcdSZachary Turner return false; 91022c8efcdSZachary Turner 91122c8efcdSZachary Turner return PyDict_Check(py_obj); 91222c8efcdSZachary Turner } 91322c8efcdSZachary Turner 914f8b22f8fSZachary Turner void 915f8b22f8fSZachary Turner PythonDictionary::Reset(PyRefType type, PyObject *py_obj) 9162c1f46dcSZachary Turner { 917f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 918f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 919f8b22f8fSZachary Turner PythonObject result(type, py_obj); 920f8b22f8fSZachary Turner 92122c8efcdSZachary Turner if (!PythonDictionary::Check(py_obj)) 92222c8efcdSZachary Turner { 923f8b22f8fSZachary Turner PythonObject::Reset(); 924f8b22f8fSZachary Turner return; 92522c8efcdSZachary Turner } 92622c8efcdSZachary Turner 927f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 928f8b22f8fSZachary Turner // back into the virtual implementation. 929f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 9302c1f46dcSZachary Turner } 9312c1f46dcSZachary Turner 9322c1f46dcSZachary Turner uint32_t 9332c1f46dcSZachary Turner PythonDictionary::GetSize() const 9342c1f46dcSZachary Turner { 935f8b22f8fSZachary Turner if (IsValid()) 9362c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 9372c1f46dcSZachary Turner return 0; 9382c1f46dcSZachary Turner } 9392c1f46dcSZachary Turner 9402c1f46dcSZachary Turner PythonList 9412c1f46dcSZachary Turner PythonDictionary::GetKeys() const 9422c1f46dcSZachary Turner { 943f8b22f8fSZachary Turner if (IsValid()) 944f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 945f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 9462c1f46dcSZachary Turner } 9472c1f46dcSZachary Turner 9482c1f46dcSZachary Turner PythonObject 949f8b22f8fSZachary Turner PythonDictionary::GetItemForKey(const PythonObject &key) const 9502c1f46dcSZachary Turner { 951f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid()) 952f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get())); 9532c1f46dcSZachary Turner return PythonObject(); 9542c1f46dcSZachary Turner } 9552c1f46dcSZachary Turner 9562c1f46dcSZachary Turner void 957f8b22f8fSZachary Turner PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value) 9582c1f46dcSZachary Turner { 959f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid() && value.IsValid()) 9602c1f46dcSZachary Turner PyDict_SetItem(m_py_obj, key.get(), value.get()); 9612c1f46dcSZachary Turner } 9622c1f46dcSZachary Turner 9632c1f46dcSZachary Turner StructuredData::DictionarySP 9642c1f46dcSZachary Turner PythonDictionary::CreateStructuredDictionary() const 9652c1f46dcSZachary Turner { 9662c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 9672c1f46dcSZachary Turner PythonList keys(GetKeys()); 9682c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 9692c1f46dcSZachary Turner for (uint32_t i = 0; i < num_keys; ++i) 9702c1f46dcSZachary Turner { 9712c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 9722c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 9732c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 974f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 9752c1f46dcSZachary Turner } 9762c1f46dcSZachary Turner return result; 9772c1f46dcSZachary Turner } 9782c1f46dcSZachary Turner 9797841efbbSZachary Turner PythonModule::PythonModule() : PythonObject() 9807841efbbSZachary Turner { 9817841efbbSZachary Turner } 9827841efbbSZachary Turner 9837841efbbSZachary Turner PythonModule::PythonModule(PyRefType type, PyObject *py_obj) 9847841efbbSZachary Turner { 9857841efbbSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module 9867841efbbSZachary Turner } 9877841efbbSZachary Turner 9887841efbbSZachary Turner PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict) 9897841efbbSZachary Turner { 9907841efbbSZachary Turner } 9917841efbbSZachary Turner 9927841efbbSZachary Turner PythonModule::~PythonModule() 9937841efbbSZachary Turner { 9947841efbbSZachary Turner } 9957841efbbSZachary Turner 9967841efbbSZachary Turner PythonModule 997a1405147SZachary Turner PythonModule::BuiltinsModule() 998a1405147SZachary Turner { 999a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3 1000a1405147SZachary Turner return AddModule("builtins"); 1001a1405147SZachary Turner #else 1002a1405147SZachary Turner return AddModule("__builtin__"); 1003a1405147SZachary Turner #endif 1004a1405147SZachary Turner } 1005a1405147SZachary Turner 1006a1405147SZachary Turner PythonModule 10077841efbbSZachary Turner PythonModule::MainModule() 10087841efbbSZachary Turner { 1009a1405147SZachary Turner return AddModule("__main__"); 1010a1405147SZachary Turner } 1011a1405147SZachary Turner 1012a1405147SZachary Turner PythonModule 1013a1405147SZachary Turner PythonModule::AddModule(llvm::StringRef module) 1014a1405147SZachary Turner { 1015a1405147SZachary Turner std::string str = module.str(); 1016a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 10177841efbbSZachary Turner } 10187841efbbSZachary Turner 10192419f1d5SZachary Turner 10202419f1d5SZachary Turner PythonModule 10212419f1d5SZachary Turner PythonModule::ImportModule(llvm::StringRef module) 10222419f1d5SZachary Turner { 10232419f1d5SZachary Turner std::string str = module.str(); 10242419f1d5SZachary Turner return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str())); 10252419f1d5SZachary Turner } 10262419f1d5SZachary Turner 10277841efbbSZachary Turner bool 10287841efbbSZachary Turner PythonModule::Check(PyObject *py_obj) 10297841efbbSZachary Turner { 10307841efbbSZachary Turner if (!py_obj) 10317841efbbSZachary Turner return false; 10327841efbbSZachary Turner 10337841efbbSZachary Turner return PyModule_Check(py_obj); 10347841efbbSZachary Turner } 10357841efbbSZachary Turner 10367841efbbSZachary Turner void 10377841efbbSZachary Turner PythonModule::Reset(PyRefType type, PyObject *py_obj) 10387841efbbSZachary Turner { 10397841efbbSZachary Turner // Grab the desired reference type so that if we end up rejecting 10407841efbbSZachary Turner // `py_obj` it still gets decremented if necessary. 10417841efbbSZachary Turner PythonObject result(type, py_obj); 10427841efbbSZachary Turner 10437841efbbSZachary Turner if (!PythonModule::Check(py_obj)) 10447841efbbSZachary Turner { 10457841efbbSZachary Turner PythonObject::Reset(); 10467841efbbSZachary Turner return; 10477841efbbSZachary Turner } 10487841efbbSZachary Turner 10497841efbbSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 10507841efbbSZachary Turner // back into the virtual implementation. 10517841efbbSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 10527841efbbSZachary Turner } 10537841efbbSZachary Turner 10547841efbbSZachary Turner PythonDictionary 10557841efbbSZachary Turner PythonModule::GetDictionary() const 10567841efbbSZachary Turner { 10577841efbbSZachary Turner return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); 10587841efbbSZachary Turner } 10597841efbbSZachary Turner 1060a1405147SZachary Turner PythonCallable::PythonCallable() : PythonObject() 1061a1405147SZachary Turner { 1062a1405147SZachary Turner } 1063a1405147SZachary Turner 1064a1405147SZachary Turner PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) 1065a1405147SZachary Turner { 1066a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable 1067a1405147SZachary Turner } 1068a1405147SZachary Turner 1069a1405147SZachary Turner PythonCallable::PythonCallable(const PythonCallable &callable) 1070a1405147SZachary Turner : PythonObject(callable) 1071a1405147SZachary Turner { 1072a1405147SZachary Turner } 1073a1405147SZachary Turner 1074a1405147SZachary Turner PythonCallable::~PythonCallable() 1075a1405147SZachary Turner { 1076a1405147SZachary Turner } 1077a1405147SZachary Turner 1078a1405147SZachary Turner bool 1079a1405147SZachary Turner PythonCallable::Check(PyObject *py_obj) 1080a1405147SZachary Turner { 1081a1405147SZachary Turner if (!py_obj) 1082a1405147SZachary Turner return false; 1083a1405147SZachary Turner 1084a1405147SZachary Turner return PyCallable_Check(py_obj); 1085a1405147SZachary Turner } 1086a1405147SZachary Turner 1087a1405147SZachary Turner void 1088a1405147SZachary Turner PythonCallable::Reset(PyRefType type, PyObject *py_obj) 1089a1405147SZachary Turner { 1090a1405147SZachary Turner // Grab the desired reference type so that if we end up rejecting 1091a1405147SZachary Turner // `py_obj` it still gets decremented if necessary. 1092a1405147SZachary Turner PythonObject result(type, py_obj); 1093a1405147SZachary Turner 1094a1405147SZachary Turner if (!PythonCallable::Check(py_obj)) 1095a1405147SZachary Turner { 1096a1405147SZachary Turner PythonObject::Reset(); 1097a1405147SZachary Turner return; 1098a1405147SZachary Turner } 1099a1405147SZachary Turner 1100a1405147SZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 1101a1405147SZachary Turner // back into the virtual implementation. 1102a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 1103a1405147SZachary Turner } 1104a1405147SZachary Turner 1105a1405147SZachary Turner 1106b58fb2f4SZachary Turner PythonCallable::ArgInfo 1107b58fb2f4SZachary Turner PythonCallable::GetNumArguments() const 1108a1405147SZachary Turner { 1109b58fb2f4SZachary Turner ArgInfo result = { 0, false, false }; 1110a1405147SZachary Turner if (!IsValid()) 1111b58fb2f4SZachary Turner return result; 1112a1405147SZachary Turner 1113a1405147SZachary Turner PyObject *py_func_obj = m_py_obj; 1114a1405147SZachary Turner if (PyMethod_Check(py_func_obj)) 1115a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 1116a1405147SZachary Turner 1117a1405147SZachary Turner if (!py_func_obj) 1118b58fb2f4SZachary Turner return result; 1119a1405147SZachary Turner 1120a1405147SZachary Turner PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj); 1121a1405147SZachary Turner if (!code) 1122b58fb2f4SZachary Turner return result; 1123a1405147SZachary Turner 1124b58fb2f4SZachary Turner result.count = code->co_argcount; 1125b58fb2f4SZachary Turner result.has_varargs = !!(code->co_flags & CO_VARARGS); 1126b58fb2f4SZachary Turner result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); 1127b58fb2f4SZachary Turner return result; 1128b58fb2f4SZachary Turner } 1129b58fb2f4SZachary Turner 1130b58fb2f4SZachary Turner PythonObject 1131b58fb2f4SZachary Turner PythonCallable::operator ()() 1132b58fb2f4SZachary Turner { 1133b58fb2f4SZachary Turner return PythonObject(PyRefType::Owned, 1134b58fb2f4SZachary Turner PyObject_CallObject(m_py_obj, nullptr)); 1135a1405147SZachary Turner } 1136a1405147SZachary Turner 1137a1405147SZachary Turner PythonObject 1138a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PyObject*> args) 1139a1405147SZachary Turner { 1140a1405147SZachary Turner PythonTuple arg_tuple(args); 1141a1405147SZachary Turner return PythonObject(PyRefType::Owned, 1142a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 1143a1405147SZachary Turner } 1144a1405147SZachary Turner 1145a1405147SZachary Turner PythonObject 1146a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PythonObject> args) 1147a1405147SZachary Turner { 1148a1405147SZachary Turner PythonTuple arg_tuple(args); 1149a1405147SZachary Turner return PythonObject(PyRefType::Owned, 1150a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 1151a1405147SZachary Turner } 1152a1405147SZachary Turner 115332064024SZachary Turner PythonFile::PythonFile() 115432064024SZachary Turner : PythonObject() 115532064024SZachary Turner { 115632064024SZachary Turner } 115732064024SZachary Turner 11589c40264fSZachary Turner PythonFile::PythonFile(File &file, const char *mode) 11599c40264fSZachary Turner { 11609c40264fSZachary Turner Reset(file, mode); 11619c40264fSZachary Turner } 11629c40264fSZachary Turner 1163eda01c31SZachary Turner PythonFile::PythonFile(const char *path, const char *mode) 1164eda01c31SZachary Turner { 1165eda01c31SZachary Turner FILE *fp = nullptr; 1166eda01c31SZachary Turner fp = fopen(path, mode); 1167eda01c31SZachary Turner lldb_private::File file(fp, true); 1168eda01c31SZachary Turner Reset(file, mode); 1169eda01c31SZachary Turner } 1170eda01c31SZachary Turner 11719c40264fSZachary Turner PythonFile::PythonFile(PyRefType type, PyObject *o) 11729c40264fSZachary Turner { 11739c40264fSZachary Turner Reset(type, o); 11749c40264fSZachary Turner } 11759c40264fSZachary Turner 11769c40264fSZachary Turner PythonFile::~PythonFile() 11779c40264fSZachary Turner { 11789c40264fSZachary Turner } 11799c40264fSZachary Turner 11809c40264fSZachary Turner bool 11819c40264fSZachary Turner PythonFile::Check(PyObject *py_obj) 11829c40264fSZachary Turner { 11839c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 11849c40264fSZachary Turner return PyFile_Check(py_obj); 11859c40264fSZachary Turner #else 11869c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 11879c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 11889c40264fSZachary Turner // over `io.open()`, which returns some object derived from `io.IOBase`. 11899c40264fSZachary Turner // As a result, the only way to detect a file in Python 3 is to check whether 11909c40264fSZachary Turner // it inherits from `io.IOBase`. Since it is possible for non-files to also 11919c40264fSZachary Turner // inherit from `io.IOBase`, we additionally verify that it has the `fileno` 11929c40264fSZachary Turner // attribute, which should guarantee that it is backed by the file system. 11939c40264fSZachary Turner PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); 11949c40264fSZachary Turner PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get())); 11959c40264fSZachary Turner PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); 11969c40264fSZachary Turner 11979c40264fSZachary Turner PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); 11989c40264fSZachary Turner 11999c40264fSZachary Turner if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) 12009c40264fSZachary Turner return false; 12019c40264fSZachary Turner if (!object_type.HasAttribute("fileno")) 12029c40264fSZachary Turner return false; 12039c40264fSZachary Turner 12049c40264fSZachary Turner return true; 12059c40264fSZachary Turner #endif 12069c40264fSZachary Turner } 12079c40264fSZachary Turner 12089c40264fSZachary Turner void 12099c40264fSZachary Turner PythonFile::Reset(PyRefType type, PyObject *py_obj) 12109c40264fSZachary Turner { 12119c40264fSZachary Turner // Grab the desired reference type so that if we end up rejecting 12129c40264fSZachary Turner // `py_obj` it still gets decremented if necessary. 12139c40264fSZachary Turner PythonObject result(type, py_obj); 12149c40264fSZachary Turner 12159c40264fSZachary Turner if (!PythonFile::Check(py_obj)) 12169c40264fSZachary Turner { 12179c40264fSZachary Turner PythonObject::Reset(); 12189c40264fSZachary Turner return; 12199c40264fSZachary Turner } 12209c40264fSZachary Turner 12219c40264fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack 12229c40264fSZachary Turner // overflow since it calls back into the virtual implementation. 12239c40264fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 12249c40264fSZachary Turner } 12259c40264fSZachary Turner 12269c40264fSZachary Turner void 12279c40264fSZachary Turner PythonFile::Reset(File &file, const char *mode) 12289c40264fSZachary Turner { 122932ac147bSZachary Turner if (!file.IsValid()) 123032ac147bSZachary Turner { 123132ac147bSZachary Turner Reset(); 123232ac147bSZachary Turner return; 123332ac147bSZachary Turner } 123432ac147bSZachary Turner 12359c40264fSZachary Turner char *cmode = const_cast<char *>(mode); 12369c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3 12379c40264fSZachary Turner Reset(PyRefType::Owned, 12389c40264fSZachary Turner PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0)); 12399c40264fSZachary Turner #else 12409c40264fSZachary Turner // Read through the Python source, doesn't seem to modify these strings 12419c40264fSZachary Turner Reset(PyRefType::Owned, 12429c40264fSZachary Turner PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr)); 12439c40264fSZachary Turner #endif 12449c40264fSZachary Turner } 12459c40264fSZachary Turner 1246744959b9SEnrico Granata uint32_t 1247744959b9SEnrico Granata PythonFile::GetOptionsFromMode(llvm::StringRef mode) 1248744959b9SEnrico Granata { 1249744959b9SEnrico Granata if (mode.empty()) 1250744959b9SEnrico Granata return 0; 1251744959b9SEnrico Granata 1252744959b9SEnrico Granata return llvm::StringSwitch<uint32_t>(mode.str().c_str()) 1253744959b9SEnrico Granata .Case("r", File::eOpenOptionRead) 1254744959b9SEnrico Granata .Case("w", File::eOpenOptionWrite) 1255744959b9SEnrico Granata .Case("a", File::eOpenOptionAppend|File::eOpenOptionCanCreate) 1256744959b9SEnrico Granata .Case("r+", File::eOpenOptionRead|File::eOpenOptionWrite) 1257744959b9SEnrico Granata .Case("w+", File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionCanCreate|File::eOpenOptionTruncate) 1258744959b9SEnrico Granata .Case("a+", File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionCanCreate) 1259744959b9SEnrico Granata .Default(0); 1260744959b9SEnrico Granata } 1261744959b9SEnrico Granata 1262eda01c31SZachary Turner bool 1263eda01c31SZachary Turner PythonFile::GetUnderlyingFile(File &file) const 1264eda01c31SZachary Turner { 1265eda01c31SZachary Turner if (!IsValid()) 1266eda01c31SZachary Turner return false; 1267eda01c31SZachary Turner 1268eda01c31SZachary Turner file.Close(); 1269eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 1270eda01c31SZachary Turner // File object knows about that. 1271eda01c31SZachary Turner file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); 1272744959b9SEnrico Granata PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); 1273744959b9SEnrico Granata file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString())); 1274eda01c31SZachary Turner return file.IsValid(); 1275eda01c31SZachary Turner } 1276eda01c31SZachary Turner 1277eda01c31SZachary Turner 12782c1f46dcSZachary Turner #endif 1279