1 //===-- PythonDataObjects.h----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
11 #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
12 
13 // C Includes
14 // C++ Includes
15 
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/lldb-defines.h"
19 #include "lldb/Core/ConstString.h"
20 #include "lldb/Core/StructuredData.h"
21 #include "lldb/Core/Flags.h"
22 #include "lldb/Interpreter/OptionValue.h"
23 
24 namespace lldb_private {
25 class PythonString;
26 class PythonList;
27 class PythonDictionary;
28 class PythonInteger;
29 
30 class StructuredPythonObject : public StructuredData::Generic
31 {
32   public:
33     StructuredPythonObject()
34         : StructuredData::Generic()
35     {
36     }
37 
38     StructuredPythonObject(void *obj)
39         : StructuredData::Generic(obj)
40     {
41         Py_XINCREF(GetValue());
42     }
43 
44     virtual ~StructuredPythonObject()
45     {
46         if (Py_IsInitialized())
47             Py_XDECREF(GetValue());
48         SetValue(nullptr);
49     }
50 
51     bool
52     IsValid() const override
53     {
54         return GetValue() && GetValue() != Py_None;
55     }
56 
57     void Dump(Stream &s) const override;
58 
59   private:
60     DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
61 };
62 
63 enum class PyObjectType
64 {
65     Unknown,
66     None,
67     Integer,
68     Dictionary,
69     List,
70     String
71 };
72 
73 enum class PyRefType
74 {
75     Borrowed, // We are not given ownership of the incoming PyObject.
76               // We cannot safely hold it without calling Py_INCREF.
77     Owned     // We have ownership of the incoming PyObject.  We should
78               // not call Py_INCREF.
79 };
80 
81 enum class PyInitialValue
82 {
83     Invalid,
84     Empty
85 };
86 
87 class PythonObject
88 {
89 public:
90     PythonObject()
91         : m_py_obj(nullptr)
92     {
93     }
94 
95     PythonObject(PyRefType type, PyObject *py_obj)
96         : m_py_obj(nullptr)
97     {
98         Reset(type, py_obj);
99     }
100 
101     PythonObject(const PythonObject &rhs)
102         : m_py_obj(nullptr)
103     {
104         Reset(rhs);
105     }
106 
107     virtual ~PythonObject() { Reset(); }
108 
109     void
110     Reset()
111     {
112         // Avoid calling the virtual method since it's not necessary
113         // to actually validate the type of the PyObject if we're
114         // just setting to null.
115         if (Py_IsInitialized())
116             Py_XDECREF(m_py_obj);
117         m_py_obj = nullptr;
118     }
119 
120     void
121     Reset(const PythonObject &rhs)
122     {
123         // Avoid calling the virtual method if it's not necessary
124         // to actually validate the type of the PyObject.
125         if (!rhs.get())
126             Reset();
127         else
128             Reset(PyRefType::Borrowed, rhs.m_py_obj);
129     }
130 
131     // PythonObject is implicitly convertible to PyObject *, which will call the
132     // wrong overload.  We want to explicitly disallow this, since a PyObject
133     // *always* owns its reference.  Therefore the overload which takes a
134     // PyRefType doesn't make sense, and the copy constructor should be used.
135     void
136     Reset(PyRefType type, const PythonObject &ref) = delete;
137 
138     virtual void
139     Reset(PyRefType type, PyObject *py_obj)
140     {
141         if (py_obj == m_py_obj)
142             return;
143 
144         if (Py_IsInitialized())
145             Py_XDECREF(m_py_obj);
146 
147         m_py_obj = py_obj;
148 
149         // If this is a borrowed reference, we need to convert it to
150         // an owned reference by incrementing it.  If it is an owned
151         // reference (for example the caller allocated it with PyDict_New()
152         // then we must *not* increment it.
153         if (Py_IsInitialized() && type == PyRefType::Borrowed)
154             Py_XINCREF(m_py_obj);
155     }
156 
157     void
158     Dump () const
159     {
160         if (m_py_obj)
161             _PyObject_Dump (m_py_obj);
162         else
163             puts ("NULL");
164     }
165 
166     void
167     Dump (Stream &strm) const;
168 
169     PyObject*
170     get () const
171     {
172         return m_py_obj;
173     }
174 
175     PyObjectType GetObjectType() const;
176 
177     PythonString
178     Repr ();
179 
180     PythonString
181     Str ();
182 
183     PythonObject &
184     operator=(const PythonObject &other)
185     {
186         Reset(PyRefType::Borrowed, other.get());
187         return *this;
188     }
189 
190     bool
191     IsValid() const;
192 
193     bool
194     IsAllocated() const;
195 
196     bool
197     IsNone() const;
198 
199     StructuredData::ObjectSP CreateStructuredObject() const;
200 
201 protected:
202     PyObject* m_py_obj;
203 };
204 
205 class PythonString : public PythonObject
206 {
207 public:
208     PythonString();
209     PythonString(PyRefType type, PyObject *o);
210     PythonString(const PythonString &object);
211     explicit PythonString(llvm::StringRef string);
212     explicit PythonString(const char *string);
213     ~PythonString() override;
214 
215     static bool Check(PyObject *py_obj);
216 
217     // Bring in the no-argument base class version
218     using PythonObject::Reset;
219 
220     void Reset(PyRefType type, PyObject *py_obj) override;
221 
222     llvm::StringRef
223     GetString() const;
224 
225     size_t
226     GetSize() const;
227 
228     void SetString(llvm::StringRef string);
229 
230     StructuredData::StringSP CreateStructuredString() const;
231 };
232 
233 class PythonInteger : public PythonObject
234 {
235 public:
236     PythonInteger();
237     PythonInteger(PyRefType type, PyObject *o);
238     PythonInteger(const PythonInteger &object);
239     explicit PythonInteger(int64_t value);
240     ~PythonInteger() override;
241 
242     static bool Check(PyObject *py_obj);
243 
244     // Bring in the no-argument base class version
245     using PythonObject::Reset;
246 
247     void Reset(PyRefType type, PyObject *py_obj) override;
248 
249     int64_t GetInteger() const;
250 
251     void
252     SetInteger (int64_t value);
253 
254     StructuredData::IntegerSP CreateStructuredInteger() const;
255 };
256 
257 class PythonList : public PythonObject
258 {
259 public:
260     PythonList(PyInitialValue value);
261     PythonList(PyRefType type, PyObject *o);
262     PythonList(const PythonList &list);
263     ~PythonList() override;
264 
265     static bool Check(PyObject *py_obj);
266 
267     // Bring in the no-argument base class version
268     using PythonObject::Reset;
269 
270     void Reset(PyRefType type, PyObject *py_obj) override;
271 
272     uint32_t GetSize() const;
273 
274     PythonObject GetItemAtIndex(uint32_t index) const;
275 
276     void SetItemAtIndex(uint32_t index, const PythonObject &object);
277 
278     void AppendItem(const PythonObject &object);
279 
280     StructuredData::ArraySP CreateStructuredArray() const;
281 };
282 
283 class PythonDictionary : public PythonObject
284 {
285 public:
286     PythonDictionary(PyInitialValue value);
287     PythonDictionary(PyRefType type, PyObject *o);
288     PythonDictionary(const PythonDictionary &dict);
289     ~PythonDictionary() override;
290 
291     static bool Check(PyObject *py_obj);
292 
293     // Bring in the no-argument base class version
294     using PythonObject::Reset;
295 
296     void Reset(PyRefType type, PyObject *py_obj) override;
297 
298     uint32_t GetSize() const;
299 
300     PythonList GetKeys() const;
301 
302     PythonObject GetItemForKey(const PythonObject &key) const;
303     void SetItemForKey(const PythonObject &key, const PythonObject &value);
304 
305     StructuredData::DictionarySP CreateStructuredDictionary() const;
306 };
307 } // namespace lldb_private
308 
309 #endif  // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
310