12c1f46dcSZachary Turner //===-- 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 
162c1f46dcSZachary Turner // Other libraries and framework includes
172c1f46dcSZachary Turner // Project includes
182c1f46dcSZachary Turner #include "lldb/lldb-defines.h"
192c1f46dcSZachary Turner #include "lldb/Core/ConstString.h"
202c1f46dcSZachary Turner #include "lldb/Core/StructuredData.h"
212c1f46dcSZachary Turner #include "lldb/Core/Flags.h"
222c1f46dcSZachary Turner #include "lldb/Interpreter/OptionValue.h"
232c1f46dcSZachary Turner 
242c1f46dcSZachary Turner namespace lldb_private {
252c1f46dcSZachary Turner class PythonString;
262c1f46dcSZachary Turner class PythonList;
272c1f46dcSZachary Turner class PythonDictionary;
282c1f46dcSZachary Turner class PythonInteger;
292c1f46dcSZachary Turner 
302c1f46dcSZachary Turner class StructuredPythonObject : public StructuredData::Generic
312c1f46dcSZachary Turner {
322c1f46dcSZachary Turner   public:
332c1f46dcSZachary Turner     StructuredPythonObject()
342c1f46dcSZachary Turner         : StructuredData::Generic()
352c1f46dcSZachary Turner     {
362c1f46dcSZachary Turner     }
372c1f46dcSZachary Turner 
382c1f46dcSZachary Turner     StructuredPythonObject(void *obj)
392c1f46dcSZachary Turner         : StructuredData::Generic(obj)
402c1f46dcSZachary Turner     {
412c1f46dcSZachary Turner         Py_XINCREF(GetValue());
422c1f46dcSZachary Turner     }
432c1f46dcSZachary Turner 
442c1f46dcSZachary Turner     virtual ~StructuredPythonObject()
452c1f46dcSZachary Turner     {
462c1f46dcSZachary Turner         if (Py_IsInitialized())
472c1f46dcSZachary Turner             Py_XDECREF(GetValue());
482c1f46dcSZachary Turner         SetValue(nullptr);
492c1f46dcSZachary Turner     }
502c1f46dcSZachary Turner 
512c1f46dcSZachary Turner     bool
522c1f46dcSZachary Turner     IsValid() const override
532c1f46dcSZachary Turner     {
542c1f46dcSZachary Turner         return GetValue() && GetValue() != Py_None;
552c1f46dcSZachary Turner     }
562c1f46dcSZachary Turner 
572c1f46dcSZachary Turner     void Dump(Stream &s) const override;
582c1f46dcSZachary Turner 
592c1f46dcSZachary Turner   private:
602c1f46dcSZachary Turner     DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
612c1f46dcSZachary Turner };
622c1f46dcSZachary Turner 
632c1f46dcSZachary Turner enum class PyObjectType
642c1f46dcSZachary Turner {
652c1f46dcSZachary Turner     Unknown,
662c1f46dcSZachary Turner     None,
672c1f46dcSZachary Turner     Integer,
682c1f46dcSZachary Turner     Dictionary,
692c1f46dcSZachary Turner     List,
702c1f46dcSZachary Turner     String
712c1f46dcSZachary Turner };
722c1f46dcSZachary Turner 
73*f8b22f8fSZachary Turner enum class PyRefType
74*f8b22f8fSZachary Turner {
75*f8b22f8fSZachary Turner     Borrowed, // We are not given ownership of the incoming PyObject.
76*f8b22f8fSZachary Turner               // We cannot safely hold it without calling Py_INCREF.
77*f8b22f8fSZachary Turner     Owned     // We have ownership of the incoming PyObject.  We should
78*f8b22f8fSZachary Turner               // not call Py_INCREF.
79*f8b22f8fSZachary Turner };
80*f8b22f8fSZachary Turner 
81*f8b22f8fSZachary Turner enum class PyInitialValue
82*f8b22f8fSZachary Turner {
83*f8b22f8fSZachary Turner     Invalid,
84*f8b22f8fSZachary Turner     Empty
85*f8b22f8fSZachary Turner };
86*f8b22f8fSZachary Turner 
872c1f46dcSZachary Turner class PythonObject
882c1f46dcSZachary Turner {
892c1f46dcSZachary Turner public:
90*f8b22f8fSZachary Turner     PythonObject()
91*f8b22f8fSZachary Turner         : m_py_obj(nullptr)
922c1f46dcSZachary Turner     {
932c1f46dcSZachary Turner     }
942c1f46dcSZachary Turner 
95*f8b22f8fSZachary Turner     PythonObject(PyRefType type, PyObject *py_obj)
96*f8b22f8fSZachary Turner         : m_py_obj(nullptr)
972c1f46dcSZachary Turner     {
98*f8b22f8fSZachary Turner         Reset(type, py_obj);
992c1f46dcSZachary Turner     }
1002c1f46dcSZachary Turner 
101*f8b22f8fSZachary Turner     PythonObject(const PythonObject &rhs)
102*f8b22f8fSZachary Turner         : m_py_obj(nullptr)
1032c1f46dcSZachary Turner     {
104*f8b22f8fSZachary Turner         Reset(rhs);
1052c1f46dcSZachary Turner     }
1062c1f46dcSZachary Turner 
107*f8b22f8fSZachary Turner     virtual ~PythonObject() { Reset(); }
1082c1f46dcSZachary Turner 
109*f8b22f8fSZachary Turner     void
110*f8b22f8fSZachary Turner     Reset()
1112c1f46dcSZachary Turner     {
112*f8b22f8fSZachary Turner         // Avoid calling the virtual method since it's not necessary
113*f8b22f8fSZachary Turner         // to actually validate the type of the PyObject if we're
114*f8b22f8fSZachary Turner         // just setting to null.
1152c1f46dcSZachary Turner         if (Py_IsInitialized())
1162c1f46dcSZachary Turner             Py_XDECREF(m_py_obj);
117*f8b22f8fSZachary Turner         m_py_obj = nullptr;
1182c1f46dcSZachary Turner     }
119*f8b22f8fSZachary Turner 
120*f8b22f8fSZachary Turner     void
121*f8b22f8fSZachary Turner     Reset(const PythonObject &rhs)
122*f8b22f8fSZachary Turner     {
123*f8b22f8fSZachary Turner         // Avoid calling the virtual method if it's not necessary
124*f8b22f8fSZachary Turner         // to actually validate the type of the PyObject.
125*f8b22f8fSZachary Turner         if (!rhs.get())
126*f8b22f8fSZachary Turner             Reset();
127*f8b22f8fSZachary Turner         else
128*f8b22f8fSZachary Turner             Reset(PyRefType::Borrowed, rhs.m_py_obj);
129*f8b22f8fSZachary Turner     }
130*f8b22f8fSZachary Turner 
131*f8b22f8fSZachary Turner     // PythonObject is implicitly convertible to PyObject *, which will call the
132*f8b22f8fSZachary Turner     // wrong overload.  We want to explicitly disallow this, since a PyObject
133*f8b22f8fSZachary Turner     // *always* owns its reference.  Therefore the overload which takes a
134*f8b22f8fSZachary Turner     // PyRefType doesn't make sense, and the copy constructor should be used.
135*f8b22f8fSZachary Turner     void
136*f8b22f8fSZachary Turner     Reset(PyRefType type, const PythonObject &ref) = delete;
137*f8b22f8fSZachary Turner 
138*f8b22f8fSZachary Turner     virtual void
139*f8b22f8fSZachary Turner     Reset(PyRefType type, PyObject *py_obj)
140*f8b22f8fSZachary Turner     {
141*f8b22f8fSZachary Turner         if (py_obj == m_py_obj)
142*f8b22f8fSZachary Turner             return;
143*f8b22f8fSZachary Turner 
144*f8b22f8fSZachary Turner         if (Py_IsInitialized())
145*f8b22f8fSZachary Turner             Py_XDECREF(m_py_obj);
146*f8b22f8fSZachary Turner 
147*f8b22f8fSZachary Turner         m_py_obj = py_obj;
148*f8b22f8fSZachary Turner 
149*f8b22f8fSZachary Turner         // If this is a borrowed reference, we need to convert it to
150*f8b22f8fSZachary Turner         // an owned reference by incrementing it.  If it is an owned
151*f8b22f8fSZachary Turner         // reference (for example the caller allocated it with PyDict_New()
152*f8b22f8fSZachary Turner         // then we must *not* increment it.
153*f8b22f8fSZachary Turner         if (Py_IsInitialized() && type == PyRefType::Borrowed)
154*f8b22f8fSZachary Turner             Py_XINCREF(m_py_obj);
1552c1f46dcSZachary Turner     }
1562c1f46dcSZachary Turner 
1572c1f46dcSZachary Turner     void
1582c1f46dcSZachary Turner     Dump () const
1592c1f46dcSZachary Turner     {
1602c1f46dcSZachary Turner         if (m_py_obj)
1612c1f46dcSZachary Turner             _PyObject_Dump (m_py_obj);
1622c1f46dcSZachary Turner         else
1632c1f46dcSZachary Turner             puts ("NULL");
1642c1f46dcSZachary Turner     }
1652c1f46dcSZachary Turner 
1662c1f46dcSZachary Turner     void
1672c1f46dcSZachary Turner     Dump (Stream &strm) const;
1682c1f46dcSZachary Turner 
1692c1f46dcSZachary Turner     PyObject*
1702c1f46dcSZachary Turner     get () const
1712c1f46dcSZachary Turner     {
1722c1f46dcSZachary Turner         return m_py_obj;
1732c1f46dcSZachary Turner     }
1742c1f46dcSZachary Turner 
1752c1f46dcSZachary Turner     PyObjectType GetObjectType() const;
1762c1f46dcSZachary Turner 
1772c1f46dcSZachary Turner     PythonString
1782c1f46dcSZachary Turner     Repr ();
1792c1f46dcSZachary Turner 
1802c1f46dcSZachary Turner     PythonString
1812c1f46dcSZachary Turner     Str ();
1822c1f46dcSZachary Turner 
183*f8b22f8fSZachary Turner     PythonObject &
184*f8b22f8fSZachary Turner     operator=(const PythonObject &other)
1852c1f46dcSZachary Turner     {
186*f8b22f8fSZachary Turner         Reset(PyRefType::Borrowed, other.get());
187*f8b22f8fSZachary Turner         return *this;
1882c1f46dcSZachary Turner     }
1892c1f46dcSZachary Turner 
1902c1f46dcSZachary Turner     bool
191*f8b22f8fSZachary Turner     IsValid() const;
192*f8b22f8fSZachary Turner 
193*f8b22f8fSZachary Turner     bool
194*f8b22f8fSZachary Turner     IsAllocated() const;
195*f8b22f8fSZachary Turner 
196*f8b22f8fSZachary Turner     bool
197*f8b22f8fSZachary Turner     IsNone() const;
1982c1f46dcSZachary Turner 
1992c1f46dcSZachary Turner     StructuredData::ObjectSP CreateStructuredObject() const;
2002c1f46dcSZachary Turner 
2012c1f46dcSZachary Turner protected:
2022c1f46dcSZachary Turner     PyObject* m_py_obj;
2032c1f46dcSZachary Turner };
2042c1f46dcSZachary Turner 
2052c1f46dcSZachary Turner class PythonString : public PythonObject
2062c1f46dcSZachary Turner {
2072c1f46dcSZachary Turner public:
2082c1f46dcSZachary Turner     PythonString();
209*f8b22f8fSZachary Turner     PythonString(PyRefType type, PyObject *o);
210*f8b22f8fSZachary Turner     PythonString(const PythonString &object);
211*f8b22f8fSZachary Turner     explicit PythonString(llvm::StringRef string);
212*f8b22f8fSZachary Turner     explicit PythonString(const char *string);
213*f8b22f8fSZachary Turner     ~PythonString() override;
2142c1f46dcSZachary Turner 
21522c8efcdSZachary Turner     static bool Check(PyObject *py_obj);
21622c8efcdSZachary Turner 
217*f8b22f8fSZachary Turner     // Bring in the no-argument base class version
218*f8b22f8fSZachary Turner     using PythonObject::Reset;
219*f8b22f8fSZachary Turner 
220*f8b22f8fSZachary Turner     void Reset(PyRefType type, PyObject *py_obj) override;
2212c1f46dcSZachary Turner 
2222c1f46dcSZachary Turner     llvm::StringRef
2232c1f46dcSZachary Turner     GetString() const;
2242c1f46dcSZachary Turner 
2252c1f46dcSZachary Turner     size_t
2262c1f46dcSZachary Turner     GetSize() const;
2272c1f46dcSZachary Turner 
2282c1f46dcSZachary Turner     void SetString(llvm::StringRef string);
2292c1f46dcSZachary Turner 
2302c1f46dcSZachary Turner     StructuredData::StringSP CreateStructuredString() const;
2312c1f46dcSZachary Turner };
2322c1f46dcSZachary Turner 
2332c1f46dcSZachary Turner class PythonInteger : public PythonObject
2342c1f46dcSZachary Turner {
2352c1f46dcSZachary Turner public:
2362c1f46dcSZachary Turner     PythonInteger();
237*f8b22f8fSZachary Turner     PythonInteger(PyRefType type, PyObject *o);
238*f8b22f8fSZachary Turner     PythonInteger(const PythonInteger &object);
239*f8b22f8fSZachary Turner     explicit PythonInteger(int64_t value);
240*f8b22f8fSZachary Turner     ~PythonInteger() override;
2412c1f46dcSZachary Turner 
24222c8efcdSZachary Turner     static bool Check(PyObject *py_obj);
24322c8efcdSZachary Turner 
244*f8b22f8fSZachary Turner     // Bring in the no-argument base class version
245*f8b22f8fSZachary Turner     using PythonObject::Reset;
246*f8b22f8fSZachary Turner 
247*f8b22f8fSZachary Turner     void Reset(PyRefType type, PyObject *py_obj) override;
2482c1f46dcSZachary Turner 
2492c1f46dcSZachary Turner     int64_t GetInteger() const;
2502c1f46dcSZachary Turner 
2512c1f46dcSZachary Turner     void
2522c1f46dcSZachary Turner     SetInteger (int64_t value);
2532c1f46dcSZachary Turner 
2542c1f46dcSZachary Turner     StructuredData::IntegerSP CreateStructuredInteger() const;
2552c1f46dcSZachary Turner };
2562c1f46dcSZachary Turner 
2572c1f46dcSZachary Turner class PythonList : public PythonObject
2582c1f46dcSZachary Turner {
2592c1f46dcSZachary Turner public:
260*f8b22f8fSZachary Turner     PythonList(PyInitialValue value);
261*f8b22f8fSZachary Turner     PythonList(PyRefType type, PyObject *o);
262*f8b22f8fSZachary Turner     PythonList(const PythonList &list);
263*f8b22f8fSZachary Turner     ~PythonList() override;
2642c1f46dcSZachary Turner 
26522c8efcdSZachary Turner     static bool Check(PyObject *py_obj);
26622c8efcdSZachary Turner 
267*f8b22f8fSZachary Turner     // Bring in the no-argument base class version
268*f8b22f8fSZachary Turner     using PythonObject::Reset;
269*f8b22f8fSZachary Turner 
270*f8b22f8fSZachary Turner     void Reset(PyRefType type, PyObject *py_obj) override;
2712c1f46dcSZachary Turner 
2722c1f46dcSZachary Turner     uint32_t GetSize() const;
2732c1f46dcSZachary Turner 
2742c1f46dcSZachary Turner     PythonObject GetItemAtIndex(uint32_t index) const;
2752c1f46dcSZachary Turner 
276*f8b22f8fSZachary Turner     void SetItemAtIndex(uint32_t index, const PythonObject &object);
2772c1f46dcSZachary Turner 
278*f8b22f8fSZachary Turner     void AppendItem(const PythonObject &object);
2792c1f46dcSZachary Turner 
2802c1f46dcSZachary Turner     StructuredData::ArraySP CreateStructuredArray() const;
2812c1f46dcSZachary Turner };
2822c1f46dcSZachary Turner 
2832c1f46dcSZachary Turner class PythonDictionary : public PythonObject
2842c1f46dcSZachary Turner {
2852c1f46dcSZachary Turner public:
286*f8b22f8fSZachary Turner     PythonDictionary(PyInitialValue value);
287*f8b22f8fSZachary Turner     PythonDictionary(PyRefType type, PyObject *o);
288*f8b22f8fSZachary Turner     PythonDictionary(const PythonDictionary &dict);
289*f8b22f8fSZachary Turner     ~PythonDictionary() override;
2902c1f46dcSZachary Turner 
29122c8efcdSZachary Turner     static bool Check(PyObject *py_obj);
29222c8efcdSZachary Turner 
293*f8b22f8fSZachary Turner     // Bring in the no-argument base class version
294*f8b22f8fSZachary Turner     using PythonObject::Reset;
295*f8b22f8fSZachary Turner 
296*f8b22f8fSZachary Turner     void Reset(PyRefType type, PyObject *py_obj) override;
2972c1f46dcSZachary Turner 
2982c1f46dcSZachary Turner     uint32_t GetSize() const;
2992c1f46dcSZachary Turner 
300*f8b22f8fSZachary Turner     PythonList GetKeys() const;
3012c1f46dcSZachary Turner 
302*f8b22f8fSZachary Turner     PythonObject GetItemForKey(const PythonObject &key) const;
303*f8b22f8fSZachary Turner     void SetItemForKey(const PythonObject &key, const PythonObject &value);
3042c1f46dcSZachary Turner 
3052c1f46dcSZachary Turner     StructuredData::DictionarySP CreateStructuredDictionary() const;
3062c1f46dcSZachary Turner };
3072c1f46dcSZachary Turner } // namespace lldb_private
3082c1f46dcSZachary Turner 
3092c1f46dcSZachary Turner #endif  // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
310