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 
26*744959b9SEnrico Granata #include "llvm/ADT/StringSwitch.h"
27*744959b9SEnrico 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
8618426935SZachary Turner     if (PythonInteger::Check(m_py_obj))
8722c8efcdSZachary Turner         return PyObjectType::Integer;
889c40264fSZachary Turner     if (PythonFile::Check(m_py_obj))
899c40264fSZachary Turner         return PyObjectType::File;
90a1405147SZachary Turner     if (PythonCallable::Check(m_py_obj))
91a1405147SZachary Turner         return PyObjectType::Callable;
922c1f46dcSZachary Turner     return PyObjectType::Unknown;
932c1f46dcSZachary Turner }
942c1f46dcSZachary Turner 
952c1f46dcSZachary Turner PythonString
967841efbbSZachary Turner PythonObject::Repr() const
972c1f46dcSZachary Turner {
982c1f46dcSZachary Turner     if (!m_py_obj)
992c1f46dcSZachary Turner         return PythonString();
1002c1f46dcSZachary Turner     PyObject *repr = PyObject_Repr(m_py_obj);
1012c1f46dcSZachary Turner     if (!repr)
1022c1f46dcSZachary Turner         return PythonString();
103f8b22f8fSZachary Turner     return PythonString(PyRefType::Owned, repr);
1042c1f46dcSZachary Turner }
1052c1f46dcSZachary Turner 
1062c1f46dcSZachary Turner PythonString
1077841efbbSZachary Turner PythonObject::Str() const
1082c1f46dcSZachary Turner {
1092c1f46dcSZachary Turner     if (!m_py_obj)
1102c1f46dcSZachary Turner         return PythonString();
1112c1f46dcSZachary Turner     PyObject *str = PyObject_Str(m_py_obj);
1122c1f46dcSZachary Turner     if (!str)
1132c1f46dcSZachary Turner         return PythonString();
114f8b22f8fSZachary Turner     return PythonString(PyRefType::Owned, str);
1152c1f46dcSZachary Turner }
1162c1f46dcSZachary Turner 
1177841efbbSZachary Turner PythonObject
11802bf92d2SZachary Turner PythonObject::ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict)
1197841efbbSZachary Turner {
120a1405147SZachary Turner     size_t dot_pos = name.find_first_of('.');
121a1405147SZachary Turner     llvm::StringRef piece = name.substr(0, dot_pos);
122a1405147SZachary Turner     PythonObject result = dict.GetItemForKey(PythonString(piece));
123a1405147SZachary Turner     if (dot_pos == llvm::StringRef::npos)
124a1405147SZachary Turner     {
125a1405147SZachary Turner         // There was no dot, we're done.
126a1405147SZachary Turner         return result;
127a1405147SZachary Turner     }
128a1405147SZachary Turner 
129a1405147SZachary Turner     // There was a dot.  The remaining portion of the name should be looked up in
130a1405147SZachary Turner     // the context of the object that was found in the dictionary.
131a1405147SZachary Turner     return result.ResolveName(name.substr(dot_pos + 1));
1327841efbbSZachary Turner }
1337841efbbSZachary Turner 
1347841efbbSZachary Turner PythonObject
1357841efbbSZachary Turner PythonObject::ResolveName(llvm::StringRef name) const
1367841efbbSZachary Turner {
1377841efbbSZachary Turner     // Resolve the name in the context of the specified object.  If,
1387841efbbSZachary Turner     // for example, `this` refers to a PyModule, then this will look for
1397841efbbSZachary Turner     // `name` in this module.  If `this` refers to a PyType, then it will
1407841efbbSZachary Turner     // resolve `name` as an attribute of that type.  If `this` refers to
1417841efbbSZachary Turner     // an instance of an object, then it will resolve `name` as the value
1427841efbbSZachary Turner     // of the specified field.
1437841efbbSZachary Turner     //
1447841efbbSZachary Turner     // This function handles dotted names so that, for example, if `m_py_obj`
1457841efbbSZachary Turner     // refers to the `sys` module, and `name` == "path.append", then it
1467841efbbSZachary Turner     // will find the function `sys.path.append`.
1477841efbbSZachary Turner 
1487841efbbSZachary Turner     size_t dot_pos = name.find_first_of('.');
1497841efbbSZachary Turner     if (dot_pos == llvm::StringRef::npos)
1507841efbbSZachary Turner     {
1517841efbbSZachary Turner         // No dots in the name, we should be able to find the value immediately
152a1405147SZachary Turner         // as an attribute of `m_py_obj`.
1537841efbbSZachary Turner         return GetAttributeValue(name);
1547841efbbSZachary Turner     }
1557841efbbSZachary Turner 
1567841efbbSZachary Turner     // Look up the first piece of the name, and resolve the rest as a child of that.
1577841efbbSZachary Turner     PythonObject parent = ResolveName(name.substr(0, dot_pos));
1587841efbbSZachary Turner     if (!parent.IsAllocated())
1597841efbbSZachary Turner         return PythonObject();
1607841efbbSZachary Turner 
1617841efbbSZachary Turner     // Tail recursion.. should be optimized by the compiler
1627841efbbSZachary Turner     return parent.ResolveName(name.substr(dot_pos + 1));
1637841efbbSZachary Turner }
1647841efbbSZachary Turner 
1652c1f46dcSZachary Turner bool
1669c40264fSZachary Turner PythonObject::HasAttribute(llvm::StringRef attr) const
1679c40264fSZachary Turner {
1689c40264fSZachary Turner     if (!IsValid())
1699c40264fSZachary Turner         return false;
1709c40264fSZachary Turner     PythonString py_attr(attr);
1719c40264fSZachary Turner     return !!PyObject_HasAttr(m_py_obj, py_attr.get());
1729c40264fSZachary Turner }
1739c40264fSZachary Turner 
1747d6d218eSZachary Turner PythonObject
1757d6d218eSZachary Turner PythonObject::GetAttributeValue(llvm::StringRef attr) const
1767d6d218eSZachary Turner {
1777d6d218eSZachary Turner     if (!IsValid())
1787d6d218eSZachary Turner         return PythonObject();
1797d6d218eSZachary Turner 
1807d6d218eSZachary Turner     PythonString py_attr(attr);
1817d6d218eSZachary Turner     if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
1827d6d218eSZachary Turner         return PythonObject();
1837d6d218eSZachary Turner 
1847d6d218eSZachary Turner     return PythonObject(PyRefType::Owned,
1857d6d218eSZachary Turner         PyObject_GetAttr(m_py_obj, py_attr.get()));
1867d6d218eSZachary Turner }
1877d6d218eSZachary Turner 
1889c40264fSZachary Turner bool
189f8b22f8fSZachary Turner PythonObject::IsNone() const
1902c1f46dcSZachary Turner {
191f8b22f8fSZachary Turner     return m_py_obj == Py_None;
192f8b22f8fSZachary Turner }
193f8b22f8fSZachary Turner 
194f8b22f8fSZachary Turner bool
195f8b22f8fSZachary Turner PythonObject::IsValid() const
196f8b22f8fSZachary Turner {
197f8b22f8fSZachary Turner     return m_py_obj != nullptr;
198f8b22f8fSZachary Turner }
199f8b22f8fSZachary Turner 
200f8b22f8fSZachary Turner bool
201f8b22f8fSZachary Turner PythonObject::IsAllocated() const
202f8b22f8fSZachary Turner {
203f8b22f8fSZachary Turner     return IsValid() && !IsNone();
2042c1f46dcSZachary Turner }
2052c1f46dcSZachary Turner 
2062c1f46dcSZachary Turner StructuredData::ObjectSP
2072c1f46dcSZachary Turner PythonObject::CreateStructuredObject() const
2082c1f46dcSZachary Turner {
2092c1f46dcSZachary Turner     switch (GetObjectType())
2102c1f46dcSZachary Turner     {
2112c1f46dcSZachary Turner         case PyObjectType::Dictionary:
212f8b22f8fSZachary Turner             return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary();
2132c1f46dcSZachary Turner         case PyObjectType::Integer:
214f8b22f8fSZachary Turner             return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger();
2152c1f46dcSZachary Turner         case PyObjectType::List:
216f8b22f8fSZachary Turner             return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
2172c1f46dcSZachary Turner         case PyObjectType::String:
218f8b22f8fSZachary Turner             return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2195a72c02bSZachary Turner         case PyObjectType::Bytes:
2205a72c02bSZachary Turner             return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
2212c1f46dcSZachary Turner         case PyObjectType::None:
2222c1f46dcSZachary Turner             return StructuredData::ObjectSP();
2232c1f46dcSZachary Turner         default:
2242c1f46dcSZachary Turner             return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
2252c1f46dcSZachary Turner     }
2262c1f46dcSZachary Turner }
2272c1f46dcSZachary Turner 
2282c1f46dcSZachary Turner //----------------------------------------------------------------------
2292c1f46dcSZachary Turner // PythonString
2302c1f46dcSZachary Turner //----------------------------------------------------------------------
2315a72c02bSZachary Turner PythonBytes::PythonBytes() : PythonObject()
2325a72c02bSZachary Turner {
2335a72c02bSZachary Turner }
2345a72c02bSZachary Turner 
2355a72c02bSZachary Turner PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject()
2365a72c02bSZachary Turner {
2375a72c02bSZachary Turner     SetBytes(bytes);
2385a72c02bSZachary Turner }
2395a72c02bSZachary Turner 
2405a72c02bSZachary Turner PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject()
2415a72c02bSZachary Turner {
2425a72c02bSZachary Turner     SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
2435a72c02bSZachary Turner }
2445a72c02bSZachary Turner 
2455a72c02bSZachary Turner PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject()
2465a72c02bSZachary Turner {
2475a72c02bSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
2485a72c02bSZachary Turner }
2495a72c02bSZachary Turner 
2505a72c02bSZachary Turner PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object)
2515a72c02bSZachary Turner {
2525a72c02bSZachary Turner }
2535a72c02bSZachary Turner 
2545a72c02bSZachary Turner PythonBytes::~PythonBytes()
2555a72c02bSZachary Turner {
2565a72c02bSZachary Turner }
2575a72c02bSZachary Turner 
2585a72c02bSZachary Turner bool
2595a72c02bSZachary Turner PythonBytes::Check(PyObject *py_obj)
2605a72c02bSZachary Turner {
2615a72c02bSZachary Turner     if (!py_obj)
2625a72c02bSZachary Turner         return false;
2635a72c02bSZachary Turner     if (PyBytes_Check(py_obj))
2645a72c02bSZachary Turner         return true;
2655a72c02bSZachary Turner     return false;
2665a72c02bSZachary Turner }
2675a72c02bSZachary Turner 
2685a72c02bSZachary Turner void
2695a72c02bSZachary Turner PythonBytes::Reset(PyRefType type, PyObject *py_obj)
2705a72c02bSZachary Turner {
2715a72c02bSZachary Turner     // Grab the desired reference type so that if we end up rejecting
2725a72c02bSZachary Turner     // `py_obj` it still gets decremented if necessary.
2735a72c02bSZachary Turner     PythonObject result(type, py_obj);
2745a72c02bSZachary Turner 
2755a72c02bSZachary Turner     if (!PythonBytes::Check(py_obj))
2765a72c02bSZachary Turner     {
2775a72c02bSZachary Turner         PythonObject::Reset();
2785a72c02bSZachary Turner         return;
2795a72c02bSZachary Turner     }
2805a72c02bSZachary Turner 
2815a72c02bSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
2825a72c02bSZachary Turner     // back into the virtual implementation.
2835a72c02bSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
2845a72c02bSZachary Turner }
2855a72c02bSZachary Turner 
2865a72c02bSZachary Turner llvm::ArrayRef<uint8_t>
2875a72c02bSZachary Turner PythonBytes::GetBytes() const
2885a72c02bSZachary Turner {
2895a72c02bSZachary Turner     if (!IsValid())
2905a72c02bSZachary Turner         return llvm::ArrayRef<uint8_t>();
2915a72c02bSZachary Turner 
2925a72c02bSZachary Turner     Py_ssize_t size;
2935a72c02bSZachary Turner     char *c;
2945a72c02bSZachary Turner 
2955a72c02bSZachary Turner     PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2965a72c02bSZachary Turner     return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
2975a72c02bSZachary Turner }
2985a72c02bSZachary Turner 
2995a72c02bSZachary Turner size_t
3005a72c02bSZachary Turner PythonBytes::GetSize() const
3015a72c02bSZachary Turner {
3025a72c02bSZachary Turner     if (!IsValid())
3035a72c02bSZachary Turner         return 0;
3045a72c02bSZachary Turner     return PyBytes_Size(m_py_obj);
3055a72c02bSZachary Turner }
3065a72c02bSZachary Turner 
3075a72c02bSZachary Turner void
3085a72c02bSZachary Turner PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes)
3095a72c02bSZachary Turner {
3105a72c02bSZachary Turner     const char *data = reinterpret_cast<const char *>(bytes.data());
3115a72c02bSZachary Turner     PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
3125a72c02bSZachary Turner     PythonObject::Reset(PyRefType::Owned, py_bytes);
3135a72c02bSZachary Turner }
3145a72c02bSZachary Turner 
3155a72c02bSZachary Turner StructuredData::StringSP
3165a72c02bSZachary Turner PythonBytes::CreateStructuredString() const
3175a72c02bSZachary Turner {
3185a72c02bSZachary Turner     StructuredData::StringSP result(new StructuredData::String);
3195a72c02bSZachary Turner     Py_ssize_t size;
3205a72c02bSZachary Turner     char *c;
3215a72c02bSZachary Turner     PyBytes_AsStringAndSize(m_py_obj, &c, &size);
3225a72c02bSZachary Turner     result->SetValue(std::string(c, size));
3235a72c02bSZachary Turner     return result;
3245a72c02bSZachary Turner }
3255a72c02bSZachary Turner 
3265a72c02bSZachary Turner //----------------------------------------------------------------------
3275a72c02bSZachary Turner // PythonString
3285a72c02bSZachary Turner //----------------------------------------------------------------------
3292c1f46dcSZachary Turner 
330f8b22f8fSZachary Turner PythonString::PythonString(PyRefType type, PyObject *py_obj)
331f8b22f8fSZachary Turner     : PythonObject()
3322c1f46dcSZachary Turner {
333f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
3342c1f46dcSZachary Turner }
3352c1f46dcSZachary Turner 
336f8b22f8fSZachary Turner PythonString::PythonString(const PythonString &object)
337f8b22f8fSZachary Turner     : PythonObject(object)
3382c1f46dcSZachary Turner {
3392c1f46dcSZachary Turner }
3402c1f46dcSZachary Turner 
34122c8efcdSZachary Turner PythonString::PythonString(llvm::StringRef string)
34222c8efcdSZachary Turner     : PythonObject()
3432c1f46dcSZachary Turner {
34422c8efcdSZachary Turner     SetString(string);
3452c1f46dcSZachary Turner }
3462c1f46dcSZachary Turner 
34722c8efcdSZachary Turner PythonString::PythonString(const char *string)
34822c8efcdSZachary Turner     : PythonObject()
3492c1f46dcSZachary Turner {
35022c8efcdSZachary Turner     SetString(llvm::StringRef(string));
3512c1f46dcSZachary Turner }
3522c1f46dcSZachary Turner 
353f8b22f8fSZachary Turner PythonString::PythonString()
354f8b22f8fSZachary Turner     : PythonObject()
3552c1f46dcSZachary Turner {
3562c1f46dcSZachary Turner }
3572c1f46dcSZachary Turner 
3582c1f46dcSZachary Turner PythonString::~PythonString ()
3592c1f46dcSZachary Turner {
3602c1f46dcSZachary Turner }
3612c1f46dcSZachary Turner 
3622c1f46dcSZachary Turner bool
36322c8efcdSZachary Turner PythonString::Check(PyObject *py_obj)
36422c8efcdSZachary Turner {
36522c8efcdSZachary Turner     if (!py_obj)
36622c8efcdSZachary Turner         return false;
36718426935SZachary Turner 
3687d6d218eSZachary Turner     if (PyUnicode_Check(py_obj))
3697d6d218eSZachary Turner         return true;
3707d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3717d6d218eSZachary Turner     if (PyString_Check(py_obj))
3727d6d218eSZachary Turner         return true;
37322c8efcdSZachary Turner #endif
3747d6d218eSZachary Turner     return false;
37522c8efcdSZachary Turner }
37622c8efcdSZachary Turner 
377f8b22f8fSZachary Turner void
378f8b22f8fSZachary Turner PythonString::Reset(PyRefType type, PyObject *py_obj)
3792c1f46dcSZachary Turner {
380f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
381f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
382f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
383f8b22f8fSZachary Turner 
38422c8efcdSZachary Turner     if (!PythonString::Check(py_obj))
38522c8efcdSZachary Turner     {
386f8b22f8fSZachary Turner         PythonObject::Reset();
387f8b22f8fSZachary Turner         return;
38822c8efcdSZachary Turner     }
3897d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3907d6d218eSZachary Turner     // In Python 2, Don't store PyUnicode objects directly, because we need
3917d6d218eSZachary Turner     // access to their underlying character buffers which Python 2 doesn't
3927d6d218eSZachary Turner     // provide.
3937d6d218eSZachary Turner     if (PyUnicode_Check(py_obj))
3947d6d218eSZachary Turner         result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
3957d6d218eSZachary Turner #endif
396f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
397f8b22f8fSZachary Turner     // back into the virtual implementation.
398f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
3992c1f46dcSZachary Turner }
4002c1f46dcSZachary Turner 
4012c1f46dcSZachary Turner llvm::StringRef
4022c1f46dcSZachary Turner PythonString::GetString() const
4032c1f46dcSZachary Turner {
40418426935SZachary Turner     if (!IsValid())
40518426935SZachary Turner         return llvm::StringRef();
40618426935SZachary Turner 
40722c8efcdSZachary Turner     Py_ssize_t size;
40822c8efcdSZachary Turner     char *c;
40918426935SZachary Turner 
41018426935SZachary Turner #if PY_MAJOR_VERSION >= 3
41118426935SZachary Turner     c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
41218426935SZachary Turner #else
41318426935SZachary Turner     PyString_AsStringAndSize(m_py_obj, &c, &size);
41418426935SZachary Turner #endif
41522c8efcdSZachary Turner     return llvm::StringRef(c, size);
41622c8efcdSZachary Turner }
4172c1f46dcSZachary Turner 
4182c1f46dcSZachary Turner size_t
4192c1f46dcSZachary Turner PythonString::GetSize() const
4202c1f46dcSZachary Turner {
421f8b22f8fSZachary Turner     if (IsValid())
42218426935SZachary Turner     {
42318426935SZachary Turner #if PY_MAJOR_VERSION >= 3
42418426935SZachary Turner         return PyUnicode_GetSize(m_py_obj);
42518426935SZachary Turner #else
42618426935SZachary Turner         return PyString_Size(m_py_obj);
42718426935SZachary Turner #endif
42818426935SZachary Turner     }
4292c1f46dcSZachary Turner     return 0;
4302c1f46dcSZachary Turner }
4312c1f46dcSZachary Turner 
4322c1f46dcSZachary Turner void
4332c1f46dcSZachary Turner PythonString::SetString (llvm::StringRef string)
4342c1f46dcSZachary Turner {
43522c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
43622c8efcdSZachary Turner     PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
43718426935SZachary Turner     PythonObject::Reset(PyRefType::Owned, unicode);
43822c8efcdSZachary Turner #else
43918426935SZachary Turner     PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
44018426935SZachary Turner     PythonObject::Reset(PyRefType::Owned, str);
44122c8efcdSZachary Turner #endif
4422c1f46dcSZachary Turner }
4432c1f46dcSZachary Turner 
4442c1f46dcSZachary Turner StructuredData::StringSP
4452c1f46dcSZachary Turner PythonString::CreateStructuredString() const
4462c1f46dcSZachary Turner {
4472c1f46dcSZachary Turner     StructuredData::StringSP result(new StructuredData::String);
4482c1f46dcSZachary Turner     result->SetValue(GetString());
4492c1f46dcSZachary Turner     return result;
4502c1f46dcSZachary Turner }
4512c1f46dcSZachary Turner 
4522c1f46dcSZachary Turner //----------------------------------------------------------------------
4532c1f46dcSZachary Turner // PythonInteger
4542c1f46dcSZachary Turner //----------------------------------------------------------------------
4552c1f46dcSZachary Turner 
4567d6d218eSZachary Turner PythonInteger::PythonInteger()
4577d6d218eSZachary Turner     : PythonObject()
4587d6d218eSZachary Turner {
4597d6d218eSZachary Turner 
4607d6d218eSZachary Turner }
4617d6d218eSZachary Turner 
462f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
463f8b22f8fSZachary Turner     : PythonObject()
4642c1f46dcSZachary Turner {
465f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
4662c1f46dcSZachary Turner }
4672c1f46dcSZachary Turner 
468f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object)
469f8b22f8fSZachary Turner     : PythonObject(object)
4702c1f46dcSZachary Turner {
4712c1f46dcSZachary Turner }
4722c1f46dcSZachary Turner 
473f8b22f8fSZachary Turner PythonInteger::PythonInteger(int64_t value)
474f8b22f8fSZachary Turner     : PythonObject()
4752c1f46dcSZachary Turner {
4762c1f46dcSZachary Turner     SetInteger(value);
4772c1f46dcSZachary Turner }
4782c1f46dcSZachary Turner 
4792c1f46dcSZachary Turner 
4802c1f46dcSZachary Turner PythonInteger::~PythonInteger ()
4812c1f46dcSZachary Turner {
4822c1f46dcSZachary Turner }
4832c1f46dcSZachary Turner 
4842c1f46dcSZachary Turner bool
48522c8efcdSZachary Turner PythonInteger::Check(PyObject *py_obj)
4862c1f46dcSZachary Turner {
48722c8efcdSZachary Turner     if (!py_obj)
48822c8efcdSZachary Turner         return false;
48922c8efcdSZachary Turner 
49022c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
49122c8efcdSZachary Turner     // Python 3 does not have PyInt_Check.  There is only one type of
49222c8efcdSZachary Turner     // integral value, long.
49322c8efcdSZachary Turner     return PyLong_Check(py_obj);
49422c8efcdSZachary Turner #else
49522c8efcdSZachary Turner     return PyLong_Check(py_obj) || PyInt_Check(py_obj);
49622c8efcdSZachary Turner #endif
4972c1f46dcSZachary Turner }
4982c1f46dcSZachary Turner 
499f8b22f8fSZachary Turner void
500f8b22f8fSZachary Turner PythonInteger::Reset(PyRefType type, PyObject *py_obj)
50122c8efcdSZachary Turner {
502f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
503f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
504f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
505f8b22f8fSZachary Turner 
50622c8efcdSZachary Turner     if (!PythonInteger::Check(py_obj))
50722c8efcdSZachary Turner     {
508f8b22f8fSZachary Turner         PythonObject::Reset();
509f8b22f8fSZachary Turner         return;
51022c8efcdSZachary Turner     }
51122c8efcdSZachary Turner 
51222c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
51322c8efcdSZachary Turner     // Always store this as a PyLong, which makes interoperability between
51422c8efcdSZachary Turner     // Python 2.x and Python 3.x easier.  This is only necessary in 2.x,
51522c8efcdSZachary Turner     // since 3.x doesn't even have a PyInt.
51622c8efcdSZachary Turner     if (PyInt_Check(py_obj))
51722c8efcdSZachary Turner     {
518f8b22f8fSZachary Turner         // Since we converted the original object to a different type, the new
519f8b22f8fSZachary Turner         // object is an owned object regardless of the ownership semantics requested
520f8b22f8fSZachary Turner         // by the user.
521f8b22f8fSZachary Turner         result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
52222c8efcdSZachary Turner     }
52322c8efcdSZachary Turner #endif
52422c8efcdSZachary Turner 
525f8b22f8fSZachary Turner     assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject");
52622c8efcdSZachary Turner 
527f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
528f8b22f8fSZachary Turner     // back into the virtual implementation.
529f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
5302c1f46dcSZachary Turner }
5312c1f46dcSZachary Turner 
5322c1f46dcSZachary Turner int64_t
5332c1f46dcSZachary Turner PythonInteger::GetInteger() const
5342c1f46dcSZachary Turner {
5352c1f46dcSZachary Turner     if (m_py_obj)
5362c1f46dcSZachary Turner     {
53722c8efcdSZachary Turner         assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
53822c8efcdSZachary Turner 
5392c1f46dcSZachary Turner         return PyLong_AsLongLong(m_py_obj);
5402c1f46dcSZachary Turner     }
5412c1f46dcSZachary Turner     return UINT64_MAX;
5422c1f46dcSZachary Turner }
5432c1f46dcSZachary Turner 
5442c1f46dcSZachary Turner void
5452c1f46dcSZachary Turner PythonInteger::SetInteger(int64_t value)
5462c1f46dcSZachary Turner {
547f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
5482c1f46dcSZachary Turner }
5492c1f46dcSZachary Turner 
5502c1f46dcSZachary Turner StructuredData::IntegerSP
5512c1f46dcSZachary Turner PythonInteger::CreateStructuredInteger() const
5522c1f46dcSZachary Turner {
5532c1f46dcSZachary Turner     StructuredData::IntegerSP result(new StructuredData::Integer);
5542c1f46dcSZachary Turner     result->SetValue(GetInteger());
5552c1f46dcSZachary Turner     return result;
5562c1f46dcSZachary Turner }
5572c1f46dcSZachary Turner 
5582c1f46dcSZachary Turner //----------------------------------------------------------------------
5592c1f46dcSZachary Turner // PythonList
5602c1f46dcSZachary Turner //----------------------------------------------------------------------
5612c1f46dcSZachary Turner 
562f8b22f8fSZachary Turner PythonList::PythonList(PyInitialValue value)
563f8b22f8fSZachary Turner     : PythonObject()
5642c1f46dcSZachary Turner {
565f8b22f8fSZachary Turner     if (value == PyInitialValue::Empty)
566f8b22f8fSZachary Turner         Reset(PyRefType::Owned, PyList_New(0));
5672c1f46dcSZachary Turner }
5682c1f46dcSZachary Turner 
56987f47729SZachary Turner PythonList::PythonList(int list_size)
57087f47729SZachary Turner     : PythonObject()
57187f47729SZachary Turner {
57287f47729SZachary Turner     Reset(PyRefType::Owned, PyList_New(list_size));
57387f47729SZachary Turner }
57487f47729SZachary Turner 
575f8b22f8fSZachary Turner PythonList::PythonList(PyRefType type, PyObject *py_obj)
576f8b22f8fSZachary Turner     : PythonObject()
5772c1f46dcSZachary Turner {
578f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
5792c1f46dcSZachary Turner }
5802c1f46dcSZachary Turner 
581f8b22f8fSZachary Turner PythonList::PythonList(const PythonList &list)
582f8b22f8fSZachary Turner     : PythonObject(list)
5832c1f46dcSZachary Turner {
5842c1f46dcSZachary Turner }
5852c1f46dcSZachary Turner 
5862c1f46dcSZachary Turner PythonList::~PythonList ()
5872c1f46dcSZachary Turner {
5882c1f46dcSZachary Turner }
5892c1f46dcSZachary Turner 
5902c1f46dcSZachary Turner bool
59122c8efcdSZachary Turner PythonList::Check(PyObject *py_obj)
59222c8efcdSZachary Turner {
59322c8efcdSZachary Turner     if (!py_obj)
59422c8efcdSZachary Turner         return false;
59522c8efcdSZachary Turner     return PyList_Check(py_obj);
59622c8efcdSZachary Turner }
59722c8efcdSZachary Turner 
598f8b22f8fSZachary Turner void
599f8b22f8fSZachary Turner PythonList::Reset(PyRefType type, PyObject *py_obj)
6002c1f46dcSZachary Turner {
601f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
602f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
603f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
604f8b22f8fSZachary Turner 
60522c8efcdSZachary Turner     if (!PythonList::Check(py_obj))
60622c8efcdSZachary Turner     {
607f8b22f8fSZachary Turner         PythonObject::Reset();
608f8b22f8fSZachary Turner         return;
60922c8efcdSZachary Turner     }
61022c8efcdSZachary Turner 
611f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
612f8b22f8fSZachary Turner     // back into the virtual implementation.
613f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
6142c1f46dcSZachary Turner }
6152c1f46dcSZachary Turner 
6162c1f46dcSZachary Turner uint32_t
6172c1f46dcSZachary Turner PythonList::GetSize() const
6182c1f46dcSZachary Turner {
619f8b22f8fSZachary Turner     if (IsValid())
6202c1f46dcSZachary Turner         return PyList_GET_SIZE(m_py_obj);
6212c1f46dcSZachary Turner     return 0;
6222c1f46dcSZachary Turner }
6232c1f46dcSZachary Turner 
6242c1f46dcSZachary Turner PythonObject
6252c1f46dcSZachary Turner PythonList::GetItemAtIndex(uint32_t index) const
6262c1f46dcSZachary Turner {
627f8b22f8fSZachary Turner     if (IsValid())
628f8b22f8fSZachary Turner         return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
6292c1f46dcSZachary Turner     return PythonObject();
6302c1f46dcSZachary Turner }
6312c1f46dcSZachary Turner 
6322c1f46dcSZachary Turner void
6332c1f46dcSZachary Turner PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object)
6342c1f46dcSZachary Turner {
635f8b22f8fSZachary Turner     if (IsAllocated() && object.IsValid())
636f8b22f8fSZachary Turner     {
637f8b22f8fSZachary Turner         // PyList_SetItem is documented to "steal" a reference, so we need to
638f8b22f8fSZachary Turner         // convert it to an owned reference by incrementing it.
639f8b22f8fSZachary Turner         Py_INCREF(object.get());
6402c1f46dcSZachary Turner         PyList_SetItem(m_py_obj, index, object.get());
6412c1f46dcSZachary Turner     }
642f8b22f8fSZachary Turner }
6432c1f46dcSZachary Turner 
6442c1f46dcSZachary Turner void
6452c1f46dcSZachary Turner PythonList::AppendItem(const PythonObject &object)
6462c1f46dcSZachary Turner {
647f8b22f8fSZachary Turner     if (IsAllocated() && object.IsValid())
648f8b22f8fSZachary Turner     {
649f8b22f8fSZachary Turner         // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
650f8b22f8fSZachary Turner         // here like we do with `PyList_SetItem`.
6512c1f46dcSZachary Turner         PyList_Append(m_py_obj, object.get());
6522c1f46dcSZachary Turner     }
653f8b22f8fSZachary Turner }
6542c1f46dcSZachary Turner 
6552c1f46dcSZachary Turner StructuredData::ArraySP
6562c1f46dcSZachary Turner PythonList::CreateStructuredArray() const
6572c1f46dcSZachary Turner {
6582c1f46dcSZachary Turner     StructuredData::ArraySP result(new StructuredData::Array);
6592c1f46dcSZachary Turner     uint32_t count = GetSize();
6602c1f46dcSZachary Turner     for (uint32_t i = 0; i < count; ++i)
6612c1f46dcSZachary Turner     {
6622c1f46dcSZachary Turner         PythonObject obj = GetItemAtIndex(i);
6632c1f46dcSZachary Turner         result->AddItem(obj.CreateStructuredObject());
6642c1f46dcSZachary Turner     }
6652c1f46dcSZachary Turner     return result;
6662c1f46dcSZachary Turner }
6672c1f46dcSZachary Turner 
6682c1f46dcSZachary Turner //----------------------------------------------------------------------
669a1405147SZachary Turner // PythonTuple
670a1405147SZachary Turner //----------------------------------------------------------------------
671a1405147SZachary Turner 
672a1405147SZachary Turner PythonTuple::PythonTuple(PyInitialValue value)
673a1405147SZachary Turner     : PythonObject()
674a1405147SZachary Turner {
675a1405147SZachary Turner     if (value == PyInitialValue::Empty)
676a1405147SZachary Turner         Reset(PyRefType::Owned, PyTuple_New(0));
677a1405147SZachary Turner }
678a1405147SZachary Turner 
679a1405147SZachary Turner PythonTuple::PythonTuple(int tuple_size)
680a1405147SZachary Turner     : PythonObject()
681a1405147SZachary Turner {
682a1405147SZachary Turner     Reset(PyRefType::Owned, PyTuple_New(tuple_size));
683a1405147SZachary Turner }
684a1405147SZachary Turner 
685a1405147SZachary Turner PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj)
686a1405147SZachary Turner     : PythonObject()
687a1405147SZachary Turner {
688a1405147SZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple
689a1405147SZachary Turner }
690a1405147SZachary Turner 
691a1405147SZachary Turner PythonTuple::PythonTuple(const PythonTuple &tuple)
692a1405147SZachary Turner     : PythonObject(tuple)
693a1405147SZachary Turner {
694a1405147SZachary Turner }
695a1405147SZachary Turner 
696a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects)
697a1405147SZachary Turner {
698a1405147SZachary Turner     m_py_obj = PyTuple_New(objects.size());
699a1405147SZachary Turner 
700a1405147SZachary Turner     uint32_t idx = 0;
701a1405147SZachary Turner     for (auto object : objects)
702a1405147SZachary Turner     {
703a1405147SZachary Turner         if (object.IsValid())
704a1405147SZachary Turner             SetItemAtIndex(idx, object);
705a1405147SZachary Turner         idx++;
706a1405147SZachary Turner     }
707a1405147SZachary Turner }
708a1405147SZachary Turner 
709a1405147SZachary Turner PythonTuple::PythonTuple(std::initializer_list<PyObject*> objects)
710a1405147SZachary Turner {
711a1405147SZachary Turner     m_py_obj = PyTuple_New(objects.size());
712a1405147SZachary Turner 
713a1405147SZachary Turner     uint32_t idx = 0;
714a1405147SZachary Turner     for (auto py_object : objects)
715a1405147SZachary Turner     {
716a1405147SZachary Turner         PythonObject object(PyRefType::Borrowed, py_object);
717a1405147SZachary Turner         if (object.IsValid())
718a1405147SZachary Turner             SetItemAtIndex(idx, object);
719a1405147SZachary Turner         idx++;
720a1405147SZachary Turner     }
721a1405147SZachary Turner }
722a1405147SZachary Turner 
723a1405147SZachary Turner PythonTuple::~PythonTuple()
724a1405147SZachary Turner {
725a1405147SZachary Turner }
726a1405147SZachary Turner 
727a1405147SZachary Turner bool
728a1405147SZachary Turner PythonTuple::Check(PyObject *py_obj)
729a1405147SZachary Turner {
730a1405147SZachary Turner     if (!py_obj)
731a1405147SZachary Turner         return false;
732a1405147SZachary Turner     return PyTuple_Check(py_obj);
733a1405147SZachary Turner }
734a1405147SZachary Turner 
735a1405147SZachary Turner void
736a1405147SZachary Turner PythonTuple::Reset(PyRefType type, PyObject *py_obj)
737a1405147SZachary Turner {
738a1405147SZachary Turner     // Grab the desired reference type so that if we end up rejecting
739a1405147SZachary Turner     // `py_obj` it still gets decremented if necessary.
740a1405147SZachary Turner     PythonObject result(type, py_obj);
741a1405147SZachary Turner 
742a1405147SZachary Turner     if (!PythonTuple::Check(py_obj))
743a1405147SZachary Turner     {
744a1405147SZachary Turner         PythonObject::Reset();
745a1405147SZachary Turner         return;
746a1405147SZachary Turner     }
747a1405147SZachary Turner 
748a1405147SZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
749a1405147SZachary Turner     // back into the virtual implementation.
750a1405147SZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
751a1405147SZachary Turner }
752a1405147SZachary Turner 
753a1405147SZachary Turner uint32_t
754a1405147SZachary Turner PythonTuple::GetSize() const
755a1405147SZachary Turner {
756a1405147SZachary Turner     if (IsValid())
757a1405147SZachary Turner         return PyTuple_GET_SIZE(m_py_obj);
758a1405147SZachary Turner     return 0;
759a1405147SZachary Turner }
760a1405147SZachary Turner 
761a1405147SZachary Turner PythonObject
762a1405147SZachary Turner PythonTuple::GetItemAtIndex(uint32_t index) const
763a1405147SZachary Turner {
764a1405147SZachary Turner     if (IsValid())
765a1405147SZachary Turner         return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
766a1405147SZachary Turner     return PythonObject();
767a1405147SZachary Turner }
768a1405147SZachary Turner 
769a1405147SZachary Turner void
770a1405147SZachary Turner PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object)
771a1405147SZachary Turner {
772a1405147SZachary Turner     if (IsAllocated() && object.IsValid())
773a1405147SZachary Turner     {
774a1405147SZachary Turner         // PyTuple_SetItem is documented to "steal" a reference, so we need to
775a1405147SZachary Turner         // convert it to an owned reference by incrementing it.
776a1405147SZachary Turner         Py_INCREF(object.get());
777a1405147SZachary Turner         PyTuple_SetItem(m_py_obj, index, object.get());
778a1405147SZachary Turner     }
779a1405147SZachary Turner }
780a1405147SZachary Turner 
781a1405147SZachary Turner StructuredData::ArraySP
782a1405147SZachary Turner PythonTuple::CreateStructuredArray() const
783a1405147SZachary Turner {
784a1405147SZachary Turner     StructuredData::ArraySP result(new StructuredData::Array);
785a1405147SZachary Turner     uint32_t count = GetSize();
786a1405147SZachary Turner     for (uint32_t i = 0; i < count; ++i)
787a1405147SZachary Turner     {
788a1405147SZachary Turner         PythonObject obj = GetItemAtIndex(i);
789a1405147SZachary Turner         result->AddItem(obj.CreateStructuredObject());
790a1405147SZachary Turner     }
791a1405147SZachary Turner     return result;
792a1405147SZachary Turner }
793a1405147SZachary Turner 
794a1405147SZachary Turner //----------------------------------------------------------------------
7952c1f46dcSZachary Turner // PythonDictionary
7962c1f46dcSZachary Turner //----------------------------------------------------------------------
7972c1f46dcSZachary Turner 
798f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyInitialValue value)
799f8b22f8fSZachary Turner     : PythonObject()
8002c1f46dcSZachary Turner {
801f8b22f8fSZachary Turner     if (value == PyInitialValue::Empty)
802f8b22f8fSZachary Turner         Reset(PyRefType::Owned, PyDict_New());
8032c1f46dcSZachary Turner }
8042c1f46dcSZachary Turner 
805f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
806f8b22f8fSZachary Turner     : PythonObject()
8072c1f46dcSZachary Turner {
808f8b22f8fSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
8092c1f46dcSZachary Turner }
8102c1f46dcSZachary Turner 
811f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object)
812f8b22f8fSZachary Turner     : PythonObject(object)
8132c1f46dcSZachary Turner {
8142c1f46dcSZachary Turner }
8152c1f46dcSZachary Turner 
8162c1f46dcSZachary Turner PythonDictionary::~PythonDictionary ()
8172c1f46dcSZachary Turner {
8182c1f46dcSZachary Turner }
8192c1f46dcSZachary Turner 
8202c1f46dcSZachary Turner bool
82122c8efcdSZachary Turner PythonDictionary::Check(PyObject *py_obj)
82222c8efcdSZachary Turner {
82322c8efcdSZachary Turner     if (!py_obj)
82422c8efcdSZachary Turner         return false;
82522c8efcdSZachary Turner 
82622c8efcdSZachary Turner     return PyDict_Check(py_obj);
82722c8efcdSZachary Turner }
82822c8efcdSZachary Turner 
829f8b22f8fSZachary Turner void
830f8b22f8fSZachary Turner PythonDictionary::Reset(PyRefType type, PyObject *py_obj)
8312c1f46dcSZachary Turner {
832f8b22f8fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
833f8b22f8fSZachary Turner     // `py_obj` it still gets decremented if necessary.
834f8b22f8fSZachary Turner     PythonObject result(type, py_obj);
835f8b22f8fSZachary Turner 
83622c8efcdSZachary Turner     if (!PythonDictionary::Check(py_obj))
83722c8efcdSZachary Turner     {
838f8b22f8fSZachary Turner         PythonObject::Reset();
839f8b22f8fSZachary Turner         return;
84022c8efcdSZachary Turner     }
84122c8efcdSZachary Turner 
842f8b22f8fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
843f8b22f8fSZachary Turner     // back into the virtual implementation.
844f8b22f8fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
8452c1f46dcSZachary Turner }
8462c1f46dcSZachary Turner 
8472c1f46dcSZachary Turner uint32_t
8482c1f46dcSZachary Turner PythonDictionary::GetSize() const
8492c1f46dcSZachary Turner {
850f8b22f8fSZachary Turner     if (IsValid())
8512c1f46dcSZachary Turner         return PyDict_Size(m_py_obj);
8522c1f46dcSZachary Turner     return 0;
8532c1f46dcSZachary Turner }
8542c1f46dcSZachary Turner 
8552c1f46dcSZachary Turner PythonList
8562c1f46dcSZachary Turner PythonDictionary::GetKeys() const
8572c1f46dcSZachary Turner {
858f8b22f8fSZachary Turner     if (IsValid())
859f8b22f8fSZachary Turner         return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
860f8b22f8fSZachary Turner     return PythonList(PyInitialValue::Invalid);
8612c1f46dcSZachary Turner }
8622c1f46dcSZachary Turner 
8632c1f46dcSZachary Turner PythonObject
864f8b22f8fSZachary Turner PythonDictionary::GetItemForKey(const PythonObject &key) const
8652c1f46dcSZachary Turner {
866f8b22f8fSZachary Turner     if (IsAllocated() && key.IsValid())
867f8b22f8fSZachary Turner         return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get()));
8682c1f46dcSZachary Turner     return PythonObject();
8692c1f46dcSZachary Turner }
8702c1f46dcSZachary Turner 
8712c1f46dcSZachary Turner void
872f8b22f8fSZachary Turner PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value)
8732c1f46dcSZachary Turner {
874f8b22f8fSZachary Turner     if (IsAllocated() && key.IsValid() && value.IsValid())
8752c1f46dcSZachary Turner         PyDict_SetItem(m_py_obj, key.get(), value.get());
8762c1f46dcSZachary Turner }
8772c1f46dcSZachary Turner 
8782c1f46dcSZachary Turner StructuredData::DictionarySP
8792c1f46dcSZachary Turner PythonDictionary::CreateStructuredDictionary() const
8802c1f46dcSZachary Turner {
8812c1f46dcSZachary Turner     StructuredData::DictionarySP result(new StructuredData::Dictionary);
8822c1f46dcSZachary Turner     PythonList keys(GetKeys());
8832c1f46dcSZachary Turner     uint32_t num_keys = keys.GetSize();
8842c1f46dcSZachary Turner     for (uint32_t i = 0; i < num_keys; ++i)
8852c1f46dcSZachary Turner     {
8862c1f46dcSZachary Turner         PythonObject key = keys.GetItemAtIndex(i);
8872c1f46dcSZachary Turner         PythonObject value = GetItemForKey(key);
8882c1f46dcSZachary Turner         StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
889f8b22f8fSZachary Turner         result->AddItem(key.Str().GetString(), structured_value);
8902c1f46dcSZachary Turner     }
8912c1f46dcSZachary Turner     return result;
8922c1f46dcSZachary Turner }
8932c1f46dcSZachary Turner 
8947841efbbSZachary Turner PythonModule::PythonModule() : PythonObject()
8957841efbbSZachary Turner {
8967841efbbSZachary Turner }
8977841efbbSZachary Turner 
8987841efbbSZachary Turner PythonModule::PythonModule(PyRefType type, PyObject *py_obj)
8997841efbbSZachary Turner {
9007841efbbSZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
9017841efbbSZachary Turner }
9027841efbbSZachary Turner 
9037841efbbSZachary Turner PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict)
9047841efbbSZachary Turner {
9057841efbbSZachary Turner }
9067841efbbSZachary Turner 
9077841efbbSZachary Turner PythonModule::~PythonModule()
9087841efbbSZachary Turner {
9097841efbbSZachary Turner }
9107841efbbSZachary Turner 
9117841efbbSZachary Turner PythonModule
912a1405147SZachary Turner PythonModule::BuiltinsModule()
913a1405147SZachary Turner {
914a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3
915a1405147SZachary Turner     return AddModule("builtins");
916a1405147SZachary Turner #else
917a1405147SZachary Turner     return AddModule("__builtin__");
918a1405147SZachary Turner #endif
919a1405147SZachary Turner }
920a1405147SZachary Turner 
921a1405147SZachary Turner PythonModule
9227841efbbSZachary Turner PythonModule::MainModule()
9237841efbbSZachary Turner {
924a1405147SZachary Turner     return AddModule("__main__");
925a1405147SZachary Turner }
926a1405147SZachary Turner 
927a1405147SZachary Turner PythonModule
928a1405147SZachary Turner PythonModule::AddModule(llvm::StringRef module)
929a1405147SZachary Turner {
930a1405147SZachary Turner     std::string str = module.str();
931a1405147SZachary Turner     return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
9327841efbbSZachary Turner }
9337841efbbSZachary Turner 
9342419f1d5SZachary Turner 
9352419f1d5SZachary Turner PythonModule
9362419f1d5SZachary Turner PythonModule::ImportModule(llvm::StringRef module)
9372419f1d5SZachary Turner {
9382419f1d5SZachary Turner     std::string str = module.str();
9392419f1d5SZachary Turner     return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str()));
9402419f1d5SZachary Turner }
9412419f1d5SZachary Turner 
9427841efbbSZachary Turner bool
9437841efbbSZachary Turner PythonModule::Check(PyObject *py_obj)
9447841efbbSZachary Turner {
9457841efbbSZachary Turner     if (!py_obj)
9467841efbbSZachary Turner         return false;
9477841efbbSZachary Turner 
9487841efbbSZachary Turner     return PyModule_Check(py_obj);
9497841efbbSZachary Turner }
9507841efbbSZachary Turner 
9517841efbbSZachary Turner void
9527841efbbSZachary Turner PythonModule::Reset(PyRefType type, PyObject *py_obj)
9537841efbbSZachary Turner {
9547841efbbSZachary Turner     // Grab the desired reference type so that if we end up rejecting
9557841efbbSZachary Turner     // `py_obj` it still gets decremented if necessary.
9567841efbbSZachary Turner     PythonObject result(type, py_obj);
9577841efbbSZachary Turner 
9587841efbbSZachary Turner     if (!PythonModule::Check(py_obj))
9597841efbbSZachary Turner     {
9607841efbbSZachary Turner         PythonObject::Reset();
9617841efbbSZachary Turner         return;
9627841efbbSZachary Turner     }
9637841efbbSZachary Turner 
9647841efbbSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
9657841efbbSZachary Turner     // back into the virtual implementation.
9667841efbbSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
9677841efbbSZachary Turner }
9687841efbbSZachary Turner 
9697841efbbSZachary Turner PythonDictionary
9707841efbbSZachary Turner PythonModule::GetDictionary() const
9717841efbbSZachary Turner {
9727841efbbSZachary Turner     return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
9737841efbbSZachary Turner }
9747841efbbSZachary Turner 
975a1405147SZachary Turner PythonCallable::PythonCallable() : PythonObject()
976a1405147SZachary Turner {
977a1405147SZachary Turner }
978a1405147SZachary Turner 
979a1405147SZachary Turner PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj)
980a1405147SZachary Turner {
981a1405147SZachary Turner     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable
982a1405147SZachary Turner }
983a1405147SZachary Turner 
984a1405147SZachary Turner PythonCallable::PythonCallable(const PythonCallable &callable)
985a1405147SZachary Turner     : PythonObject(callable)
986a1405147SZachary Turner {
987a1405147SZachary Turner }
988a1405147SZachary Turner 
989a1405147SZachary Turner PythonCallable::~PythonCallable()
990a1405147SZachary Turner {
991a1405147SZachary Turner }
992a1405147SZachary Turner 
993a1405147SZachary Turner bool
994a1405147SZachary Turner PythonCallable::Check(PyObject *py_obj)
995a1405147SZachary Turner {
996a1405147SZachary Turner     if (!py_obj)
997a1405147SZachary Turner         return false;
998a1405147SZachary Turner 
999a1405147SZachary Turner     return PyCallable_Check(py_obj);
1000a1405147SZachary Turner }
1001a1405147SZachary Turner 
1002a1405147SZachary Turner void
1003a1405147SZachary Turner PythonCallable::Reset(PyRefType type, PyObject *py_obj)
1004a1405147SZachary Turner {
1005a1405147SZachary Turner     // Grab the desired reference type so that if we end up rejecting
1006a1405147SZachary Turner     // `py_obj` it still gets decremented if necessary.
1007a1405147SZachary Turner     PythonObject result(type, py_obj);
1008a1405147SZachary Turner 
1009a1405147SZachary Turner     if (!PythonCallable::Check(py_obj))
1010a1405147SZachary Turner     {
1011a1405147SZachary Turner         PythonObject::Reset();
1012a1405147SZachary Turner         return;
1013a1405147SZachary Turner     }
1014a1405147SZachary Turner 
1015a1405147SZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
1016a1405147SZachary Turner     // back into the virtual implementation.
1017a1405147SZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
1018a1405147SZachary Turner }
1019a1405147SZachary Turner 
1020a1405147SZachary Turner 
1021b58fb2f4SZachary Turner PythonCallable::ArgInfo
1022b58fb2f4SZachary Turner PythonCallable::GetNumArguments() const
1023a1405147SZachary Turner {
1024b58fb2f4SZachary Turner     ArgInfo result = { 0, false, false };
1025a1405147SZachary Turner     if (!IsValid())
1026b58fb2f4SZachary Turner         return result;
1027a1405147SZachary Turner 
1028a1405147SZachary Turner     PyObject *py_func_obj = m_py_obj;
1029a1405147SZachary Turner     if (PyMethod_Check(py_func_obj))
1030a1405147SZachary Turner         py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
1031a1405147SZachary Turner 
1032a1405147SZachary Turner     if (!py_func_obj)
1033b58fb2f4SZachary Turner         return result;
1034a1405147SZachary Turner 
1035a1405147SZachary Turner     PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj);
1036a1405147SZachary Turner     if (!code)
1037b58fb2f4SZachary Turner         return result;
1038a1405147SZachary Turner 
1039b58fb2f4SZachary Turner     result.count = code->co_argcount;
1040b58fb2f4SZachary Turner     result.has_varargs = !!(code->co_flags & CO_VARARGS);
1041b58fb2f4SZachary Turner     result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS);
1042b58fb2f4SZachary Turner     return result;
1043b58fb2f4SZachary Turner }
1044b58fb2f4SZachary Turner 
1045b58fb2f4SZachary Turner PythonObject
1046b58fb2f4SZachary Turner PythonCallable::operator ()()
1047b58fb2f4SZachary Turner {
1048b58fb2f4SZachary Turner     return PythonObject(PyRefType::Owned,
1049b58fb2f4SZachary Turner         PyObject_CallObject(m_py_obj, nullptr));
1050a1405147SZachary Turner }
1051a1405147SZachary Turner 
1052a1405147SZachary Turner PythonObject
1053a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PyObject*> args)
1054a1405147SZachary Turner {
1055a1405147SZachary Turner     PythonTuple arg_tuple(args);
1056a1405147SZachary Turner     return PythonObject(PyRefType::Owned,
1057a1405147SZachary Turner         PyObject_CallObject(m_py_obj, arg_tuple.get()));
1058a1405147SZachary Turner }
1059a1405147SZachary Turner 
1060a1405147SZachary Turner PythonObject
1061a1405147SZachary Turner PythonCallable::operator ()(std::initializer_list<PythonObject> args)
1062a1405147SZachary Turner {
1063a1405147SZachary Turner     PythonTuple arg_tuple(args);
1064a1405147SZachary Turner     return PythonObject(PyRefType::Owned,
1065a1405147SZachary Turner         PyObject_CallObject(m_py_obj, arg_tuple.get()));
1066a1405147SZachary Turner }
1067a1405147SZachary Turner 
106832064024SZachary Turner PythonFile::PythonFile()
106932064024SZachary Turner     : PythonObject()
107032064024SZachary Turner {
107132064024SZachary Turner }
107232064024SZachary Turner 
10739c40264fSZachary Turner PythonFile::PythonFile(File &file, const char *mode)
10749c40264fSZachary Turner {
10759c40264fSZachary Turner     Reset(file, mode);
10769c40264fSZachary Turner }
10779c40264fSZachary Turner 
1078eda01c31SZachary Turner PythonFile::PythonFile(const char *path, const char *mode)
1079eda01c31SZachary Turner {
1080eda01c31SZachary Turner     FILE *fp = nullptr;
1081eda01c31SZachary Turner     fp = fopen(path, mode);
1082eda01c31SZachary Turner     lldb_private::File file(fp, true);
1083eda01c31SZachary Turner     Reset(file, mode);
1084eda01c31SZachary Turner }
1085eda01c31SZachary Turner 
10869c40264fSZachary Turner PythonFile::PythonFile(PyRefType type, PyObject *o)
10879c40264fSZachary Turner {
10889c40264fSZachary Turner     Reset(type, o);
10899c40264fSZachary Turner }
10909c40264fSZachary Turner 
10919c40264fSZachary Turner PythonFile::~PythonFile()
10929c40264fSZachary Turner {
10939c40264fSZachary Turner }
10949c40264fSZachary Turner 
10959c40264fSZachary Turner bool
10969c40264fSZachary Turner PythonFile::Check(PyObject *py_obj)
10979c40264fSZachary Turner {
10989c40264fSZachary Turner #if PY_MAJOR_VERSION < 3
10999c40264fSZachary Turner     return PyFile_Check(py_obj);
11009c40264fSZachary Turner #else
11019c40264fSZachary Turner     // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
11029c40264fSZachary Turner     // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
11039c40264fSZachary Turner     // over `io.open()`, which returns some object derived from `io.IOBase`.
11049c40264fSZachary Turner     // As a result, the only way to detect a file in Python 3 is to check whether
11059c40264fSZachary Turner     // it inherits from `io.IOBase`.  Since it is possible for non-files to also
11069c40264fSZachary Turner     // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
11079c40264fSZachary Turner     // attribute, which should guarantee that it is backed by the file system.
11089c40264fSZachary Turner     PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
11099c40264fSZachary Turner     PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get()));
11109c40264fSZachary Turner     PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
11119c40264fSZachary Turner 
11129c40264fSZachary Turner     PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
11139c40264fSZachary Turner 
11149c40264fSZachary Turner     if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
11159c40264fSZachary Turner         return false;
11169c40264fSZachary Turner     if (!object_type.HasAttribute("fileno"))
11179c40264fSZachary Turner         return false;
11189c40264fSZachary Turner 
11199c40264fSZachary Turner     return true;
11209c40264fSZachary Turner #endif
11219c40264fSZachary Turner }
11229c40264fSZachary Turner 
11239c40264fSZachary Turner void
11249c40264fSZachary Turner PythonFile::Reset(PyRefType type, PyObject *py_obj)
11259c40264fSZachary Turner {
11269c40264fSZachary Turner     // Grab the desired reference type so that if we end up rejecting
11279c40264fSZachary Turner     // `py_obj` it still gets decremented if necessary.
11289c40264fSZachary Turner     PythonObject result(type, py_obj);
11299c40264fSZachary Turner 
11309c40264fSZachary Turner     if (!PythonFile::Check(py_obj))
11319c40264fSZachary Turner     {
11329c40264fSZachary Turner         PythonObject::Reset();
11339c40264fSZachary Turner         return;
11349c40264fSZachary Turner     }
11359c40264fSZachary Turner 
11369c40264fSZachary Turner     // Calling PythonObject::Reset(const PythonObject&) will lead to stack
11379c40264fSZachary Turner     // overflow since it calls back into the virtual implementation.
11389c40264fSZachary Turner     PythonObject::Reset(PyRefType::Borrowed, result.get());
11399c40264fSZachary Turner }
11409c40264fSZachary Turner 
11419c40264fSZachary Turner void
11429c40264fSZachary Turner PythonFile::Reset(File &file, const char *mode)
11439c40264fSZachary Turner {
114432ac147bSZachary Turner     if (!file.IsValid())
114532ac147bSZachary Turner     {
114632ac147bSZachary Turner         Reset();
114732ac147bSZachary Turner         return;
114832ac147bSZachary Turner     }
114932ac147bSZachary Turner 
11509c40264fSZachary Turner     char *cmode = const_cast<char *>(mode);
11519c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3
11529c40264fSZachary Turner     Reset(PyRefType::Owned,
11539c40264fSZachary Turner         PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0));
11549c40264fSZachary Turner #else
11559c40264fSZachary Turner     // Read through the Python source, doesn't seem to modify these strings
11569c40264fSZachary Turner     Reset(PyRefType::Owned,
11579c40264fSZachary Turner         PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr));
11589c40264fSZachary Turner #endif
11599c40264fSZachary Turner }
11609c40264fSZachary Turner 
1161*744959b9SEnrico Granata uint32_t
1162*744959b9SEnrico Granata PythonFile::GetOptionsFromMode(llvm::StringRef mode)
1163*744959b9SEnrico Granata {
1164*744959b9SEnrico Granata     if (mode.empty())
1165*744959b9SEnrico Granata         return 0;
1166*744959b9SEnrico Granata 
1167*744959b9SEnrico Granata     return llvm::StringSwitch<uint32_t>(mode.str().c_str())
1168*744959b9SEnrico Granata     .Case("r",   File::eOpenOptionRead)
1169*744959b9SEnrico Granata     .Case("w",   File::eOpenOptionWrite)
1170*744959b9SEnrico Granata     .Case("a",   File::eOpenOptionAppend|File::eOpenOptionCanCreate)
1171*744959b9SEnrico Granata     .Case("r+",  File::eOpenOptionRead|File::eOpenOptionWrite)
1172*744959b9SEnrico Granata     .Case("w+",  File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionCanCreate|File::eOpenOptionTruncate)
1173*744959b9SEnrico Granata     .Case("a+",  File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionCanCreate)
1174*744959b9SEnrico Granata     .Default(0);
1175*744959b9SEnrico Granata }
1176*744959b9SEnrico Granata 
1177eda01c31SZachary Turner bool
1178eda01c31SZachary Turner PythonFile::GetUnderlyingFile(File &file) const
1179eda01c31SZachary Turner {
1180eda01c31SZachary Turner     if (!IsValid())
1181eda01c31SZachary Turner         return false;
1182eda01c31SZachary Turner 
1183eda01c31SZachary Turner     file.Close();
1184eda01c31SZachary Turner     // We don't own the file descriptor returned by this function, make sure the
1185eda01c31SZachary Turner     // File object knows about that.
1186eda01c31SZachary Turner     file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
1187*744959b9SEnrico Granata     PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>();
1188*744959b9SEnrico Granata     file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString()));
1189eda01c31SZachary Turner     return file.IsValid();
1190eda01c31SZachary Turner }
1191eda01c31SZachary Turner 
1192eda01c31SZachary Turner 
11932c1f46dcSZachary Turner #endif
1194