1bcadb5a3SPavel Labath //===-- PythonDataObjects.cpp -----------------------------------*- C++ -*-===//
22c1f46dcSZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62c1f46dcSZachary Turner //
72c1f46dcSZachary Turner //===----------------------------------------------------------------------===//
82c1f46dcSZachary Turner 
9d68983e3SPavel Labath #ifdef LLDB_DISABLE_PYTHON
10d68983e3SPavel Labath 
11d68983e3SPavel Labath // Python is disabled in this build
12d68983e3SPavel Labath 
13d68983e3SPavel Labath #else
14d68983e3SPavel Labath 
152c1f46dcSZachary Turner #include "PythonDataObjects.h"
162c1f46dcSZachary Turner #include "ScriptInterpreterPython.h"
172c1f46dcSZachary Turner 
182c1f46dcSZachary Turner #include "lldb/Host/File.h"
19190fadcdSZachary Turner #include "lldb/Host/FileSystem.h"
202c1f46dcSZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h"
21bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
222c1f46dcSZachary Turner 
23190fadcdSZachary Turner #include "llvm/Support/ConvertUTF.h"
24*2819136fSMichal Gorny #include "llvm/Support/Errno.h"
25190fadcdSZachary Turner 
262c1f46dcSZachary Turner #include <stdio.h>
272c1f46dcSZachary Turner 
28744959b9SEnrico Granata #include "llvm/ADT/StringSwitch.h"
29744959b9SEnrico Granata 
302c1f46dcSZachary Turner using namespace lldb_private;
312c1f46dcSZachary Turner using namespace lldb;
322c1f46dcSZachary Turner 
33b9c1b51eSKate Stone void StructuredPythonObject::Dump(Stream &s, bool pretty_print) const {
342c1f46dcSZachary Turner   s << "Python Obj: 0x" << GetValue();
352c1f46dcSZachary Turner }
362c1f46dcSZachary Turner 
372c1f46dcSZachary Turner //----------------------------------------------------------------------
382c1f46dcSZachary Turner // PythonObject
392c1f46dcSZachary Turner //----------------------------------------------------------------------
402c1f46dcSZachary Turner 
41b9c1b51eSKate Stone void PythonObject::Dump(Stream &strm) const {
42b9c1b51eSKate Stone   if (m_py_obj) {
43*2819136fSMichal Gorny     FILE *file = llvm::sys::RetryAfterSignal(nullptr, ::tmpfile);
44b9c1b51eSKate Stone     if (file) {
452c1f46dcSZachary Turner       ::PyObject_Print(m_py_obj, file, 0);
462c1f46dcSZachary Turner       const long length = ftell(file);
47b9c1b51eSKate Stone       if (length) {
482c1f46dcSZachary Turner         ::rewind(file);
492c1f46dcSZachary Turner         std::vector<char> file_contents(length, '\0');
50b9c1b51eSKate Stone         const size_t length_read =
51b9c1b51eSKate Stone             ::fread(file_contents.data(), 1, file_contents.size(), file);
522c1f46dcSZachary Turner         if (length_read > 0)
532c1f46dcSZachary Turner           strm.Write(file_contents.data(), length_read);
542c1f46dcSZachary Turner       }
552c1f46dcSZachary Turner       ::fclose(file);
562c1f46dcSZachary Turner     }
57b9c1b51eSKate Stone   } else
582c1f46dcSZachary Turner     strm.PutCString("NULL");
592c1f46dcSZachary Turner }
602c1f46dcSZachary Turner 
61b9c1b51eSKate Stone PyObjectType PythonObject::GetObjectType() const {
62f8b22f8fSZachary Turner   if (!IsAllocated())
632c1f46dcSZachary Turner     return PyObjectType::None;
642c1f46dcSZachary Turner 
657841efbbSZachary Turner   if (PythonModule::Check(m_py_obj))
667841efbbSZachary Turner     return PyObjectType::Module;
6718426935SZachary Turner   if (PythonList::Check(m_py_obj))
682c1f46dcSZachary Turner     return PyObjectType::List;
69a1405147SZachary Turner   if (PythonTuple::Check(m_py_obj))
70a1405147SZachary Turner     return PyObjectType::Tuple;
7118426935SZachary Turner   if (PythonDictionary::Check(m_py_obj))
722c1f46dcSZachary Turner     return PyObjectType::Dictionary;
7318426935SZachary Turner   if (PythonString::Check(m_py_obj))
7422c8efcdSZachary Turner     return PyObjectType::String;
755a72c02bSZachary Turner #if PY_MAJOR_VERSION >= 3
765a72c02bSZachary Turner   if (PythonBytes::Check(m_py_obj))
775a72c02bSZachary Turner     return PyObjectType::Bytes;
785a72c02bSZachary Turner #endif
79f9d6d204SZachary Turner   if (PythonByteArray::Check(m_py_obj))
80f9d6d204SZachary Turner     return PyObjectType::ByteArray;
81b81d715cSTatyana Krasnukha   if (PythonBoolean::Check(m_py_obj))
82b81d715cSTatyana Krasnukha     return PyObjectType::Boolean;
8318426935SZachary Turner   if (PythonInteger::Check(m_py_obj))
8422c8efcdSZachary Turner     return PyObjectType::Integer;
859c40264fSZachary Turner   if (PythonFile::Check(m_py_obj))
869c40264fSZachary Turner     return PyObjectType::File;
87a1405147SZachary Turner   if (PythonCallable::Check(m_py_obj))
88a1405147SZachary Turner     return PyObjectType::Callable;
892c1f46dcSZachary Turner   return PyObjectType::Unknown;
902c1f46dcSZachary Turner }
912c1f46dcSZachary Turner 
92b9c1b51eSKate Stone PythonString PythonObject::Repr() const {
932c1f46dcSZachary Turner   if (!m_py_obj)
942c1f46dcSZachary Turner     return PythonString();
952c1f46dcSZachary Turner   PyObject *repr = PyObject_Repr(m_py_obj);
962c1f46dcSZachary Turner   if (!repr)
972c1f46dcSZachary Turner     return PythonString();
98f8b22f8fSZachary Turner   return PythonString(PyRefType::Owned, repr);
992c1f46dcSZachary Turner }
1002c1f46dcSZachary Turner 
101b9c1b51eSKate Stone PythonString PythonObject::Str() const {
1022c1f46dcSZachary Turner   if (!m_py_obj)
1032c1f46dcSZachary Turner     return PythonString();
1042c1f46dcSZachary Turner   PyObject *str = PyObject_Str(m_py_obj);
1052c1f46dcSZachary Turner   if (!str)
1062c1f46dcSZachary Turner     return PythonString();
107f8b22f8fSZachary Turner   return PythonString(PyRefType::Owned, str);
1082c1f46dcSZachary Turner }
1092c1f46dcSZachary Turner 
1107841efbbSZachary Turner PythonObject
111b9c1b51eSKate Stone PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
112b9c1b51eSKate Stone                                         const PythonDictionary &dict) {
113a1405147SZachary Turner   size_t dot_pos = name.find_first_of('.');
114a1405147SZachary Turner   llvm::StringRef piece = name.substr(0, dot_pos);
115a1405147SZachary Turner   PythonObject result = dict.GetItemForKey(PythonString(piece));
116b9c1b51eSKate Stone   if (dot_pos == llvm::StringRef::npos) {
117a1405147SZachary Turner     // There was no dot, we're done.
118a1405147SZachary Turner     return result;
119a1405147SZachary Turner   }
120a1405147SZachary Turner 
121a1405147SZachary Turner   // There was a dot.  The remaining portion of the name should be looked up in
122a1405147SZachary Turner   // the context of the object that was found in the dictionary.
123a1405147SZachary Turner   return result.ResolveName(name.substr(dot_pos + 1));
1247841efbbSZachary Turner }
1257841efbbSZachary Turner 
126b9c1b51eSKate Stone PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
12705097246SAdrian Prantl   // Resolve the name in the context of the specified object.  If, for example,
12805097246SAdrian Prantl   // `this` refers to a PyModule, then this will look for `name` in this
12905097246SAdrian Prantl   // module.  If `this` refers to a PyType, then it will resolve `name` as an
13005097246SAdrian Prantl   // attribute of that type.  If `this` refers to an instance of an object,
13105097246SAdrian Prantl   // then it will resolve `name` as the value of the specified field.
1327841efbbSZachary Turner   //
1337841efbbSZachary Turner   // This function handles dotted names so that, for example, if `m_py_obj`
13405097246SAdrian Prantl   // refers to the `sys` module, and `name` == "path.append", then it will find
13505097246SAdrian Prantl   // the function `sys.path.append`.
1367841efbbSZachary Turner 
1377841efbbSZachary Turner   size_t dot_pos = name.find_first_of('.');
138b9c1b51eSKate Stone   if (dot_pos == llvm::StringRef::npos) {
13905097246SAdrian Prantl     // No dots in the name, we should be able to find the value immediately as
14005097246SAdrian Prantl     // an attribute of `m_py_obj`.
1417841efbbSZachary Turner     return GetAttributeValue(name);
1427841efbbSZachary Turner   }
1437841efbbSZachary Turner 
144b9c1b51eSKate Stone   // Look up the first piece of the name, and resolve the rest as a child of
145b9c1b51eSKate Stone   // that.
1467841efbbSZachary Turner   PythonObject parent = ResolveName(name.substr(0, dot_pos));
1477841efbbSZachary Turner   if (!parent.IsAllocated())
1487841efbbSZachary Turner     return PythonObject();
1497841efbbSZachary Turner 
1507841efbbSZachary Turner   // Tail recursion.. should be optimized by the compiler
1517841efbbSZachary Turner   return parent.ResolveName(name.substr(dot_pos + 1));
1527841efbbSZachary Turner }
1537841efbbSZachary Turner 
154b9c1b51eSKate Stone bool PythonObject::HasAttribute(llvm::StringRef attr) const {
1559c40264fSZachary Turner   if (!IsValid())
1569c40264fSZachary Turner     return false;
1579c40264fSZachary Turner   PythonString py_attr(attr);
1589c40264fSZachary Turner   return !!PyObject_HasAttr(m_py_obj, py_attr.get());
1599c40264fSZachary Turner }
1609c40264fSZachary Turner 
161b9c1b51eSKate Stone PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const {
1627d6d218eSZachary Turner   if (!IsValid())
1637d6d218eSZachary Turner     return PythonObject();
1647d6d218eSZachary Turner 
1657d6d218eSZachary Turner   PythonString py_attr(attr);
1667d6d218eSZachary Turner   if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
1677d6d218eSZachary Turner     return PythonObject();
1687d6d218eSZachary Turner 
1697d6d218eSZachary Turner   return PythonObject(PyRefType::Owned,
1707d6d218eSZachary Turner                       PyObject_GetAttr(m_py_obj, py_attr.get()));
1717d6d218eSZachary Turner }
1727d6d218eSZachary Turner 
173b9c1b51eSKate Stone bool PythonObject::IsNone() const { return m_py_obj == Py_None; }
174f8b22f8fSZachary Turner 
175b9c1b51eSKate Stone bool PythonObject::IsValid() const { return m_py_obj != nullptr; }
176f8b22f8fSZachary Turner 
177b9c1b51eSKate Stone bool PythonObject::IsAllocated() const { return IsValid() && !IsNone(); }
1782c1f46dcSZachary Turner 
179b9c1b51eSKate Stone StructuredData::ObjectSP PythonObject::CreateStructuredObject() const {
180b9c1b51eSKate Stone   switch (GetObjectType()) {
1812c1f46dcSZachary Turner   case PyObjectType::Dictionary:
182b9c1b51eSKate Stone     return PythonDictionary(PyRefType::Borrowed, m_py_obj)
183b9c1b51eSKate Stone         .CreateStructuredDictionary();
184b81d715cSTatyana Krasnukha   case PyObjectType::Boolean:
185b81d715cSTatyana Krasnukha     return PythonBoolean(PyRefType::Borrowed, m_py_obj)
186b81d715cSTatyana Krasnukha         .CreateStructuredBoolean();
1872c1f46dcSZachary Turner   case PyObjectType::Integer:
188b9c1b51eSKate Stone     return PythonInteger(PyRefType::Borrowed, m_py_obj)
189b9c1b51eSKate Stone         .CreateStructuredInteger();
1902c1f46dcSZachary Turner   case PyObjectType::List:
191f8b22f8fSZachary Turner     return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
1922c1f46dcSZachary Turner   case PyObjectType::String:
193f8b22f8fSZachary Turner     return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
1945a72c02bSZachary Turner   case PyObjectType::Bytes:
1955a72c02bSZachary Turner     return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
196f9d6d204SZachary Turner   case PyObjectType::ByteArray:
197b9c1b51eSKate Stone     return PythonByteArray(PyRefType::Borrowed, m_py_obj)
198b9c1b51eSKate Stone         .CreateStructuredString();
1992c1f46dcSZachary Turner   case PyObjectType::None:
2002c1f46dcSZachary Turner     return StructuredData::ObjectSP();
2012c1f46dcSZachary Turner   default:
2022c1f46dcSZachary Turner     return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
2032c1f46dcSZachary Turner   }
2042c1f46dcSZachary Turner }
2052c1f46dcSZachary Turner 
2062c1f46dcSZachary Turner //----------------------------------------------------------------------
2072c1f46dcSZachary Turner // PythonString
2082c1f46dcSZachary Turner //----------------------------------------------------------------------
209b9c1b51eSKate Stone PythonBytes::PythonBytes() : PythonObject() {}
2105a72c02bSZachary Turner 
211b9c1b51eSKate Stone PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() {
2125a72c02bSZachary Turner   SetBytes(bytes);
2135a72c02bSZachary Turner }
2145a72c02bSZachary Turner 
215b9c1b51eSKate Stone PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() {
2165a72c02bSZachary Turner   SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
2175a72c02bSZachary Turner }
2185a72c02bSZachary Turner 
219b9c1b51eSKate Stone PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() {
2205a72c02bSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
2215a72c02bSZachary Turner }
2225a72c02bSZachary Turner 
223b9c1b51eSKate Stone PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object) {}
2245a72c02bSZachary Turner 
225b9c1b51eSKate Stone PythonBytes::~PythonBytes() {}
2265a72c02bSZachary Turner 
227b9c1b51eSKate Stone bool PythonBytes::Check(PyObject *py_obj) {
2285a72c02bSZachary Turner   if (!py_obj)
2295a72c02bSZachary Turner     return false;
230a6682a41SJonas Devlieghere   return PyBytes_Check(py_obj);
2315a72c02bSZachary Turner }
2325a72c02bSZachary Turner 
233b9c1b51eSKate Stone void PythonBytes::Reset(PyRefType type, PyObject *py_obj) {
23405097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
23505097246SAdrian Prantl   // still gets decremented if necessary.
2365a72c02bSZachary Turner   PythonObject result(type, py_obj);
2375a72c02bSZachary Turner 
238b9c1b51eSKate Stone   if (!PythonBytes::Check(py_obj)) {
2395a72c02bSZachary Turner     PythonObject::Reset();
2405a72c02bSZachary Turner     return;
2415a72c02bSZachary Turner   }
2425a72c02bSZachary Turner 
243b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
24405097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
2455a72c02bSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
2465a72c02bSZachary Turner }
2475a72c02bSZachary Turner 
248b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const {
2495a72c02bSZachary Turner   if (!IsValid())
2505a72c02bSZachary Turner     return llvm::ArrayRef<uint8_t>();
2515a72c02bSZachary Turner 
2525a72c02bSZachary Turner   Py_ssize_t size;
2535a72c02bSZachary Turner   char *c;
2545a72c02bSZachary Turner 
2555a72c02bSZachary Turner   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2565a72c02bSZachary Turner   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
2575a72c02bSZachary Turner }
2585a72c02bSZachary Turner 
259b9c1b51eSKate Stone size_t PythonBytes::GetSize() const {
2605a72c02bSZachary Turner   if (!IsValid())
2615a72c02bSZachary Turner     return 0;
2625a72c02bSZachary Turner   return PyBytes_Size(m_py_obj);
2635a72c02bSZachary Turner }
2645a72c02bSZachary Turner 
265b9c1b51eSKate Stone void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) {
2665a72c02bSZachary Turner   const char *data = reinterpret_cast<const char *>(bytes.data());
2675a72c02bSZachary Turner   PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
2685a72c02bSZachary Turner   PythonObject::Reset(PyRefType::Owned, py_bytes);
2695a72c02bSZachary Turner }
2705a72c02bSZachary Turner 
271b9c1b51eSKate Stone StructuredData::StringSP PythonBytes::CreateStructuredString() const {
2725a72c02bSZachary Turner   StructuredData::StringSP result(new StructuredData::String);
2735a72c02bSZachary Turner   Py_ssize_t size;
2745a72c02bSZachary Turner   char *c;
2755a72c02bSZachary Turner   PyBytes_AsStringAndSize(m_py_obj, &c, &size);
2765a72c02bSZachary Turner   result->SetValue(std::string(c, size));
2775a72c02bSZachary Turner   return result;
2785a72c02bSZachary Turner }
2795a72c02bSZachary Turner 
280b9c1b51eSKate Stone PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes)
281b9c1b51eSKate Stone     : PythonByteArray(bytes.data(), bytes.size()) {}
282f9d6d204SZachary Turner 
283b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) {
284f9d6d204SZachary Turner   const char *str = reinterpret_cast<const char *>(bytes);
285f9d6d204SZachary Turner   Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length));
286f9d6d204SZachary Turner }
287f9d6d204SZachary Turner 
288b9c1b51eSKate Stone PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) {
289f9d6d204SZachary Turner   Reset(type, o);
290f9d6d204SZachary Turner }
291f9d6d204SZachary Turner 
292b9c1b51eSKate Stone PythonByteArray::PythonByteArray(const PythonBytes &object)
293b9c1b51eSKate Stone     : PythonObject(object) {}
294f9d6d204SZachary Turner 
295b9c1b51eSKate Stone PythonByteArray::~PythonByteArray() {}
296f9d6d204SZachary Turner 
297b9c1b51eSKate Stone bool PythonByteArray::Check(PyObject *py_obj) {
298f9d6d204SZachary Turner   if (!py_obj)
299f9d6d204SZachary Turner     return false;
300a6682a41SJonas Devlieghere   return PyByteArray_Check(py_obj);
301f9d6d204SZachary Turner }
302f9d6d204SZachary Turner 
303b9c1b51eSKate Stone void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) {
30405097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
30505097246SAdrian Prantl   // still gets decremented if necessary.
306f9d6d204SZachary Turner   PythonObject result(type, py_obj);
307f9d6d204SZachary Turner 
308b9c1b51eSKate Stone   if (!PythonByteArray::Check(py_obj)) {
309f9d6d204SZachary Turner     PythonObject::Reset();
310f9d6d204SZachary Turner     return;
311f9d6d204SZachary Turner   }
312f9d6d204SZachary Turner 
313b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
31405097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
315f9d6d204SZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
316f9d6d204SZachary Turner }
317f9d6d204SZachary Turner 
318b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const {
319f9d6d204SZachary Turner   if (!IsValid())
320f9d6d204SZachary Turner     return llvm::ArrayRef<uint8_t>();
321f9d6d204SZachary Turner 
322f9d6d204SZachary Turner   char *c = PyByteArray_AsString(m_py_obj);
323f9d6d204SZachary Turner   size_t size = GetSize();
324f9d6d204SZachary Turner   return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
325f9d6d204SZachary Turner }
326f9d6d204SZachary Turner 
327b9c1b51eSKate Stone size_t PythonByteArray::GetSize() const {
328f9d6d204SZachary Turner   if (!IsValid())
329f9d6d204SZachary Turner     return 0;
330f9d6d204SZachary Turner 
331f9d6d204SZachary Turner   return PyByteArray_Size(m_py_obj);
332f9d6d204SZachary Turner }
333f9d6d204SZachary Turner 
334b9c1b51eSKate Stone StructuredData::StringSP PythonByteArray::CreateStructuredString() const {
335f9d6d204SZachary Turner   StructuredData::StringSP result(new StructuredData::String);
336f9d6d204SZachary Turner   llvm::ArrayRef<uint8_t> bytes = GetBytes();
337f9d6d204SZachary Turner   const char *str = reinterpret_cast<const char *>(bytes.data());
338f9d6d204SZachary Turner   result->SetValue(std::string(str, bytes.size()));
339f9d6d204SZachary Turner   return result;
340f9d6d204SZachary Turner }
341f9d6d204SZachary Turner 
3425a72c02bSZachary Turner //----------------------------------------------------------------------
3435a72c02bSZachary Turner // PythonString
3445a72c02bSZachary Turner //----------------------------------------------------------------------
3452c1f46dcSZachary Turner 
346b9c1b51eSKate Stone PythonString::PythonString(PyRefType type, PyObject *py_obj) : PythonObject() {
347f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
3482c1f46dcSZachary Turner }
3492c1f46dcSZachary Turner 
350b9c1b51eSKate Stone PythonString::PythonString(const PythonString &object) : PythonObject(object) {}
3512c1f46dcSZachary Turner 
352b9c1b51eSKate Stone PythonString::PythonString(llvm::StringRef string) : PythonObject() {
35322c8efcdSZachary Turner   SetString(string);
3542c1f46dcSZachary Turner }
3552c1f46dcSZachary Turner 
356b9c1b51eSKate Stone PythonString::PythonString(const char *string) : PythonObject() {
35722c8efcdSZachary Turner   SetString(llvm::StringRef(string));
3582c1f46dcSZachary Turner }
3592c1f46dcSZachary Turner 
360b9c1b51eSKate Stone PythonString::PythonString() : PythonObject() {}
3612c1f46dcSZachary Turner 
362b9c1b51eSKate Stone PythonString::~PythonString() {}
3632c1f46dcSZachary Turner 
364b9c1b51eSKate Stone bool PythonString::Check(PyObject *py_obj) {
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 
377b9c1b51eSKate Stone void PythonString::Reset(PyRefType type, PyObject *py_obj) {
37805097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
37905097246SAdrian Prantl   // still gets decremented if necessary.
380f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
381f8b22f8fSZachary Turner 
382b9c1b51eSKate Stone   if (!PythonString::Check(py_obj)) {
383f8b22f8fSZachary Turner     PythonObject::Reset();
384f8b22f8fSZachary Turner     return;
38522c8efcdSZachary Turner   }
3867d6d218eSZachary Turner #if PY_MAJOR_VERSION < 3
3877d6d218eSZachary Turner   // In Python 2, Don't store PyUnicode objects directly, because we need
3887d6d218eSZachary Turner   // access to their underlying character buffers which Python 2 doesn't
3897d6d218eSZachary Turner   // provide.
3907d6d218eSZachary Turner   if (PyUnicode_Check(py_obj))
3917d6d218eSZachary Turner     result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
3927d6d218eSZachary Turner #endif
393b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
39405097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
395f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
3962c1f46dcSZachary Turner }
3972c1f46dcSZachary Turner 
398b9c1b51eSKate Stone llvm::StringRef PythonString::GetString() const {
39918426935SZachary Turner   if (!IsValid())
40018426935SZachary Turner     return llvm::StringRef();
40118426935SZachary Turner 
40222c8efcdSZachary Turner   Py_ssize_t size;
4035457b426SPavel Labath   const char *data;
40418426935SZachary Turner 
40518426935SZachary Turner #if PY_MAJOR_VERSION >= 3
4065457b426SPavel Labath   data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
40718426935SZachary Turner #else
4085457b426SPavel Labath   char *c;
40918426935SZachary Turner   PyString_AsStringAndSize(m_py_obj, &c, &size);
4105457b426SPavel Labath   data = c;
41118426935SZachary Turner #endif
4125457b426SPavel Labath   return llvm::StringRef(data, size);
41322c8efcdSZachary Turner }
4142c1f46dcSZachary Turner 
415b9c1b51eSKate Stone size_t PythonString::GetSize() const {
416b9c1b51eSKate Stone   if (IsValid()) {
41718426935SZachary Turner #if PY_MAJOR_VERSION >= 3
41818426935SZachary Turner     return PyUnicode_GetSize(m_py_obj);
41918426935SZachary Turner #else
42018426935SZachary Turner     return PyString_Size(m_py_obj);
42118426935SZachary Turner #endif
42218426935SZachary Turner   }
4232c1f46dcSZachary Turner   return 0;
4242c1f46dcSZachary Turner }
4252c1f46dcSZachary Turner 
426b9c1b51eSKate Stone void PythonString::SetString(llvm::StringRef string) {
42722c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
42822c8efcdSZachary Turner   PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
42918426935SZachary Turner   PythonObject::Reset(PyRefType::Owned, unicode);
43022c8efcdSZachary Turner #else
43118426935SZachary Turner   PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
43218426935SZachary Turner   PythonObject::Reset(PyRefType::Owned, str);
43322c8efcdSZachary Turner #endif
4342c1f46dcSZachary Turner }
4352c1f46dcSZachary Turner 
436b9c1b51eSKate Stone StructuredData::StringSP PythonString::CreateStructuredString() const {
4372c1f46dcSZachary Turner   StructuredData::StringSP result(new StructuredData::String);
4382c1f46dcSZachary Turner   result->SetValue(GetString());
4392c1f46dcSZachary Turner   return result;
4402c1f46dcSZachary Turner }
4412c1f46dcSZachary Turner 
4422c1f46dcSZachary Turner //----------------------------------------------------------------------
4432c1f46dcSZachary Turner // PythonInteger
4442c1f46dcSZachary Turner //----------------------------------------------------------------------
4452c1f46dcSZachary Turner 
446b9c1b51eSKate Stone PythonInteger::PythonInteger() : PythonObject() {}
4477d6d218eSZachary Turner 
448f8b22f8fSZachary Turner PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
449b9c1b51eSKate Stone     : PythonObject() {
450f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
4512c1f46dcSZachary Turner }
4522c1f46dcSZachary Turner 
453f8b22f8fSZachary Turner PythonInteger::PythonInteger(const PythonInteger &object)
454b9c1b51eSKate Stone     : PythonObject(object) {}
4552c1f46dcSZachary Turner 
456b9c1b51eSKate Stone PythonInteger::PythonInteger(int64_t value) : PythonObject() {
4572c1f46dcSZachary Turner   SetInteger(value);
4582c1f46dcSZachary Turner }
4592c1f46dcSZachary Turner 
460b9c1b51eSKate Stone PythonInteger::~PythonInteger() {}
4612c1f46dcSZachary Turner 
462b9c1b51eSKate Stone bool PythonInteger::Check(PyObject *py_obj) {
46322c8efcdSZachary Turner   if (!py_obj)
46422c8efcdSZachary Turner     return false;
46522c8efcdSZachary Turner 
46622c8efcdSZachary Turner #if PY_MAJOR_VERSION >= 3
46705097246SAdrian Prantl   // Python 3 does not have PyInt_Check.  There is only one type of integral
46805097246SAdrian Prantl   // value, long.
46922c8efcdSZachary Turner   return PyLong_Check(py_obj);
47022c8efcdSZachary Turner #else
47122c8efcdSZachary Turner   return PyLong_Check(py_obj) || PyInt_Check(py_obj);
47222c8efcdSZachary Turner #endif
4732c1f46dcSZachary Turner }
4742c1f46dcSZachary Turner 
475b9c1b51eSKate Stone void PythonInteger::Reset(PyRefType type, PyObject *py_obj) {
47605097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
47705097246SAdrian Prantl   // still gets decremented if necessary.
478f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
479f8b22f8fSZachary Turner 
480b9c1b51eSKate Stone   if (!PythonInteger::Check(py_obj)) {
481f8b22f8fSZachary Turner     PythonObject::Reset();
482f8b22f8fSZachary Turner     return;
48322c8efcdSZachary Turner   }
48422c8efcdSZachary Turner 
48522c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
48605097246SAdrian Prantl   // Always store this as a PyLong, which makes interoperability between Python
48705097246SAdrian Prantl   // 2.x and Python 3.x easier.  This is only necessary in 2.x, since 3.x
48805097246SAdrian Prantl   // doesn't even have a PyInt.
489b9c1b51eSKate Stone   if (PyInt_Check(py_obj)) {
490f8b22f8fSZachary Turner     // Since we converted the original object to a different type, the new
49105097246SAdrian Prantl     // object is an owned object regardless of the ownership semantics
49205097246SAdrian Prantl     // requested by the user.
493f8b22f8fSZachary Turner     result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
49422c8efcdSZachary Turner   }
49522c8efcdSZachary Turner #endif
49622c8efcdSZachary Turner 
497b9c1b51eSKate Stone   assert(PyLong_Check(result.get()) &&
498b9c1b51eSKate Stone          "Couldn't get a PyLong from this PyObject");
49922c8efcdSZachary Turner 
500b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
50105097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
502f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
5032c1f46dcSZachary Turner }
5042c1f46dcSZachary Turner 
505b9c1b51eSKate Stone int64_t PythonInteger::GetInteger() const {
506b9c1b51eSKate Stone   if (m_py_obj) {
507b9c1b51eSKate Stone     assert(PyLong_Check(m_py_obj) &&
508b9c1b51eSKate Stone            "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
50922c8efcdSZachary Turner 
510008ec446SGreg Clayton     int overflow = 0;
511008ec446SGreg Clayton     int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow);
512b9c1b51eSKate Stone     if (overflow != 0) {
51305097246SAdrian Prantl       // We got an integer that overflows, like 18446744072853913392L we can't
51405097246SAdrian Prantl       // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we
51505097246SAdrian Prantl       // use the unsigned long long it will work as expected.
516008ec446SGreg Clayton       const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj);
5174f730dc7SIlia K       result = static_cast<int64_t>(uval);
518008ec446SGreg Clayton     }
519008ec446SGreg Clayton     return result;
5202c1f46dcSZachary Turner   }
5212c1f46dcSZachary Turner   return UINT64_MAX;
5222c1f46dcSZachary Turner }
5232c1f46dcSZachary Turner 
524b9c1b51eSKate Stone void PythonInteger::SetInteger(int64_t value) {
525f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
5262c1f46dcSZachary Turner }
5272c1f46dcSZachary Turner 
528b9c1b51eSKate Stone StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const {
5292c1f46dcSZachary Turner   StructuredData::IntegerSP result(new StructuredData::Integer);
5302c1f46dcSZachary Turner   result->SetValue(GetInteger());
5312c1f46dcSZachary Turner   return result;
5322c1f46dcSZachary Turner }
5332c1f46dcSZachary Turner 
5342c1f46dcSZachary Turner //----------------------------------------------------------------------
535b81d715cSTatyana Krasnukha // PythonBoolean
536b81d715cSTatyana Krasnukha //----------------------------------------------------------------------
537b81d715cSTatyana Krasnukha 
538b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(PyRefType type, PyObject *py_obj)
539b81d715cSTatyana Krasnukha     : PythonObject() {
540b81d715cSTatyana Krasnukha   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a boolean type
541b81d715cSTatyana Krasnukha }
542b81d715cSTatyana Krasnukha 
543b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(const PythonBoolean &object)
544b81d715cSTatyana Krasnukha     : PythonObject(object) {}
545b81d715cSTatyana Krasnukha 
546b81d715cSTatyana Krasnukha PythonBoolean::PythonBoolean(bool value) {
547b81d715cSTatyana Krasnukha   SetValue(value);
548b81d715cSTatyana Krasnukha }
549b81d715cSTatyana Krasnukha 
550b81d715cSTatyana Krasnukha bool PythonBoolean::Check(PyObject *py_obj) {
551b81d715cSTatyana Krasnukha   return py_obj ? PyBool_Check(py_obj) : false;
552b81d715cSTatyana Krasnukha }
553b81d715cSTatyana Krasnukha 
554b81d715cSTatyana Krasnukha void PythonBoolean::Reset(PyRefType type, PyObject *py_obj) {
555b81d715cSTatyana Krasnukha   // Grab the desired reference type so that if we end up rejecting `py_obj` it
556b81d715cSTatyana Krasnukha   // still gets decremented if necessary.
557b81d715cSTatyana Krasnukha   PythonObject result(type, py_obj);
558b81d715cSTatyana Krasnukha 
559b81d715cSTatyana Krasnukha   if (!PythonBoolean::Check(py_obj)) {
560b81d715cSTatyana Krasnukha     PythonObject::Reset();
561b81d715cSTatyana Krasnukha     return;
562b81d715cSTatyana Krasnukha   }
563b81d715cSTatyana Krasnukha 
564b81d715cSTatyana Krasnukha   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
565b81d715cSTatyana Krasnukha   // overflow since it calls back into the virtual implementation.
566b81d715cSTatyana Krasnukha   PythonObject::Reset(PyRefType::Borrowed, result.get());
567b81d715cSTatyana Krasnukha }
568b81d715cSTatyana Krasnukha 
569b81d715cSTatyana Krasnukha bool PythonBoolean::GetValue() const {
570b81d715cSTatyana Krasnukha   return m_py_obj ? PyObject_IsTrue(m_py_obj) : false;
571b81d715cSTatyana Krasnukha }
572b81d715cSTatyana Krasnukha 
573b81d715cSTatyana Krasnukha void PythonBoolean::SetValue(bool value) {
574b81d715cSTatyana Krasnukha   PythonObject::Reset(PyRefType::Owned, PyBool_FromLong(value));
575b81d715cSTatyana Krasnukha }
576b81d715cSTatyana Krasnukha 
577b81d715cSTatyana Krasnukha StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const {
578b81d715cSTatyana Krasnukha   StructuredData::BooleanSP result(new StructuredData::Boolean);
579b81d715cSTatyana Krasnukha   result->SetValue(GetValue());
580b81d715cSTatyana Krasnukha   return result;
581b81d715cSTatyana Krasnukha }
582b81d715cSTatyana Krasnukha 
583b81d715cSTatyana Krasnukha //----------------------------------------------------------------------
5842c1f46dcSZachary Turner // PythonList
5852c1f46dcSZachary Turner //----------------------------------------------------------------------
5862c1f46dcSZachary Turner 
587b9c1b51eSKate Stone PythonList::PythonList(PyInitialValue value) : PythonObject() {
588f8b22f8fSZachary Turner   if (value == PyInitialValue::Empty)
589f8b22f8fSZachary Turner     Reset(PyRefType::Owned, PyList_New(0));
5902c1f46dcSZachary Turner }
5912c1f46dcSZachary Turner 
592b9c1b51eSKate Stone PythonList::PythonList(int list_size) : PythonObject() {
59387f47729SZachary Turner   Reset(PyRefType::Owned, PyList_New(list_size));
59487f47729SZachary Turner }
59587f47729SZachary Turner 
596b9c1b51eSKate Stone PythonList::PythonList(PyRefType type, PyObject *py_obj) : PythonObject() {
597f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
5982c1f46dcSZachary Turner }
5992c1f46dcSZachary Turner 
600b9c1b51eSKate Stone PythonList::PythonList(const PythonList &list) : PythonObject(list) {}
6012c1f46dcSZachary Turner 
602b9c1b51eSKate Stone PythonList::~PythonList() {}
6032c1f46dcSZachary Turner 
604b9c1b51eSKate Stone bool PythonList::Check(PyObject *py_obj) {
60522c8efcdSZachary Turner   if (!py_obj)
60622c8efcdSZachary Turner     return false;
60722c8efcdSZachary Turner   return PyList_Check(py_obj);
60822c8efcdSZachary Turner }
60922c8efcdSZachary Turner 
610b9c1b51eSKate Stone void PythonList::Reset(PyRefType type, PyObject *py_obj) {
61105097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
61205097246SAdrian Prantl   // still gets decremented if necessary.
613f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
614f8b22f8fSZachary Turner 
615b9c1b51eSKate Stone   if (!PythonList::Check(py_obj)) {
616f8b22f8fSZachary Turner     PythonObject::Reset();
617f8b22f8fSZachary Turner     return;
61822c8efcdSZachary Turner   }
61922c8efcdSZachary Turner 
620b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
62105097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
622f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
6232c1f46dcSZachary Turner }
6242c1f46dcSZachary Turner 
625b9c1b51eSKate Stone uint32_t PythonList::GetSize() const {
626f8b22f8fSZachary Turner   if (IsValid())
6272c1f46dcSZachary Turner     return PyList_GET_SIZE(m_py_obj);
6282c1f46dcSZachary Turner   return 0;
6292c1f46dcSZachary Turner }
6302c1f46dcSZachary Turner 
631b9c1b51eSKate Stone PythonObject PythonList::GetItemAtIndex(uint32_t index) const {
632f8b22f8fSZachary Turner   if (IsValid())
633f8b22f8fSZachary Turner     return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
6342c1f46dcSZachary Turner   return PythonObject();
6352c1f46dcSZachary Turner }
6362c1f46dcSZachary Turner 
637b9c1b51eSKate Stone void PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) {
638b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
639f8b22f8fSZachary Turner     // PyList_SetItem is documented to "steal" a reference, so we need to
640f8b22f8fSZachary Turner     // convert it to an owned reference by incrementing it.
641f8b22f8fSZachary Turner     Py_INCREF(object.get());
6422c1f46dcSZachary Turner     PyList_SetItem(m_py_obj, index, object.get());
6432c1f46dcSZachary Turner   }
644f8b22f8fSZachary Turner }
6452c1f46dcSZachary Turner 
646b9c1b51eSKate Stone void PythonList::AppendItem(const PythonObject &object) {
647b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
648f8b22f8fSZachary Turner     // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
649f8b22f8fSZachary Turner     // here like we do with `PyList_SetItem`.
6502c1f46dcSZachary Turner     PyList_Append(m_py_obj, object.get());
6512c1f46dcSZachary Turner   }
652f8b22f8fSZachary Turner }
6532c1f46dcSZachary Turner 
654b9c1b51eSKate Stone StructuredData::ArraySP PythonList::CreateStructuredArray() const {
6552c1f46dcSZachary Turner   StructuredData::ArraySP result(new StructuredData::Array);
6562c1f46dcSZachary Turner   uint32_t count = GetSize();
657b9c1b51eSKate Stone   for (uint32_t i = 0; i < count; ++i) {
6582c1f46dcSZachary Turner     PythonObject obj = GetItemAtIndex(i);
6592c1f46dcSZachary Turner     result->AddItem(obj.CreateStructuredObject());
6602c1f46dcSZachary Turner   }
6612c1f46dcSZachary Turner   return result;
6622c1f46dcSZachary Turner }
6632c1f46dcSZachary Turner 
6642c1f46dcSZachary Turner //----------------------------------------------------------------------
665a1405147SZachary Turner // PythonTuple
666a1405147SZachary Turner //----------------------------------------------------------------------
667a1405147SZachary Turner 
668b9c1b51eSKate Stone PythonTuple::PythonTuple(PyInitialValue value) : PythonObject() {
669a1405147SZachary Turner   if (value == PyInitialValue::Empty)
670a1405147SZachary Turner     Reset(PyRefType::Owned, PyTuple_New(0));
671a1405147SZachary Turner }
672a1405147SZachary Turner 
673b9c1b51eSKate Stone PythonTuple::PythonTuple(int tuple_size) : PythonObject() {
674a1405147SZachary Turner   Reset(PyRefType::Owned, PyTuple_New(tuple_size));
675a1405147SZachary Turner }
676a1405147SZachary Turner 
677b9c1b51eSKate Stone PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) : PythonObject() {
678a1405147SZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple
679a1405147SZachary Turner }
680a1405147SZachary Turner 
681b9c1b51eSKate Stone PythonTuple::PythonTuple(const PythonTuple &tuple) : PythonObject(tuple) {}
682a1405147SZachary Turner 
683b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) {
684a1405147SZachary Turner   m_py_obj = PyTuple_New(objects.size());
685a1405147SZachary Turner 
686a1405147SZachary Turner   uint32_t idx = 0;
687b9c1b51eSKate Stone   for (auto object : objects) {
688a1405147SZachary Turner     if (object.IsValid())
689a1405147SZachary Turner       SetItemAtIndex(idx, object);
690a1405147SZachary Turner     idx++;
691a1405147SZachary Turner   }
692a1405147SZachary Turner }
693a1405147SZachary Turner 
694b9c1b51eSKate Stone PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) {
695a1405147SZachary Turner   m_py_obj = PyTuple_New(objects.size());
696a1405147SZachary Turner 
697a1405147SZachary Turner   uint32_t idx = 0;
698b9c1b51eSKate Stone   for (auto py_object : objects) {
699a1405147SZachary Turner     PythonObject object(PyRefType::Borrowed, py_object);
700a1405147SZachary Turner     if (object.IsValid())
701a1405147SZachary Turner       SetItemAtIndex(idx, object);
702a1405147SZachary Turner     idx++;
703a1405147SZachary Turner   }
704a1405147SZachary Turner }
705a1405147SZachary Turner 
706b9c1b51eSKate Stone PythonTuple::~PythonTuple() {}
707a1405147SZachary Turner 
708b9c1b51eSKate Stone bool PythonTuple::Check(PyObject *py_obj) {
709a1405147SZachary Turner   if (!py_obj)
710a1405147SZachary Turner     return false;
711a1405147SZachary Turner   return PyTuple_Check(py_obj);
712a1405147SZachary Turner }
713a1405147SZachary Turner 
714b9c1b51eSKate Stone void PythonTuple::Reset(PyRefType type, PyObject *py_obj) {
71505097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
71605097246SAdrian Prantl   // still gets decremented if necessary.
717a1405147SZachary Turner   PythonObject result(type, py_obj);
718a1405147SZachary Turner 
719b9c1b51eSKate Stone   if (!PythonTuple::Check(py_obj)) {
720a1405147SZachary Turner     PythonObject::Reset();
721a1405147SZachary Turner     return;
722a1405147SZachary Turner   }
723a1405147SZachary Turner 
724b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
72505097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
726a1405147SZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
727a1405147SZachary Turner }
728a1405147SZachary Turner 
729b9c1b51eSKate Stone uint32_t PythonTuple::GetSize() const {
730a1405147SZachary Turner   if (IsValid())
731a1405147SZachary Turner     return PyTuple_GET_SIZE(m_py_obj);
732a1405147SZachary Turner   return 0;
733a1405147SZachary Turner }
734a1405147SZachary Turner 
735b9c1b51eSKate Stone PythonObject PythonTuple::GetItemAtIndex(uint32_t index) const {
736a1405147SZachary Turner   if (IsValid())
737a1405147SZachary Turner     return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
738a1405147SZachary Turner   return PythonObject();
739a1405147SZachary Turner }
740a1405147SZachary Turner 
741b9c1b51eSKate Stone void PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) {
742b9c1b51eSKate Stone   if (IsAllocated() && object.IsValid()) {
743a1405147SZachary Turner     // PyTuple_SetItem is documented to "steal" a reference, so we need to
744a1405147SZachary Turner     // convert it to an owned reference by incrementing it.
745a1405147SZachary Turner     Py_INCREF(object.get());
746a1405147SZachary Turner     PyTuple_SetItem(m_py_obj, index, object.get());
747a1405147SZachary Turner   }
748a1405147SZachary Turner }
749a1405147SZachary Turner 
750b9c1b51eSKate Stone StructuredData::ArraySP PythonTuple::CreateStructuredArray() const {
751a1405147SZachary Turner   StructuredData::ArraySP result(new StructuredData::Array);
752a1405147SZachary Turner   uint32_t count = GetSize();
753b9c1b51eSKate Stone   for (uint32_t i = 0; i < count; ++i) {
754a1405147SZachary Turner     PythonObject obj = GetItemAtIndex(i);
755a1405147SZachary Turner     result->AddItem(obj.CreateStructuredObject());
756a1405147SZachary Turner   }
757a1405147SZachary Turner   return result;
758a1405147SZachary Turner }
759a1405147SZachary Turner 
760a1405147SZachary Turner //----------------------------------------------------------------------
7612c1f46dcSZachary Turner // PythonDictionary
7622c1f46dcSZachary Turner //----------------------------------------------------------------------
7632c1f46dcSZachary Turner 
764b9c1b51eSKate Stone PythonDictionary::PythonDictionary(PyInitialValue value) : PythonObject() {
765f8b22f8fSZachary Turner   if (value == PyInitialValue::Empty)
766f8b22f8fSZachary Turner     Reset(PyRefType::Owned, PyDict_New());
7672c1f46dcSZachary Turner }
7682c1f46dcSZachary Turner 
769f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
770b9c1b51eSKate Stone     : PythonObject() {
771f8b22f8fSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
7722c1f46dcSZachary Turner }
7732c1f46dcSZachary Turner 
774f8b22f8fSZachary Turner PythonDictionary::PythonDictionary(const PythonDictionary &object)
775b9c1b51eSKate Stone     : PythonObject(object) {}
7762c1f46dcSZachary Turner 
777b9c1b51eSKate Stone PythonDictionary::~PythonDictionary() {}
7782c1f46dcSZachary Turner 
779b9c1b51eSKate Stone bool PythonDictionary::Check(PyObject *py_obj) {
78022c8efcdSZachary Turner   if (!py_obj)
78122c8efcdSZachary Turner     return false;
78222c8efcdSZachary Turner 
78322c8efcdSZachary Turner   return PyDict_Check(py_obj);
78422c8efcdSZachary Turner }
78522c8efcdSZachary Turner 
786b9c1b51eSKate Stone void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) {
78705097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
78805097246SAdrian Prantl   // still gets decremented if necessary.
789f8b22f8fSZachary Turner   PythonObject result(type, py_obj);
790f8b22f8fSZachary Turner 
791b9c1b51eSKate Stone   if (!PythonDictionary::Check(py_obj)) {
792f8b22f8fSZachary Turner     PythonObject::Reset();
793f8b22f8fSZachary Turner     return;
79422c8efcdSZachary Turner   }
79522c8efcdSZachary Turner 
796b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
79705097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
798f8b22f8fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
7992c1f46dcSZachary Turner }
8002c1f46dcSZachary Turner 
801b9c1b51eSKate Stone uint32_t PythonDictionary::GetSize() const {
802f8b22f8fSZachary Turner   if (IsValid())
8032c1f46dcSZachary Turner     return PyDict_Size(m_py_obj);
8042c1f46dcSZachary Turner   return 0;
8052c1f46dcSZachary Turner }
8062c1f46dcSZachary Turner 
807b9c1b51eSKate Stone PythonList PythonDictionary::GetKeys() const {
808f8b22f8fSZachary Turner   if (IsValid())
809f8b22f8fSZachary Turner     return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
810f8b22f8fSZachary Turner   return PythonList(PyInitialValue::Invalid);
8112c1f46dcSZachary Turner }
8122c1f46dcSZachary Turner 
813b9c1b51eSKate Stone PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const {
814f8b22f8fSZachary Turner   if (IsAllocated() && key.IsValid())
815b9c1b51eSKate Stone     return PythonObject(PyRefType::Borrowed,
816b9c1b51eSKate Stone                         PyDict_GetItem(m_py_obj, key.get()));
8172c1f46dcSZachary Turner   return PythonObject();
8182c1f46dcSZachary Turner }
8192c1f46dcSZachary Turner 
820b9c1b51eSKate Stone void PythonDictionary::SetItemForKey(const PythonObject &key,
821b9c1b51eSKate Stone                                      const PythonObject &value) {
822f8b22f8fSZachary Turner   if (IsAllocated() && key.IsValid() && value.IsValid())
8232c1f46dcSZachary Turner     PyDict_SetItem(m_py_obj, key.get(), value.get());
8242c1f46dcSZachary Turner }
8252c1f46dcSZachary Turner 
8262c1f46dcSZachary Turner StructuredData::DictionarySP
827b9c1b51eSKate Stone PythonDictionary::CreateStructuredDictionary() const {
8282c1f46dcSZachary Turner   StructuredData::DictionarySP result(new StructuredData::Dictionary);
8292c1f46dcSZachary Turner   PythonList keys(GetKeys());
8302c1f46dcSZachary Turner   uint32_t num_keys = keys.GetSize();
831b9c1b51eSKate Stone   for (uint32_t i = 0; i < num_keys; ++i) {
8322c1f46dcSZachary Turner     PythonObject key = keys.GetItemAtIndex(i);
8332c1f46dcSZachary Turner     PythonObject value = GetItemForKey(key);
8342c1f46dcSZachary Turner     StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
835f8b22f8fSZachary Turner     result->AddItem(key.Str().GetString(), structured_value);
8362c1f46dcSZachary Turner   }
8372c1f46dcSZachary Turner   return result;
8382c1f46dcSZachary Turner }
8392c1f46dcSZachary Turner 
840b9c1b51eSKate Stone PythonModule::PythonModule() : PythonObject() {}
8417841efbbSZachary Turner 
842b9c1b51eSKate Stone PythonModule::PythonModule(PyRefType type, PyObject *py_obj) {
8437841efbbSZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
8447841efbbSZachary Turner }
8457841efbbSZachary Turner 
846b9c1b51eSKate Stone PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict) {}
8477841efbbSZachary Turner 
848b9c1b51eSKate Stone PythonModule::~PythonModule() {}
8497841efbbSZachary Turner 
850b9c1b51eSKate Stone PythonModule PythonModule::BuiltinsModule() {
851a1405147SZachary Turner #if PY_MAJOR_VERSION >= 3
852a1405147SZachary Turner   return AddModule("builtins");
853a1405147SZachary Turner #else
854a1405147SZachary Turner   return AddModule("__builtin__");
855a1405147SZachary Turner #endif
856a1405147SZachary Turner }
857a1405147SZachary Turner 
858b9c1b51eSKate Stone PythonModule PythonModule::MainModule() { return AddModule("__main__"); }
859a1405147SZachary Turner 
860b9c1b51eSKate Stone PythonModule PythonModule::AddModule(llvm::StringRef module) {
861a1405147SZachary Turner   std::string str = module.str();
862a1405147SZachary Turner   return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
8637841efbbSZachary Turner }
8647841efbbSZachary Turner 
865b9c1b51eSKate Stone PythonModule PythonModule::ImportModule(llvm::StringRef module) {
8662419f1d5SZachary Turner   std::string str = module.str();
8672419f1d5SZachary Turner   return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str()));
8682419f1d5SZachary Turner }
8692419f1d5SZachary Turner 
870b9c1b51eSKate Stone bool PythonModule::Check(PyObject *py_obj) {
8717841efbbSZachary Turner   if (!py_obj)
8727841efbbSZachary Turner     return false;
8737841efbbSZachary Turner 
8747841efbbSZachary Turner   return PyModule_Check(py_obj);
8757841efbbSZachary Turner }
8767841efbbSZachary Turner 
877b9c1b51eSKate Stone void PythonModule::Reset(PyRefType type, PyObject *py_obj) {
87805097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
87905097246SAdrian Prantl   // still gets decremented if necessary.
8807841efbbSZachary Turner   PythonObject result(type, py_obj);
8817841efbbSZachary Turner 
882b9c1b51eSKate Stone   if (!PythonModule::Check(py_obj)) {
8837841efbbSZachary Turner     PythonObject::Reset();
8847841efbbSZachary Turner     return;
8857841efbbSZachary Turner   }
8867841efbbSZachary Turner 
887b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
88805097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
8897841efbbSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
8907841efbbSZachary Turner }
8917841efbbSZachary Turner 
892b9c1b51eSKate Stone PythonDictionary PythonModule::GetDictionary() const {
8937841efbbSZachary Turner   return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
8947841efbbSZachary Turner }
8957841efbbSZachary Turner 
896b9c1b51eSKate Stone PythonCallable::PythonCallable() : PythonObject() {}
897a1405147SZachary Turner 
898b9c1b51eSKate Stone PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) {
899a1405147SZachary Turner   Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable
900a1405147SZachary Turner }
901a1405147SZachary Turner 
902a1405147SZachary Turner PythonCallable::PythonCallable(const PythonCallable &callable)
903b9c1b51eSKate Stone     : PythonObject(callable) {}
904a1405147SZachary Turner 
905b9c1b51eSKate Stone PythonCallable::~PythonCallable() {}
906a1405147SZachary Turner 
907b9c1b51eSKate Stone bool PythonCallable::Check(PyObject *py_obj) {
908a1405147SZachary Turner   if (!py_obj)
909a1405147SZachary Turner     return false;
910a1405147SZachary Turner 
911a1405147SZachary Turner   return PyCallable_Check(py_obj);
912a1405147SZachary Turner }
913a1405147SZachary Turner 
914b9c1b51eSKate Stone void PythonCallable::Reset(PyRefType type, PyObject *py_obj) {
91505097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
91605097246SAdrian Prantl   // still gets decremented if necessary.
917a1405147SZachary Turner   PythonObject result(type, py_obj);
918a1405147SZachary Turner 
919b9c1b51eSKate Stone   if (!PythonCallable::Check(py_obj)) {
920a1405147SZachary Turner     PythonObject::Reset();
921a1405147SZachary Turner     return;
922a1405147SZachary Turner   }
923a1405147SZachary Turner 
924b9c1b51eSKate Stone   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
92505097246SAdrian Prantl   // overflow since it calls back into the virtual implementation.
926a1405147SZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
927a1405147SZachary Turner }
928a1405147SZachary Turner 
929b9c1b51eSKate Stone PythonCallable::ArgInfo PythonCallable::GetNumArguments() const {
930a5d6765cSEnrico Granata   ArgInfo result = {0, false, false, false};
931a1405147SZachary Turner   if (!IsValid())
932b58fb2f4SZachary Turner     return result;
933a1405147SZachary Turner 
934a1405147SZachary Turner   PyObject *py_func_obj = m_py_obj;
935b9c1b51eSKate Stone   if (PyMethod_Check(py_func_obj)) {
936a1405147SZachary Turner     py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
937a5d6765cSEnrico Granata     PythonObject im_self = GetAttributeValue("im_self");
938a5d6765cSEnrico Granata     if (im_self.IsValid() && !im_self.IsNone())
939a5d6765cSEnrico Granata       result.is_bound_method = true;
940b9c1b51eSKate Stone   } else {
941a5d6765cSEnrico Granata     // see if this is a callable object with an __call__ method
942b9c1b51eSKate Stone     if (!PyFunction_Check(py_func_obj)) {
943a5d6765cSEnrico Granata       PythonObject __call__ = GetAttributeValue("__call__");
944b9c1b51eSKate Stone       if (__call__.IsValid()) {
945a5d6765cSEnrico Granata         auto __callable__ = __call__.AsType<PythonCallable>();
946b9c1b51eSKate Stone         if (__callable__.IsValid()) {
947a5d6765cSEnrico Granata           py_func_obj = PyMethod_GET_FUNCTION(__callable__.get());
948a5d6765cSEnrico Granata           PythonObject im_self = GetAttributeValue("im_self");
949a5d6765cSEnrico Granata           if (im_self.IsValid() && !im_self.IsNone())
950a5d6765cSEnrico Granata             result.is_bound_method = true;
951a5d6765cSEnrico Granata         }
952a5d6765cSEnrico Granata       }
953a5d6765cSEnrico Granata     }
954a5d6765cSEnrico Granata   }
955a1405147SZachary Turner 
956a1405147SZachary Turner   if (!py_func_obj)
957b58fb2f4SZachary Turner     return result;
958a1405147SZachary Turner 
959a1405147SZachary Turner   PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj);
960a1405147SZachary Turner   if (!code)
961b58fb2f4SZachary Turner     return result;
962a1405147SZachary Turner 
963b58fb2f4SZachary Turner   result.count = code->co_argcount;
964b58fb2f4SZachary Turner   result.has_varargs = !!(code->co_flags & CO_VARARGS);
965b58fb2f4SZachary Turner   result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS);
966b58fb2f4SZachary Turner   return result;
967b58fb2f4SZachary Turner }
968b58fb2f4SZachary Turner 
969b9c1b51eSKate Stone PythonObject PythonCallable::operator()() {
970b9c1b51eSKate Stone   return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
971a1405147SZachary Turner }
972a1405147SZachary Turner 
973b9c1b51eSKate Stone PythonObject PythonCallable::
974b9c1b51eSKate Stone operator()(std::initializer_list<PyObject *> args) {
975a1405147SZachary Turner   PythonTuple arg_tuple(args);
976a1405147SZachary Turner   return PythonObject(PyRefType::Owned,
977a1405147SZachary Turner                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
978a1405147SZachary Turner }
979a1405147SZachary Turner 
980b9c1b51eSKate Stone PythonObject PythonCallable::
981b9c1b51eSKate Stone operator()(std::initializer_list<PythonObject> args) {
982a1405147SZachary Turner   PythonTuple arg_tuple(args);
983a1405147SZachary Turner   return PythonObject(PyRefType::Owned,
984a1405147SZachary Turner                       PyObject_CallObject(m_py_obj, arg_tuple.get()));
985a1405147SZachary Turner }
986a1405147SZachary Turner 
987b9c1b51eSKate Stone PythonFile::PythonFile() : PythonObject() {}
98832064024SZachary Turner 
989b9c1b51eSKate Stone PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); }
9909c40264fSZachary Turner 
991b9c1b51eSKate Stone PythonFile::PythonFile(const char *path, const char *mode) {
99250bc1ed2SJonas Devlieghere   lldb_private::File file;
99350bc1ed2SJonas Devlieghere   FileSystem::Instance().Open(file, FileSpec(path), GetOptionsFromMode(mode));
994eda01c31SZachary Turner   Reset(file, mode);
995eda01c31SZachary Turner }
996eda01c31SZachary Turner 
997b9c1b51eSKate Stone PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); }
9989c40264fSZachary Turner 
999b9c1b51eSKate Stone PythonFile::~PythonFile() {}
10009c40264fSZachary Turner 
1001b9c1b51eSKate Stone bool PythonFile::Check(PyObject *py_obj) {
10029c40264fSZachary Turner #if PY_MAJOR_VERSION < 3
100323502721SJason Molenda   return PyFile_Check(py_obj);
100423502721SJason Molenda #else
10059c40264fSZachary Turner   // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
10069c40264fSZachary Turner   // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
100705097246SAdrian Prantl   // over `io.open()`, which returns some object derived from `io.IOBase`. As a
100805097246SAdrian Prantl   // result, the only way to detect a file in Python 3 is to check whether it
100905097246SAdrian Prantl   // inherits from `io.IOBase`.  Since it is possible for non-files to also
10109c40264fSZachary Turner   // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
10119c40264fSZachary Turner   // attribute, which should guarantee that it is backed by the file system.
10129c40264fSZachary Turner   PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
1013b9c1b51eSKate Stone   PythonDictionary io_dict(PyRefType::Borrowed,
1014b9c1b51eSKate Stone                            PyModule_GetDict(io_module.get()));
10159c40264fSZachary Turner   PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
10169c40264fSZachary Turner 
10179c40264fSZachary Turner   PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
10189c40264fSZachary Turner 
10199c40264fSZachary Turner   if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
10209c40264fSZachary Turner     return false;
10219c40264fSZachary Turner   if (!object_type.HasAttribute("fileno"))
10229c40264fSZachary Turner     return false;
10239c40264fSZachary Turner 
10249c40264fSZachary Turner   return true;
102523502721SJason Molenda #endif
10269c40264fSZachary Turner }
10279c40264fSZachary Turner 
1028b9c1b51eSKate Stone void PythonFile::Reset(PyRefType type, PyObject *py_obj) {
102905097246SAdrian Prantl   // Grab the desired reference type so that if we end up rejecting `py_obj` it
103005097246SAdrian Prantl   // still gets decremented if necessary.
10319c40264fSZachary Turner   PythonObject result(type, py_obj);
10329c40264fSZachary Turner 
103323502721SJason Molenda   if (!PythonFile::Check(py_obj)) {
10349c40264fSZachary Turner     PythonObject::Reset();
10359c40264fSZachary Turner     return;
10369c40264fSZachary Turner   }
10379c40264fSZachary Turner 
10389c40264fSZachary Turner   // Calling PythonObject::Reset(const PythonObject&) will lead to stack
10399c40264fSZachary Turner   // overflow since it calls back into the virtual implementation.
10409c40264fSZachary Turner   PythonObject::Reset(PyRefType::Borrowed, result.get());
10419c40264fSZachary Turner }
10429c40264fSZachary Turner 
1043b9c1b51eSKate Stone void PythonFile::Reset(File &file, const char *mode) {
1044b9c1b51eSKate Stone   if (!file.IsValid()) {
104532ac147bSZachary Turner     Reset();
104632ac147bSZachary Turner     return;
104732ac147bSZachary Turner   }
104832ac147bSZachary Turner 
10499c40264fSZachary Turner   char *cmode = const_cast<char *>(mode);
10509c40264fSZachary Turner #if PY_MAJOR_VERSION >= 3
1051b9c1b51eSKate Stone   Reset(PyRefType::Owned, PyFile_FromFd(file.GetDescriptor(), nullptr, cmode,
1052b9c1b51eSKate Stone                                         -1, nullptr, "ignore", nullptr, 0));
10539c40264fSZachary Turner #else
10549c40264fSZachary Turner   // Read through the Python source, doesn't seem to modify these strings
10559c40264fSZachary Turner   Reset(PyRefType::Owned,
1056b9c1b51eSKate Stone         PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode,
1057b9c1b51eSKate Stone                         nullptr));
10589c40264fSZachary Turner #endif
10599c40264fSZachary Turner }
10609c40264fSZachary Turner 
1061b9c1b51eSKate Stone uint32_t PythonFile::GetOptionsFromMode(llvm::StringRef mode) {
1062744959b9SEnrico Granata   if (mode.empty())
1063744959b9SEnrico Granata     return 0;
1064744959b9SEnrico Granata 
1065771ef6d4SMalcolm Parsons   return llvm::StringSwitch<uint32_t>(mode.str())
1066744959b9SEnrico Granata       .Case("r", File::eOpenOptionRead)
1067744959b9SEnrico Granata       .Case("w", File::eOpenOptionWrite)
1068b9c1b51eSKate Stone       .Case("a", File::eOpenOptionWrite | File::eOpenOptionAppend |
1069b9c1b51eSKate Stone                      File::eOpenOptionCanCreate)
1070744959b9SEnrico Granata       .Case("r+", File::eOpenOptionRead | File::eOpenOptionWrite)
1071b9c1b51eSKate Stone       .Case("w+", File::eOpenOptionRead | File::eOpenOptionWrite |
1072b9c1b51eSKate Stone                       File::eOpenOptionCanCreate | File::eOpenOptionTruncate)
1073b9c1b51eSKate Stone       .Case("a+", File::eOpenOptionRead | File::eOpenOptionWrite |
1074b9c1b51eSKate Stone                       File::eOpenOptionAppend | File::eOpenOptionCanCreate)
1075744959b9SEnrico Granata       .Default(0);
1076744959b9SEnrico Granata }
1077744959b9SEnrico Granata 
1078b9c1b51eSKate Stone bool PythonFile::GetUnderlyingFile(File &file) const {
1079eda01c31SZachary Turner   if (!IsValid())
1080eda01c31SZachary Turner     return false;
1081eda01c31SZachary Turner 
1082eda01c31SZachary Turner   file.Close();
1083eda01c31SZachary Turner   // We don't own the file descriptor returned by this function, make sure the
1084eda01c31SZachary Turner   // File object knows about that.
1085eda01c31SZachary Turner   file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
1086744959b9SEnrico Granata   PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>();
1087744959b9SEnrico Granata   file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString()));
1088eda01c31SZachary Turner   return file.IsValid();
1089eda01c31SZachary Turner }
1090d68983e3SPavel Labath 
1091d68983e3SPavel Labath #endif
1092