1*edb35d95SEugene Zelenko //===-- PythonDataObjects.h--------------------------------------*- 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 #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
112c1f46dcSZachary Turner #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
122c1f46dcSZachary Turner 
132c1f46dcSZachary Turner // C Includes
142c1f46dcSZachary Turner // C++ Includes
152c1f46dcSZachary Turner // Other libraries and framework includes
162c1f46dcSZachary Turner // Project includes
172c1f46dcSZachary Turner #include "lldb/lldb-defines.h"
182c1f46dcSZachary Turner #include "lldb/Core/ConstString.h"
192c1f46dcSZachary Turner #include "lldb/Core/StructuredData.h"
202c1f46dcSZachary Turner #include "lldb/Core/Flags.h"
219c40264fSZachary Turner #include "lldb/Host/File.h"
222c1f46dcSZachary Turner #include "lldb/Interpreter/OptionValue.h"
232c1f46dcSZachary Turner 
242c1f46dcSZachary Turner namespace lldb_private {
25*edb35d95SEugene Zelenko 
262c1f46dcSZachary Turner class PythonString;
272c1f46dcSZachary Turner class PythonList;
282c1f46dcSZachary Turner class PythonDictionary;
292c1f46dcSZachary Turner class PythonInteger;
302c1f46dcSZachary Turner 
312c1f46dcSZachary Turner class StructuredPythonObject : public StructuredData::Generic
322c1f46dcSZachary Turner {
332c1f46dcSZachary Turner public:
342c1f46dcSZachary Turner     StructuredPythonObject()
352c1f46dcSZachary Turner         : StructuredData::Generic()
362c1f46dcSZachary Turner     {
372c1f46dcSZachary Turner     }
382c1f46dcSZachary Turner 
392c1f46dcSZachary Turner     StructuredPythonObject(void *obj)
402c1f46dcSZachary Turner         : StructuredData::Generic(obj)
412c1f46dcSZachary Turner     {
422c1f46dcSZachary Turner         Py_XINCREF(GetValue());
432c1f46dcSZachary Turner     }
442c1f46dcSZachary Turner 
45*edb35d95SEugene Zelenko     ~StructuredPythonObject() override
462c1f46dcSZachary Turner     {
472c1f46dcSZachary Turner         if (Py_IsInitialized())
482c1f46dcSZachary Turner             Py_XDECREF(GetValue());
492c1f46dcSZachary Turner         SetValue(nullptr);
502c1f46dcSZachary Turner     }
512c1f46dcSZachary Turner 
522c1f46dcSZachary Turner     bool
532c1f46dcSZachary Turner     IsValid() const override
542c1f46dcSZachary Turner     {
552c1f46dcSZachary Turner         return GetValue() && GetValue() != Py_None;
562c1f46dcSZachary Turner     }
572c1f46dcSZachary Turner 
582c1f46dcSZachary Turner     void Dump(Stream &s) const override;
592c1f46dcSZachary Turner 
602c1f46dcSZachary Turner private:
612c1f46dcSZachary Turner     DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
622c1f46dcSZachary Turner };
632c1f46dcSZachary Turner 
642c1f46dcSZachary Turner enum class PyObjectType
652c1f46dcSZachary Turner {
662c1f46dcSZachary Turner     Unknown,
672c1f46dcSZachary Turner     None,
682c1f46dcSZachary Turner     Integer,
692c1f46dcSZachary Turner     Dictionary,
702c1f46dcSZachary Turner     List,
719c40264fSZachary Turner     String,
729c40264fSZachary Turner     File
732c1f46dcSZachary Turner };
742c1f46dcSZachary Turner 
75f8b22f8fSZachary Turner enum class PyRefType
76f8b22f8fSZachary Turner {
77f8b22f8fSZachary Turner     Borrowed, // We are not given ownership of the incoming PyObject.
78f8b22f8fSZachary Turner               // We cannot safely hold it without calling Py_INCREF.
79f8b22f8fSZachary Turner     Owned     // We have ownership of the incoming PyObject.  We should
80f8b22f8fSZachary Turner               // not call Py_INCREF.
81f8b22f8fSZachary Turner };
82f8b22f8fSZachary Turner 
83f8b22f8fSZachary Turner enum class PyInitialValue
84f8b22f8fSZachary Turner {
85f8b22f8fSZachary Turner     Invalid,
86f8b22f8fSZachary Turner     Empty
87f8b22f8fSZachary Turner };
88f8b22f8fSZachary Turner 
892c1f46dcSZachary Turner class PythonObject
902c1f46dcSZachary Turner {
912c1f46dcSZachary Turner public:
92f8b22f8fSZachary Turner     PythonObject()
93f8b22f8fSZachary Turner         : m_py_obj(nullptr)
942c1f46dcSZachary Turner     {
952c1f46dcSZachary Turner     }
962c1f46dcSZachary Turner 
97f8b22f8fSZachary Turner     PythonObject(PyRefType type, PyObject *py_obj)
98f8b22f8fSZachary Turner         : m_py_obj(nullptr)
992c1f46dcSZachary Turner     {
100f8b22f8fSZachary Turner         Reset(type, py_obj);
1012c1f46dcSZachary Turner     }
1022c1f46dcSZachary Turner 
103f8b22f8fSZachary Turner     PythonObject(const PythonObject &rhs)
104f8b22f8fSZachary Turner         : m_py_obj(nullptr)
1052c1f46dcSZachary Turner     {
106f8b22f8fSZachary Turner         Reset(rhs);
1072c1f46dcSZachary Turner     }
1082c1f46dcSZachary Turner 
109*edb35d95SEugene Zelenko     virtual ~PythonObject()
110*edb35d95SEugene Zelenko     {
111*edb35d95SEugene Zelenko         Reset();
112*edb35d95SEugene Zelenko     }
1132c1f46dcSZachary Turner 
114f8b22f8fSZachary Turner     void
115f8b22f8fSZachary Turner     Reset()
1162c1f46dcSZachary Turner     {
117f8b22f8fSZachary Turner         // Avoid calling the virtual method since it's not necessary
118f8b22f8fSZachary Turner         // to actually validate the type of the PyObject if we're
119f8b22f8fSZachary Turner         // just setting to null.
1202c1f46dcSZachary Turner         if (Py_IsInitialized())
1212c1f46dcSZachary Turner             Py_XDECREF(m_py_obj);
122f8b22f8fSZachary Turner         m_py_obj = nullptr;
1232c1f46dcSZachary Turner     }
124f8b22f8fSZachary Turner 
125f8b22f8fSZachary Turner     void
126f8b22f8fSZachary Turner     Reset(const PythonObject &rhs)
127f8b22f8fSZachary Turner     {
128f8b22f8fSZachary Turner         // Avoid calling the virtual method if it's not necessary
129f8b22f8fSZachary Turner         // to actually validate the type of the PyObject.
13060c24f70SZachary Turner         if (!rhs.IsValid())
131f8b22f8fSZachary Turner             Reset();
132f8b22f8fSZachary Turner         else
133f8b22f8fSZachary Turner             Reset(PyRefType::Borrowed, rhs.m_py_obj);
134f8b22f8fSZachary Turner     }
135f8b22f8fSZachary Turner 
136f8b22f8fSZachary Turner     // PythonObject is implicitly convertible to PyObject *, which will call the
137f8b22f8fSZachary Turner     // wrong overload.  We want to explicitly disallow this, since a PyObject
138f8b22f8fSZachary Turner     // *always* owns its reference.  Therefore the overload which takes a
139f8b22f8fSZachary Turner     // PyRefType doesn't make sense, and the copy constructor should be used.
140f8b22f8fSZachary Turner     void
141f8b22f8fSZachary Turner     Reset(PyRefType type, const PythonObject &ref) = delete;
142f8b22f8fSZachary Turner 
143f8b22f8fSZachary Turner     virtual void
144f8b22f8fSZachary Turner     Reset(PyRefType type, PyObject *py_obj)
145f8b22f8fSZachary Turner     {
146f8b22f8fSZachary Turner         if (py_obj == m_py_obj)
147f8b22f8fSZachary Turner             return;
148f8b22f8fSZachary Turner 
149f8b22f8fSZachary Turner         if (Py_IsInitialized())
150f8b22f8fSZachary Turner             Py_XDECREF(m_py_obj);
151f8b22f8fSZachary Turner 
152f8b22f8fSZachary Turner         m_py_obj = py_obj;
153f8b22f8fSZachary Turner 
154f8b22f8fSZachary Turner         // If this is a borrowed reference, we need to convert it to
155f8b22f8fSZachary Turner         // an owned reference by incrementing it.  If it is an owned
156f8b22f8fSZachary Turner         // reference (for example the caller allocated it with PyDict_New()
157f8b22f8fSZachary Turner         // then we must *not* increment it.
158f8b22f8fSZachary Turner         if (Py_IsInitialized() && type == PyRefType::Borrowed)
159f8b22f8fSZachary Turner             Py_XINCREF(m_py_obj);
1602c1f46dcSZachary Turner     }
1612c1f46dcSZachary Turner 
1622c1f46dcSZachary Turner     void
1632c1f46dcSZachary Turner     Dump () const
1642c1f46dcSZachary Turner     {
1652c1f46dcSZachary Turner         if (m_py_obj)
1662c1f46dcSZachary Turner             _PyObject_Dump (m_py_obj);
1672c1f46dcSZachary Turner         else
1682c1f46dcSZachary Turner             puts ("NULL");
1692c1f46dcSZachary Turner     }
1702c1f46dcSZachary Turner 
1712c1f46dcSZachary Turner     void
1722c1f46dcSZachary Turner     Dump (Stream &strm) const;
1732c1f46dcSZachary Turner 
1742c1f46dcSZachary Turner     PyObject*
1752c1f46dcSZachary Turner     get() const
1762c1f46dcSZachary Turner     {
1772c1f46dcSZachary Turner         return m_py_obj;
1782c1f46dcSZachary Turner     }
1792c1f46dcSZachary Turner 
18060c24f70SZachary Turner     PyObject*
18160c24f70SZachary Turner     release()
18260c24f70SZachary Turner     {
18360c24f70SZachary Turner         PyObject *result = m_py_obj;
18460c24f70SZachary Turner         m_py_obj = nullptr;
18560c24f70SZachary Turner         return result;
18660c24f70SZachary Turner     }
18760c24f70SZachary Turner 
18860c24f70SZachary Turner     PyObjectType
18960c24f70SZachary Turner     GetObjectType() const;
1902c1f46dcSZachary Turner 
1912c1f46dcSZachary Turner     PythonString
1922c1f46dcSZachary Turner     Repr ();
1932c1f46dcSZachary Turner 
1942c1f46dcSZachary Turner     PythonString
1952c1f46dcSZachary Turner     Str ();
1962c1f46dcSZachary Turner 
197f8b22f8fSZachary Turner     PythonObject &
198f8b22f8fSZachary Turner     operator=(const PythonObject &other)
1992c1f46dcSZachary Turner     {
200f8b22f8fSZachary Turner         Reset(PyRefType::Borrowed, other.get());
201f8b22f8fSZachary Turner         return *this;
2022c1f46dcSZachary Turner     }
2032c1f46dcSZachary Turner 
2042c1f46dcSZachary Turner     bool
2059c40264fSZachary Turner     HasAttribute(llvm::StringRef attribute) const;
2069c40264fSZachary Turner 
2077d6d218eSZachary Turner     PythonObject
2087d6d218eSZachary Turner     GetAttributeValue(llvm::StringRef attribute) const;
2097d6d218eSZachary Turner 
2109c40264fSZachary Turner     bool
211f8b22f8fSZachary Turner     IsValid() const;
212f8b22f8fSZachary Turner 
213f8b22f8fSZachary Turner     bool
214f8b22f8fSZachary Turner     IsAllocated() const;
215f8b22f8fSZachary Turner 
216f8b22f8fSZachary Turner     bool
217f8b22f8fSZachary Turner     IsNone() const;
2182c1f46dcSZachary Turner 
2197d6d218eSZachary Turner     template<typename T>
2207d6d218eSZachary Turner     T AsType() const
2217d6d218eSZachary Turner     {
2227d6d218eSZachary Turner         if (!T::Check(m_py_obj))
2237d6d218eSZachary Turner             return T();
2247d6d218eSZachary Turner         return T(PyRefType::Borrowed, m_py_obj);
2257d6d218eSZachary Turner     }
2267d6d218eSZachary Turner 
2272c1f46dcSZachary Turner     StructuredData::ObjectSP CreateStructuredObject() const;
2282c1f46dcSZachary Turner 
2292c1f46dcSZachary Turner protected:
2302c1f46dcSZachary Turner     PyObject* m_py_obj;
2312c1f46dcSZachary Turner };
2322c1f46dcSZachary Turner 
2332c1f46dcSZachary Turner class PythonString : public PythonObject
2342c1f46dcSZachary Turner {
2352c1f46dcSZachary Turner public:
2362c1f46dcSZachary Turner     PythonString();
237f8b22f8fSZachary Turner     explicit PythonString(llvm::StringRef string);
238f8b22f8fSZachary Turner     explicit PythonString(const char *string);
23987f47729SZachary Turner     PythonString(PyRefType type, PyObject *o);
24087f47729SZachary Turner     PythonString(const PythonString &object);
241*edb35d95SEugene Zelenko 
242f8b22f8fSZachary Turner     ~PythonString() override;
2432c1f46dcSZachary Turner 
24422c8efcdSZachary Turner     static bool Check(PyObject *py_obj);
24522c8efcdSZachary Turner 
246f8b22f8fSZachary Turner     // Bring in the no-argument base class version
247f8b22f8fSZachary Turner     using PythonObject::Reset;
248f8b22f8fSZachary Turner 
249f8b22f8fSZachary Turner     void Reset(PyRefType type, PyObject *py_obj) override;
2502c1f46dcSZachary Turner 
2512c1f46dcSZachary Turner     llvm::StringRef
2522c1f46dcSZachary Turner     GetString() const;
2532c1f46dcSZachary Turner 
2542c1f46dcSZachary Turner     size_t
2552c1f46dcSZachary Turner     GetSize() const;
2562c1f46dcSZachary Turner 
2572c1f46dcSZachary Turner     void SetString(llvm::StringRef string);
2582c1f46dcSZachary Turner 
2592c1f46dcSZachary Turner     StructuredData::StringSP CreateStructuredString() const;
2602c1f46dcSZachary Turner };
2612c1f46dcSZachary Turner 
2622c1f46dcSZachary Turner class PythonInteger : public PythonObject
2632c1f46dcSZachary Turner {
2642c1f46dcSZachary Turner public:
2652c1f46dcSZachary Turner     PythonInteger();
26687f47729SZachary Turner     explicit PythonInteger(int64_t value);
267f8b22f8fSZachary Turner     PythonInteger(PyRefType type, PyObject *o);
268f8b22f8fSZachary Turner     PythonInteger(const PythonInteger &object);
269*edb35d95SEugene Zelenko 
270f8b22f8fSZachary Turner     ~PythonInteger() override;
2712c1f46dcSZachary Turner 
27222c8efcdSZachary Turner     static bool Check(PyObject *py_obj);
27322c8efcdSZachary Turner 
274f8b22f8fSZachary Turner     // Bring in the no-argument base class version
275f8b22f8fSZachary Turner     using PythonObject::Reset;
276f8b22f8fSZachary Turner 
277f8b22f8fSZachary Turner     void Reset(PyRefType type, PyObject *py_obj) override;
2782c1f46dcSZachary Turner 
2792c1f46dcSZachary Turner     int64_t GetInteger() const;
2802c1f46dcSZachary Turner 
2812c1f46dcSZachary Turner     void
2822c1f46dcSZachary Turner     SetInteger (int64_t value);
2832c1f46dcSZachary Turner 
2842c1f46dcSZachary Turner     StructuredData::IntegerSP CreateStructuredInteger() const;
2852c1f46dcSZachary Turner };
2862c1f46dcSZachary Turner 
2872c1f46dcSZachary Turner class PythonList : public PythonObject
2882c1f46dcSZachary Turner {
2892c1f46dcSZachary Turner public:
29087f47729SZachary Turner     explicit PythonList(PyInitialValue value);
29187f47729SZachary Turner     explicit PythonList(int list_size);
292f8b22f8fSZachary Turner     PythonList(PyRefType type, PyObject *o);
293f8b22f8fSZachary Turner     PythonList(const PythonList &list);
294*edb35d95SEugene Zelenko 
295f8b22f8fSZachary Turner     ~PythonList() override;
2962c1f46dcSZachary Turner 
29722c8efcdSZachary Turner     static bool Check(PyObject *py_obj);
29822c8efcdSZachary Turner 
299f8b22f8fSZachary Turner     // Bring in the no-argument base class version
300f8b22f8fSZachary Turner     using PythonObject::Reset;
301f8b22f8fSZachary Turner 
302f8b22f8fSZachary Turner     void Reset(PyRefType type, PyObject *py_obj) override;
3032c1f46dcSZachary Turner 
3042c1f46dcSZachary Turner     uint32_t GetSize() const;
3052c1f46dcSZachary Turner 
3062c1f46dcSZachary Turner     PythonObject GetItemAtIndex(uint32_t index) const;
3072c1f46dcSZachary Turner 
308f8b22f8fSZachary Turner     void SetItemAtIndex(uint32_t index, const PythonObject &object);
3092c1f46dcSZachary Turner 
310f8b22f8fSZachary Turner     void AppendItem(const PythonObject &object);
3112c1f46dcSZachary Turner 
3122c1f46dcSZachary Turner     StructuredData::ArraySP CreateStructuredArray() const;
3132c1f46dcSZachary Turner };
3142c1f46dcSZachary Turner 
3152c1f46dcSZachary Turner class PythonDictionary : public PythonObject
3162c1f46dcSZachary Turner {
3172c1f46dcSZachary Turner public:
31887f47729SZachary Turner     explicit PythonDictionary(PyInitialValue value);
319f8b22f8fSZachary Turner     PythonDictionary(PyRefType type, PyObject *o);
320f8b22f8fSZachary Turner     PythonDictionary(const PythonDictionary &dict);
321*edb35d95SEugene Zelenko 
322f8b22f8fSZachary Turner     ~PythonDictionary() override;
3232c1f46dcSZachary Turner 
32422c8efcdSZachary Turner     static bool Check(PyObject *py_obj);
32522c8efcdSZachary Turner 
326f8b22f8fSZachary Turner     // Bring in the no-argument base class version
327f8b22f8fSZachary Turner     using PythonObject::Reset;
328f8b22f8fSZachary Turner 
329f8b22f8fSZachary Turner     void Reset(PyRefType type, PyObject *py_obj) override;
3302c1f46dcSZachary Turner 
3312c1f46dcSZachary Turner     uint32_t GetSize() const;
3322c1f46dcSZachary Turner 
333f8b22f8fSZachary Turner     PythonList GetKeys() const;
3342c1f46dcSZachary Turner 
335f8b22f8fSZachary Turner     PythonObject GetItemForKey(const PythonObject &key) const;
336f8b22f8fSZachary Turner     void SetItemForKey(const PythonObject &key, const PythonObject &value);
3372c1f46dcSZachary Turner 
3382c1f46dcSZachary Turner     StructuredData::DictionarySP CreateStructuredDictionary() const;
3392c1f46dcSZachary Turner };
34087f47729SZachary Turner 
3419c40264fSZachary Turner class PythonFile : public PythonObject
3429c40264fSZachary Turner {
3439c40264fSZachary Turner   public:
34432064024SZachary Turner     PythonFile();
345eda01c31SZachary Turner     PythonFile(File &file, const char *mode);
346eda01c31SZachary Turner     PythonFile(const char *path, const char *mode);
3479c40264fSZachary Turner     PythonFile(PyRefType type, PyObject *o);
348*edb35d95SEugene Zelenko 
3499c40264fSZachary Turner     ~PythonFile() override;
3509c40264fSZachary Turner 
3519c40264fSZachary Turner     static bool Check(PyObject *py_obj);
3529c40264fSZachary Turner 
3539c40264fSZachary Turner     using PythonObject::Reset;
3549c40264fSZachary Turner 
3559c40264fSZachary Turner     void Reset(PyRefType type, PyObject *py_obj) override;
3569c40264fSZachary Turner     void Reset(File &file, const char *mode);
357eda01c31SZachary Turner 
358eda01c31SZachary Turner     bool GetUnderlyingFile(File &file) const;
3599c40264fSZachary Turner };
3609c40264fSZachary Turner 
3612c1f46dcSZachary Turner } // namespace lldb_private
3622c1f46dcSZachary Turner 
3632c1f46dcSZachary Turner #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
364