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