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" 22190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 232c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h" 242c1f46dcSZachary Turner 25190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h" 26190fadcdSZachary 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 35d9c9da53SJason Molenda StructuredPythonObject::Dump(Stream &s, bool pretty_print) 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 627*008ec446SGreg Clayton int overflow = 0; 628*008ec446SGreg Clayton int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow); 629*008ec446SGreg Clayton if (overflow != 0) 630*008ec446SGreg Clayton { 631*008ec446SGreg Clayton // We got an integer that overflows, like 18446744072853913392L 632*008ec446SGreg Clayton // we can't use PyLong_AsLongLong() as it will return 633*008ec446SGreg Clayton // 0xffffffffffffffff. If we use the unsigned long long 634*008ec446SGreg Clayton // it will work as expected. 635*008ec446SGreg Clayton const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj); 636*008ec446SGreg Clayton result = *((int64_t *)&uval); 637*008ec446SGreg Clayton } 638*008ec446SGreg Clayton return result; 6392c1f46dcSZachary Turner } 6402c1f46dcSZachary Turner return UINT64_MAX; 6412c1f46dcSZachary Turner } 6422c1f46dcSZachary Turner 6432c1f46dcSZachary Turner void 6442c1f46dcSZachary Turner PythonInteger::SetInteger(int64_t value) 6452c1f46dcSZachary Turner { 646f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); 6472c1f46dcSZachary Turner } 6482c1f46dcSZachary Turner 6492c1f46dcSZachary Turner StructuredData::IntegerSP 6502c1f46dcSZachary Turner PythonInteger::CreateStructuredInteger() const 6512c1f46dcSZachary Turner { 6522c1f46dcSZachary Turner StructuredData::IntegerSP result(new StructuredData::Integer); 6532c1f46dcSZachary Turner result->SetValue(GetInteger()); 6542c1f46dcSZachary Turner return result; 6552c1f46dcSZachary Turner } 6562c1f46dcSZachary Turner 6572c1f46dcSZachary Turner //---------------------------------------------------------------------- 6582c1f46dcSZachary Turner // PythonList 6592c1f46dcSZachary Turner //---------------------------------------------------------------------- 6602c1f46dcSZachary Turner 661f8b22f8fSZachary Turner PythonList::PythonList(PyInitialValue value) 662f8b22f8fSZachary Turner : PythonObject() 6632c1f46dcSZachary Turner { 664f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 665f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyList_New(0)); 6662c1f46dcSZachary Turner } 6672c1f46dcSZachary Turner 66887f47729SZachary Turner PythonList::PythonList(int list_size) 66987f47729SZachary Turner : PythonObject() 67087f47729SZachary Turner { 67187f47729SZachary Turner Reset(PyRefType::Owned, PyList_New(list_size)); 67287f47729SZachary Turner } 67387f47729SZachary Turner 674f8b22f8fSZachary Turner PythonList::PythonList(PyRefType type, PyObject *py_obj) 675f8b22f8fSZachary Turner : PythonObject() 6762c1f46dcSZachary Turner { 677f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list 6782c1f46dcSZachary Turner } 6792c1f46dcSZachary Turner 680f8b22f8fSZachary Turner PythonList::PythonList(const PythonList &list) 681f8b22f8fSZachary Turner : PythonObject(list) 6822c1f46dcSZachary Turner { 6832c1f46dcSZachary Turner } 6842c1f46dcSZachary Turner 6852c1f46dcSZachary Turner PythonList::~PythonList () 6862c1f46dcSZachary Turner { 6872c1f46dcSZachary Turner } 6882c1f46dcSZachary Turner 6892c1f46dcSZachary Turner bool 69022c8efcdSZachary Turner PythonList::Check(PyObject *py_obj) 69122c8efcdSZachary Turner { 69222c8efcdSZachary Turner if (!py_obj) 69322c8efcdSZachary Turner return false; 69422c8efcdSZachary Turner return PyList_Check(py_obj); 69522c8efcdSZachary Turner } 69622c8efcdSZachary Turner 697f8b22f8fSZachary Turner void 698f8b22f8fSZachary Turner PythonList::Reset(PyRefType type, PyObject *py_obj) 6992c1f46dcSZachary Turner { 700f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 701f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 702f8b22f8fSZachary Turner PythonObject result(type, py_obj); 703f8b22f8fSZachary Turner 70422c8efcdSZachary Turner if (!PythonList::Check(py_obj)) 70522c8efcdSZachary Turner { 706f8b22f8fSZachary Turner PythonObject::Reset(); 707f8b22f8fSZachary Turner return; 70822c8efcdSZachary Turner } 70922c8efcdSZachary Turner 710f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 711f8b22f8fSZachary Turner // back into the virtual implementation. 712f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 7132c1f46dcSZachary Turner } 7142c1f46dcSZachary Turner 7152c1f46dcSZachary Turner uint32_t 7162c1f46dcSZachary Turner PythonList::GetSize() const 7172c1f46dcSZachary Turner { 718f8b22f8fSZachary Turner if (IsValid()) 7192c1f46dcSZachary Turner return PyList_GET_SIZE(m_py_obj); 7202c1f46dcSZachary Turner return 0; 7212c1f46dcSZachary Turner } 7222c1f46dcSZachary Turner 7232c1f46dcSZachary Turner PythonObject 7242c1f46dcSZachary Turner PythonList::GetItemAtIndex(uint32_t index) const 7252c1f46dcSZachary Turner { 726f8b22f8fSZachary Turner if (IsValid()) 727f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); 7282c1f46dcSZachary Turner return PythonObject(); 7292c1f46dcSZachary Turner } 7302c1f46dcSZachary Turner 7312c1f46dcSZachary Turner void 7322c1f46dcSZachary Turner PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) 7332c1f46dcSZachary Turner { 734f8b22f8fSZachary Turner if (IsAllocated() && object.IsValid()) 735f8b22f8fSZachary Turner { 736f8b22f8fSZachary Turner // PyList_SetItem is documented to "steal" a reference, so we need to 737f8b22f8fSZachary Turner // convert it to an owned reference by incrementing it. 738f8b22f8fSZachary Turner Py_INCREF(object.get()); 7392c1f46dcSZachary Turner PyList_SetItem(m_py_obj, index, object.get()); 7402c1f46dcSZachary Turner } 741f8b22f8fSZachary Turner } 7422c1f46dcSZachary Turner 7432c1f46dcSZachary Turner void 7442c1f46dcSZachary Turner PythonList::AppendItem(const PythonObject &object) 7452c1f46dcSZachary Turner { 746f8b22f8fSZachary Turner if (IsAllocated() && object.IsValid()) 747f8b22f8fSZachary Turner { 748f8b22f8fSZachary Turner // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` 749f8b22f8fSZachary Turner // here like we do with `PyList_SetItem`. 7502c1f46dcSZachary Turner PyList_Append(m_py_obj, object.get()); 7512c1f46dcSZachary Turner } 752f8b22f8fSZachary Turner } 7532c1f46dcSZachary Turner 7542c1f46dcSZachary Turner StructuredData::ArraySP 7552c1f46dcSZachary Turner PythonList::CreateStructuredArray() const 7562c1f46dcSZachary Turner { 7572c1f46dcSZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 7582c1f46dcSZachary Turner uint32_t count = GetSize(); 7592c1f46dcSZachary Turner for (uint32_t i = 0; i < count; ++i) 7602c1f46dcSZachary Turner { 7612c1f46dcSZachary Turner PythonObject obj = GetItemAtIndex(i); 7622c1f46dcSZachary Turner result->AddItem(obj.CreateStructuredObject()); 7632c1f46dcSZachary Turner } 7642c1f46dcSZachary Turner return result; 7652c1f46dcSZachary Turner } 7662c1f46dcSZachary Turner 7672c1f46dcSZachary Turner //---------------------------------------------------------------------- 768a1405147SZachary Turner // PythonTuple 769a1405147SZachary Turner //---------------------------------------------------------------------- 770a1405147SZachary Turner 771a1405147SZachary Turner PythonTuple::PythonTuple(PyInitialValue value) 772a1405147SZachary Turner : PythonObject() 773a1405147SZachary Turner { 774a1405147SZachary Turner if (value == PyInitialValue::Empty) 775a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(0)); 776a1405147SZachary Turner } 777a1405147SZachary Turner 778a1405147SZachary Turner PythonTuple::PythonTuple(int tuple_size) 779a1405147SZachary Turner : PythonObject() 780a1405147SZachary Turner { 781a1405147SZachary Turner Reset(PyRefType::Owned, PyTuple_New(tuple_size)); 782a1405147SZachary Turner } 783a1405147SZachary Turner 784a1405147SZachary Turner PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) 785a1405147SZachary Turner : PythonObject() 786a1405147SZachary Turner { 787a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple 788a1405147SZachary Turner } 789a1405147SZachary Turner 790a1405147SZachary Turner PythonTuple::PythonTuple(const PythonTuple &tuple) 791a1405147SZachary Turner : PythonObject(tuple) 792a1405147SZachary Turner { 793a1405147SZachary Turner } 794a1405147SZachary Turner 795a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) 796a1405147SZachary Turner { 797a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 798a1405147SZachary Turner 799a1405147SZachary Turner uint32_t idx = 0; 800a1405147SZachary Turner for (auto object : objects) 801a1405147SZachary Turner { 802a1405147SZachary Turner if (object.IsValid()) 803a1405147SZachary Turner SetItemAtIndex(idx, object); 804a1405147SZachary Turner idx++; 805a1405147SZachary Turner } 806a1405147SZachary Turner } 807a1405147SZachary Turner 808a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PyObject*> objects) 809a1405147SZachary Turner { 810a1405147SZachary Turner m_py_obj = PyTuple_New(objects.size()); 811a1405147SZachary Turner 812a1405147SZachary Turner uint32_t idx = 0; 813a1405147SZachary Turner for (auto py_object : objects) 814a1405147SZachary Turner { 815a1405147SZachary Turner PythonObject object(PyRefType::Borrowed, py_object); 816a1405147SZachary Turner if (object.IsValid()) 817a1405147SZachary Turner SetItemAtIndex(idx, object); 818a1405147SZachary Turner idx++; 819a1405147SZachary Turner } 820a1405147SZachary Turner } 821a1405147SZachary Turner 822a1405147SZachary Turner PythonTuple::~PythonTuple() 823a1405147SZachary Turner { 824a1405147SZachary Turner } 825a1405147SZachary Turner 826a1405147SZachary Turner bool 827a1405147SZachary Turner PythonTuple::Check(PyObject *py_obj) 828a1405147SZachary Turner { 829a1405147SZachary Turner if (!py_obj) 830a1405147SZachary Turner return false; 831a1405147SZachary Turner return PyTuple_Check(py_obj); 832a1405147SZachary Turner } 833a1405147SZachary Turner 834a1405147SZachary Turner void 835a1405147SZachary Turner PythonTuple::Reset(PyRefType type, PyObject *py_obj) 836a1405147SZachary Turner { 837a1405147SZachary Turner // Grab the desired reference type so that if we end up rejecting 838a1405147SZachary Turner // `py_obj` it still gets decremented if necessary. 839a1405147SZachary Turner PythonObject result(type, py_obj); 840a1405147SZachary Turner 841a1405147SZachary Turner if (!PythonTuple::Check(py_obj)) 842a1405147SZachary Turner { 843a1405147SZachary Turner PythonObject::Reset(); 844a1405147SZachary Turner return; 845a1405147SZachary Turner } 846a1405147SZachary Turner 847a1405147SZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 848a1405147SZachary Turner // back into the virtual implementation. 849a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 850a1405147SZachary Turner } 851a1405147SZachary Turner 852a1405147SZachary Turner uint32_t 853a1405147SZachary Turner PythonTuple::GetSize() const 854a1405147SZachary Turner { 855a1405147SZachary Turner if (IsValid()) 856a1405147SZachary Turner return PyTuple_GET_SIZE(m_py_obj); 857a1405147SZachary Turner return 0; 858a1405147SZachary Turner } 859a1405147SZachary Turner 860a1405147SZachary Turner PythonObject 861a1405147SZachary Turner PythonTuple::GetItemAtIndex(uint32_t index) const 862a1405147SZachary Turner { 863a1405147SZachary Turner if (IsValid()) 864a1405147SZachary Turner return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); 865a1405147SZachary Turner return PythonObject(); 866a1405147SZachary Turner } 867a1405147SZachary Turner 868a1405147SZachary Turner void 869a1405147SZachary Turner PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) 870a1405147SZachary Turner { 871a1405147SZachary Turner if (IsAllocated() && object.IsValid()) 872a1405147SZachary Turner { 873a1405147SZachary Turner // PyTuple_SetItem is documented to "steal" a reference, so we need to 874a1405147SZachary Turner // convert it to an owned reference by incrementing it. 875a1405147SZachary Turner Py_INCREF(object.get()); 876a1405147SZachary Turner PyTuple_SetItem(m_py_obj, index, object.get()); 877a1405147SZachary Turner } 878a1405147SZachary Turner } 879a1405147SZachary Turner 880a1405147SZachary Turner StructuredData::ArraySP 881a1405147SZachary Turner PythonTuple::CreateStructuredArray() const 882a1405147SZachary Turner { 883a1405147SZachary Turner StructuredData::ArraySP result(new StructuredData::Array); 884a1405147SZachary Turner uint32_t count = GetSize(); 885a1405147SZachary Turner for (uint32_t i = 0; i < count; ++i) 886a1405147SZachary Turner { 887a1405147SZachary Turner PythonObject obj = GetItemAtIndex(i); 888a1405147SZachary Turner result->AddItem(obj.CreateStructuredObject()); 889a1405147SZachary Turner } 890a1405147SZachary Turner return result; 891a1405147SZachary Turner } 892a1405147SZachary Turner 893a1405147SZachary Turner //---------------------------------------------------------------------- 8942c1f46dcSZachary Turner // PythonDictionary 8952c1f46dcSZachary Turner //---------------------------------------------------------------------- 8962c1f46dcSZachary Turner 897f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyInitialValue value) 898f8b22f8fSZachary Turner : PythonObject() 8992c1f46dcSZachary Turner { 900f8b22f8fSZachary Turner if (value == PyInitialValue::Empty) 901f8b22f8fSZachary Turner Reset(PyRefType::Owned, PyDict_New()); 9022c1f46dcSZachary Turner } 9032c1f46dcSZachary Turner 904f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) 905f8b22f8fSZachary Turner : PythonObject() 9062c1f46dcSZachary Turner { 907f8b22f8fSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary 9082c1f46dcSZachary Turner } 9092c1f46dcSZachary Turner 910f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object) 911f8b22f8fSZachary Turner : PythonObject(object) 9122c1f46dcSZachary Turner { 9132c1f46dcSZachary Turner } 9142c1f46dcSZachary Turner 9152c1f46dcSZachary Turner PythonDictionary::~PythonDictionary () 9162c1f46dcSZachary Turner { 9172c1f46dcSZachary Turner } 9182c1f46dcSZachary Turner 9192c1f46dcSZachary Turner bool 92022c8efcdSZachary Turner PythonDictionary::Check(PyObject *py_obj) 92122c8efcdSZachary Turner { 92222c8efcdSZachary Turner if (!py_obj) 92322c8efcdSZachary Turner return false; 92422c8efcdSZachary Turner 92522c8efcdSZachary Turner return PyDict_Check(py_obj); 92622c8efcdSZachary Turner } 92722c8efcdSZachary Turner 928f8b22f8fSZachary Turner void 929f8b22f8fSZachary Turner PythonDictionary::Reset(PyRefType type, PyObject *py_obj) 9302c1f46dcSZachary Turner { 931f8b22f8fSZachary Turner // Grab the desired reference type so that if we end up rejecting 932f8b22f8fSZachary Turner // `py_obj` it still gets decremented if necessary. 933f8b22f8fSZachary Turner PythonObject result(type, py_obj); 934f8b22f8fSZachary Turner 93522c8efcdSZachary Turner if (!PythonDictionary::Check(py_obj)) 93622c8efcdSZachary Turner { 937f8b22f8fSZachary Turner PythonObject::Reset(); 938f8b22f8fSZachary Turner return; 93922c8efcdSZachary Turner } 94022c8efcdSZachary Turner 941f8b22f8fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 942f8b22f8fSZachary Turner // back into the virtual implementation. 943f8b22f8fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 9442c1f46dcSZachary Turner } 9452c1f46dcSZachary Turner 9462c1f46dcSZachary Turner uint32_t 9472c1f46dcSZachary Turner PythonDictionary::GetSize() const 9482c1f46dcSZachary Turner { 949f8b22f8fSZachary Turner if (IsValid()) 9502c1f46dcSZachary Turner return PyDict_Size(m_py_obj); 9512c1f46dcSZachary Turner return 0; 9522c1f46dcSZachary Turner } 9532c1f46dcSZachary Turner 9542c1f46dcSZachary Turner PythonList 9552c1f46dcSZachary Turner PythonDictionary::GetKeys() const 9562c1f46dcSZachary Turner { 957f8b22f8fSZachary Turner if (IsValid()) 958f8b22f8fSZachary Turner return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); 959f8b22f8fSZachary Turner return PythonList(PyInitialValue::Invalid); 9602c1f46dcSZachary Turner } 9612c1f46dcSZachary Turner 9622c1f46dcSZachary Turner PythonObject 963f8b22f8fSZachary Turner PythonDictionary::GetItemForKey(const PythonObject &key) const 9642c1f46dcSZachary Turner { 965f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid()) 966f8b22f8fSZachary Turner return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get())); 9672c1f46dcSZachary Turner return PythonObject(); 9682c1f46dcSZachary Turner } 9692c1f46dcSZachary Turner 9702c1f46dcSZachary Turner void 971f8b22f8fSZachary Turner PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value) 9722c1f46dcSZachary Turner { 973f8b22f8fSZachary Turner if (IsAllocated() && key.IsValid() && value.IsValid()) 9742c1f46dcSZachary Turner PyDict_SetItem(m_py_obj, key.get(), value.get()); 9752c1f46dcSZachary Turner } 9762c1f46dcSZachary Turner 9772c1f46dcSZachary Turner StructuredData::DictionarySP 9782c1f46dcSZachary Turner PythonDictionary::CreateStructuredDictionary() const 9792c1f46dcSZachary Turner { 9802c1f46dcSZachary Turner StructuredData::DictionarySP result(new StructuredData::Dictionary); 9812c1f46dcSZachary Turner PythonList keys(GetKeys()); 9822c1f46dcSZachary Turner uint32_t num_keys = keys.GetSize(); 9832c1f46dcSZachary Turner for (uint32_t i = 0; i < num_keys; ++i) 9842c1f46dcSZachary Turner { 9852c1f46dcSZachary Turner PythonObject key = keys.GetItemAtIndex(i); 9862c1f46dcSZachary Turner PythonObject value = GetItemForKey(key); 9872c1f46dcSZachary Turner StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); 988f8b22f8fSZachary Turner result->AddItem(key.Str().GetString(), structured_value); 9892c1f46dcSZachary Turner } 9902c1f46dcSZachary Turner return result; 9912c1f46dcSZachary Turner } 9922c1f46dcSZachary Turner 9937841efbbSZachary Turner PythonModule::PythonModule() : PythonObject() 9947841efbbSZachary Turner { 9957841efbbSZachary Turner } 9967841efbbSZachary Turner 9977841efbbSZachary Turner PythonModule::PythonModule(PyRefType type, PyObject *py_obj) 9987841efbbSZachary Turner { 9997841efbbSZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module 10007841efbbSZachary Turner } 10017841efbbSZachary Turner 10027841efbbSZachary Turner PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict) 10037841efbbSZachary Turner { 10047841efbbSZachary Turner } 10057841efbbSZachary Turner 10067841efbbSZachary Turner PythonModule::~PythonModule() 10077841efbbSZachary Turner { 10087841efbbSZachary Turner } 10097841efbbSZachary Turner 10107841efbbSZachary Turner PythonModule 1011a1405147SZachary Turner PythonModule::BuiltinsModule() 1012a1405147SZachary Turner { 1013a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3 1014a1405147SZachary Turner return AddModule("builtins"); 1015a1405147SZachary Turner #else 1016a1405147SZachary Turner return AddModule("__builtin__"); 1017a1405147SZachary Turner #endif 1018a1405147SZachary Turner } 1019a1405147SZachary Turner 1020a1405147SZachary Turner PythonModule 10217841efbbSZachary Turner PythonModule::MainModule() 10227841efbbSZachary Turner { 1023a1405147SZachary Turner return AddModule("__main__"); 1024a1405147SZachary Turner } 1025a1405147SZachary Turner 1026a1405147SZachary Turner PythonModule 1027a1405147SZachary Turner PythonModule::AddModule(llvm::StringRef module) 1028a1405147SZachary Turner { 1029a1405147SZachary Turner std::string str = module.str(); 1030a1405147SZachary Turner return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); 10317841efbbSZachary Turner } 10327841efbbSZachary Turner 10332419f1d5SZachary Turner 10342419f1d5SZachary Turner PythonModule 10352419f1d5SZachary Turner PythonModule::ImportModule(llvm::StringRef module) 10362419f1d5SZachary Turner { 10372419f1d5SZachary Turner std::string str = module.str(); 10382419f1d5SZachary Turner return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str())); 10392419f1d5SZachary Turner } 10402419f1d5SZachary Turner 10417841efbbSZachary Turner bool 10427841efbbSZachary Turner PythonModule::Check(PyObject *py_obj) 10437841efbbSZachary Turner { 10447841efbbSZachary Turner if (!py_obj) 10457841efbbSZachary Turner return false; 10467841efbbSZachary Turner 10477841efbbSZachary Turner return PyModule_Check(py_obj); 10487841efbbSZachary Turner } 10497841efbbSZachary Turner 10507841efbbSZachary Turner void 10517841efbbSZachary Turner PythonModule::Reset(PyRefType type, PyObject *py_obj) 10527841efbbSZachary Turner { 10537841efbbSZachary Turner // Grab the desired reference type so that if we end up rejecting 10547841efbbSZachary Turner // `py_obj` it still gets decremented if necessary. 10557841efbbSZachary Turner PythonObject result(type, py_obj); 10567841efbbSZachary Turner 10577841efbbSZachary Turner if (!PythonModule::Check(py_obj)) 10587841efbbSZachary Turner { 10597841efbbSZachary Turner PythonObject::Reset(); 10607841efbbSZachary Turner return; 10617841efbbSZachary Turner } 10627841efbbSZachary Turner 10637841efbbSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 10647841efbbSZachary Turner // back into the virtual implementation. 10657841efbbSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 10667841efbbSZachary Turner } 10677841efbbSZachary Turner 10687841efbbSZachary Turner PythonDictionary 10697841efbbSZachary Turner PythonModule::GetDictionary() const 10707841efbbSZachary Turner { 10717841efbbSZachary Turner return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); 10727841efbbSZachary Turner } 10737841efbbSZachary Turner 1074a1405147SZachary Turner PythonCallable::PythonCallable() : PythonObject() 1075a1405147SZachary Turner { 1076a1405147SZachary Turner } 1077a1405147SZachary Turner 1078a1405147SZachary Turner PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) 1079a1405147SZachary Turner { 1080a1405147SZachary Turner Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable 1081a1405147SZachary Turner } 1082a1405147SZachary Turner 1083a1405147SZachary Turner PythonCallable::PythonCallable(const PythonCallable &callable) 1084a1405147SZachary Turner : PythonObject(callable) 1085a1405147SZachary Turner { 1086a1405147SZachary Turner } 1087a1405147SZachary Turner 1088a1405147SZachary Turner PythonCallable::~PythonCallable() 1089a1405147SZachary Turner { 1090a1405147SZachary Turner } 1091a1405147SZachary Turner 1092a1405147SZachary Turner bool 1093a1405147SZachary Turner PythonCallable::Check(PyObject *py_obj) 1094a1405147SZachary Turner { 1095a1405147SZachary Turner if (!py_obj) 1096a1405147SZachary Turner return false; 1097a1405147SZachary Turner 1098a1405147SZachary Turner return PyCallable_Check(py_obj); 1099a1405147SZachary Turner } 1100a1405147SZachary Turner 1101a1405147SZachary Turner void 1102a1405147SZachary Turner PythonCallable::Reset(PyRefType type, PyObject *py_obj) 1103a1405147SZachary Turner { 1104a1405147SZachary Turner // Grab the desired reference type so that if we end up rejecting 1105a1405147SZachary Turner // `py_obj` it still gets decremented if necessary. 1106a1405147SZachary Turner PythonObject result(type, py_obj); 1107a1405147SZachary Turner 1108a1405147SZachary Turner if (!PythonCallable::Check(py_obj)) 1109a1405147SZachary Turner { 1110a1405147SZachary Turner PythonObject::Reset(); 1111a1405147SZachary Turner return; 1112a1405147SZachary Turner } 1113a1405147SZachary Turner 1114a1405147SZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls 1115a1405147SZachary Turner // back into the virtual implementation. 1116a1405147SZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 1117a1405147SZachary Turner } 1118a1405147SZachary Turner 1119a1405147SZachary Turner 1120b58fb2f4SZachary Turner PythonCallable::ArgInfo 1121b58fb2f4SZachary Turner PythonCallable::GetNumArguments() const 1122a1405147SZachary Turner { 1123a5d6765cSEnrico Granata ArgInfo result = { 0, false, false, false }; 1124a1405147SZachary Turner if (!IsValid()) 1125b58fb2f4SZachary Turner return result; 1126a1405147SZachary Turner 1127a1405147SZachary Turner PyObject *py_func_obj = m_py_obj; 1128a1405147SZachary Turner if (PyMethod_Check(py_func_obj)) 1129a5d6765cSEnrico Granata { 1130a1405147SZachary Turner py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); 1131a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 1132a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 1133a5d6765cSEnrico Granata result.is_bound_method = true; 1134a5d6765cSEnrico Granata } 1135a5d6765cSEnrico Granata else 1136a5d6765cSEnrico Granata { 1137a5d6765cSEnrico Granata // see if this is a callable object with an __call__ method 1138a5d6765cSEnrico Granata if (!PyFunction_Check(py_func_obj)) 1139a5d6765cSEnrico Granata { 1140a5d6765cSEnrico Granata PythonObject __call__ = GetAttributeValue("__call__"); 1141a5d6765cSEnrico Granata if (__call__.IsValid()) 1142a5d6765cSEnrico Granata { 1143a5d6765cSEnrico Granata auto __callable__ = __call__.AsType<PythonCallable>(); 1144a5d6765cSEnrico Granata if (__callable__.IsValid()) 1145a5d6765cSEnrico Granata { 1146a5d6765cSEnrico Granata py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); 1147a5d6765cSEnrico Granata PythonObject im_self = GetAttributeValue("im_self"); 1148a5d6765cSEnrico Granata if (im_self.IsValid() && !im_self.IsNone()) 1149a5d6765cSEnrico Granata result.is_bound_method = true; 1150a5d6765cSEnrico Granata } 1151a5d6765cSEnrico Granata } 1152a5d6765cSEnrico Granata } 1153a5d6765cSEnrico Granata } 1154a1405147SZachary Turner 1155a1405147SZachary Turner if (!py_func_obj) 1156b58fb2f4SZachary Turner return result; 1157a1405147SZachary Turner 1158a1405147SZachary Turner PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj); 1159a1405147SZachary Turner if (!code) 1160b58fb2f4SZachary Turner return result; 1161a1405147SZachary Turner 1162b58fb2f4SZachary Turner result.count = code->co_argcount; 1163b58fb2f4SZachary Turner result.has_varargs = !!(code->co_flags & CO_VARARGS); 1164b58fb2f4SZachary Turner result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); 1165b58fb2f4SZachary Turner return result; 1166b58fb2f4SZachary Turner } 1167b58fb2f4SZachary Turner 1168b58fb2f4SZachary Turner PythonObject 1169b58fb2f4SZachary Turner PythonCallable::operator ()() 1170b58fb2f4SZachary Turner { 1171b58fb2f4SZachary Turner return PythonObject(PyRefType::Owned, 1172b58fb2f4SZachary Turner PyObject_CallObject(m_py_obj, nullptr)); 1173a1405147SZachary Turner } 1174a1405147SZachary Turner 1175a1405147SZachary Turner PythonObject 1176a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PyObject*> args) 1177a1405147SZachary Turner { 1178a1405147SZachary Turner PythonTuple arg_tuple(args); 1179a1405147SZachary Turner return PythonObject(PyRefType::Owned, 1180a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 1181a1405147SZachary Turner } 1182a1405147SZachary Turner 1183a1405147SZachary Turner PythonObject 1184a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PythonObject> args) 1185a1405147SZachary Turner { 1186a1405147SZachary Turner PythonTuple arg_tuple(args); 1187a1405147SZachary Turner return PythonObject(PyRefType::Owned, 1188a1405147SZachary Turner PyObject_CallObject(m_py_obj, arg_tuple.get())); 1189a1405147SZachary Turner } 1190a1405147SZachary Turner 119132064024SZachary Turner PythonFile::PythonFile() 119232064024SZachary Turner : PythonObject() 119332064024SZachary Turner { 119432064024SZachary Turner } 119532064024SZachary Turner 11969c40264fSZachary Turner PythonFile::PythonFile(File &file, const char *mode) 11979c40264fSZachary Turner { 11989c40264fSZachary Turner Reset(file, mode); 11999c40264fSZachary Turner } 12009c40264fSZachary Turner 1201eda01c31SZachary Turner PythonFile::PythonFile(const char *path, const char *mode) 1202eda01c31SZachary Turner { 1203190fadcdSZachary Turner lldb_private::File file(path, GetOptionsFromMode(mode)); 1204eda01c31SZachary Turner Reset(file, mode); 1205eda01c31SZachary Turner } 1206eda01c31SZachary Turner 12079c40264fSZachary Turner PythonFile::PythonFile(PyRefType type, PyObject *o) 12089c40264fSZachary Turner { 12099c40264fSZachary Turner Reset(type, o); 12109c40264fSZachary Turner } 12119c40264fSZachary Turner 12129c40264fSZachary Turner PythonFile::~PythonFile() 12139c40264fSZachary Turner { 12149c40264fSZachary Turner } 12159c40264fSZachary Turner 12169c40264fSZachary Turner bool 12179c40264fSZachary Turner PythonFile::Check(PyObject *py_obj) 12189c40264fSZachary Turner { 12199c40264fSZachary Turner #if PY_MAJOR_VERSION < 3 12209c40264fSZachary Turner return PyFile_Check(py_obj); 12219c40264fSZachary Turner #else 12229c40264fSZachary Turner // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a 12239c40264fSZachary Turner // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper 12249c40264fSZachary Turner // over `io.open()`, which returns some object derived from `io.IOBase`. 12259c40264fSZachary Turner // As a result, the only way to detect a file in Python 3 is to check whether 12269c40264fSZachary Turner // it inherits from `io.IOBase`. Since it is possible for non-files to also 12279c40264fSZachary Turner // inherit from `io.IOBase`, we additionally verify that it has the `fileno` 12289c40264fSZachary Turner // attribute, which should guarantee that it is backed by the file system. 12299c40264fSZachary Turner PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); 12309c40264fSZachary Turner PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get())); 12319c40264fSZachary Turner PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); 12329c40264fSZachary Turner 12339c40264fSZachary Turner PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); 12349c40264fSZachary Turner 12359c40264fSZachary Turner if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) 12369c40264fSZachary Turner return false; 12379c40264fSZachary Turner if (!object_type.HasAttribute("fileno")) 12389c40264fSZachary Turner return false; 12399c40264fSZachary Turner 12409c40264fSZachary Turner return true; 12419c40264fSZachary Turner #endif 12429c40264fSZachary Turner } 12439c40264fSZachary Turner 12449c40264fSZachary Turner void 12459c40264fSZachary Turner PythonFile::Reset(PyRefType type, PyObject *py_obj) 12469c40264fSZachary Turner { 12479c40264fSZachary Turner // Grab the desired reference type so that if we end up rejecting 12489c40264fSZachary Turner // `py_obj` it still gets decremented if necessary. 12499c40264fSZachary Turner PythonObject result(type, py_obj); 12509c40264fSZachary Turner 12519c40264fSZachary Turner if (!PythonFile::Check(py_obj)) 12529c40264fSZachary Turner { 12539c40264fSZachary Turner PythonObject::Reset(); 12549c40264fSZachary Turner return; 12559c40264fSZachary Turner } 12569c40264fSZachary Turner 12579c40264fSZachary Turner // Calling PythonObject::Reset(const PythonObject&) will lead to stack 12589c40264fSZachary Turner // overflow since it calls back into the virtual implementation. 12599c40264fSZachary Turner PythonObject::Reset(PyRefType::Borrowed, result.get()); 12609c40264fSZachary Turner } 12619c40264fSZachary Turner 12629c40264fSZachary Turner void 12639c40264fSZachary Turner PythonFile::Reset(File &file, const char *mode) 12649c40264fSZachary Turner { 126532ac147bSZachary Turner if (!file.IsValid()) 126632ac147bSZachary Turner { 126732ac147bSZachary Turner Reset(); 126832ac147bSZachary Turner return; 126932ac147bSZachary Turner } 127032ac147bSZachary Turner 12719c40264fSZachary Turner char *cmode = const_cast<char *>(mode); 12729c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3 12739c40264fSZachary Turner Reset(PyRefType::Owned, 12749c40264fSZachary Turner PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0)); 12759c40264fSZachary Turner #else 12769c40264fSZachary Turner // Read through the Python source, doesn't seem to modify these strings 12779c40264fSZachary Turner Reset(PyRefType::Owned, 12789c40264fSZachary Turner PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr)); 12799c40264fSZachary Turner #endif 12809c40264fSZachary Turner } 12819c40264fSZachary Turner 1282744959b9SEnrico Granata uint32_t 1283744959b9SEnrico Granata PythonFile::GetOptionsFromMode(llvm::StringRef mode) 1284744959b9SEnrico Granata { 1285744959b9SEnrico Granata if (mode.empty()) 1286744959b9SEnrico Granata return 0; 1287744959b9SEnrico Granata 1288744959b9SEnrico Granata return llvm::StringSwitch<uint32_t>(mode.str().c_str()) 1289744959b9SEnrico Granata .Case("r", File::eOpenOptionRead) 1290744959b9SEnrico Granata .Case("w", File::eOpenOptionWrite) 1291c5273d92SStephane Sezer .Case("a", File::eOpenOptionWrite|File::eOpenOptionAppend|File::eOpenOptionCanCreate) 1292744959b9SEnrico Granata .Case("r+", File::eOpenOptionRead|File::eOpenOptionWrite) 1293744959b9SEnrico Granata .Case("w+", File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionCanCreate|File::eOpenOptionTruncate) 1294c5273d92SStephane Sezer .Case("a+", File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionAppend|File::eOpenOptionCanCreate) 1295744959b9SEnrico Granata .Default(0); 1296744959b9SEnrico Granata } 1297744959b9SEnrico Granata 1298eda01c31SZachary Turner bool 1299eda01c31SZachary Turner PythonFile::GetUnderlyingFile(File &file) const 1300eda01c31SZachary Turner { 1301eda01c31SZachary Turner if (!IsValid()) 1302eda01c31SZachary Turner return false; 1303eda01c31SZachary Turner 1304eda01c31SZachary Turner file.Close(); 1305eda01c31SZachary Turner // We don't own the file descriptor returned by this function, make sure the 1306eda01c31SZachary Turner // File object knows about that. 1307eda01c31SZachary Turner file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); 1308744959b9SEnrico Granata PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); 1309744959b9SEnrico Granata file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString())); 1310eda01c31SZachary Turner return file.IsValid(); 1311eda01c31SZachary Turner } 1312eda01c31SZachary Turner 1313eda01c31SZachary Turner 13142c1f46dcSZachary Turner #endif 1315