xref: /llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h (revision 7841efbb9255126763167b9d7d59242333c6f1bd)
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 // Other libraries and framework includes
16 // Project includes
17 #include "lldb/lldb-defines.h"
18 #include "lldb/Core/ConstString.h"
19 #include "lldb/Core/StructuredData.h"
20 #include "lldb/Core/Flags.h"
21 #include "lldb/Host/File.h"
22 #include "lldb/Interpreter/OptionValue.h"
23 
24 namespace lldb_private {
25 
26 class PythonString;
27 class PythonList;
28 class PythonDictionary;
29 class PythonInteger;
30 
31 class StructuredPythonObject : public StructuredData::Generic
32 {
33 public:
34     StructuredPythonObject()
35         : StructuredData::Generic()
36     {
37     }
38 
39     StructuredPythonObject(void *obj)
40         : StructuredData::Generic(obj)
41     {
42         Py_XINCREF(GetValue());
43     }
44 
45     ~StructuredPythonObject() override
46     {
47         if (Py_IsInitialized())
48             Py_XDECREF(GetValue());
49         SetValue(nullptr);
50     }
51 
52     bool
53     IsValid() const override
54     {
55         return GetValue() && GetValue() != Py_None;
56     }
57 
58     void Dump(Stream &s) const override;
59 
60 private:
61     DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
62 };
63 
64 enum class PyObjectType
65 {
66     Unknown,
67     None,
68     Integer,
69     Dictionary,
70     List,
71     String,
72     Module,
73     File
74 };
75 
76 enum class PyRefType
77 {
78     Borrowed, // We are not given ownership of the incoming PyObject.
79               // We cannot safely hold it without calling Py_INCREF.
80     Owned     // We have ownership of the incoming PyObject.  We should
81               // not call Py_INCREF.
82 };
83 
84 enum class PyInitialValue
85 {
86     Invalid,
87     Empty
88 };
89 
90 class PythonObject
91 {
92 public:
93     PythonObject()
94         : m_py_obj(nullptr)
95     {
96     }
97 
98     PythonObject(PyRefType type, PyObject *py_obj)
99         : m_py_obj(nullptr)
100     {
101         Reset(type, py_obj);
102     }
103 
104     PythonObject(const PythonObject &rhs)
105         : m_py_obj(nullptr)
106     {
107         Reset(rhs);
108     }
109 
110     virtual ~PythonObject()
111     {
112         Reset();
113     }
114 
115     void
116     Reset()
117     {
118         // Avoid calling the virtual method since it's not necessary
119         // to actually validate the type of the PyObject if we're
120         // just setting to null.
121         if (Py_IsInitialized())
122             Py_XDECREF(m_py_obj);
123         m_py_obj = nullptr;
124     }
125 
126     void
127     Reset(const PythonObject &rhs)
128     {
129         // Avoid calling the virtual method if it's not necessary
130         // to actually validate the type of the PyObject.
131         if (!rhs.IsValid())
132             Reset();
133         else
134             Reset(PyRefType::Borrowed, rhs.m_py_obj);
135     }
136 
137     // PythonObject is implicitly convertible to PyObject *, which will call the
138     // wrong overload.  We want to explicitly disallow this, since a PyObject
139     // *always* owns its reference.  Therefore the overload which takes a
140     // PyRefType doesn't make sense, and the copy constructor should be used.
141     void
142     Reset(PyRefType type, const PythonObject &ref) = delete;
143 
144     virtual void
145     Reset(PyRefType type, PyObject *py_obj)
146     {
147         if (py_obj == m_py_obj)
148             return;
149 
150         if (Py_IsInitialized())
151             Py_XDECREF(m_py_obj);
152 
153         m_py_obj = py_obj;
154 
155         // If this is a borrowed reference, we need to convert it to
156         // an owned reference by incrementing it.  If it is an owned
157         // reference (for example the caller allocated it with PyDict_New()
158         // then we must *not* increment it.
159         if (Py_IsInitialized() && type == PyRefType::Borrowed)
160             Py_XINCREF(m_py_obj);
161     }
162 
163     void
164     Dump () const
165     {
166         if (m_py_obj)
167             _PyObject_Dump (m_py_obj);
168         else
169             puts ("NULL");
170     }
171 
172     void
173     Dump (Stream &strm) const;
174 
175     PyObject*
176     get() const
177     {
178         return m_py_obj;
179     }
180 
181     PyObject*
182     release()
183     {
184         PyObject *result = m_py_obj;
185         m_py_obj = nullptr;
186         return result;
187     }
188 
189     PythonObject &
190     operator=(const PythonObject &other)
191     {
192         Reset(PyRefType::Borrowed, other.get());
193         return *this;
194     }
195 
196     PyObjectType
197     GetObjectType() const;
198 
199     PythonString
200     Repr() const;
201 
202     PythonString
203     Str() const;
204 
205     static PythonObject
206     ResolveNameGlobal(llvm::StringRef name);
207 
208     PythonObject
209     ResolveName(llvm::StringRef name) const;
210 
211     bool
212     HasAttribute(llvm::StringRef attribute) const;
213 
214     PythonObject
215     GetAttributeValue(llvm::StringRef attribute) const;
216 
217     bool
218     IsValid() const;
219 
220     bool
221     IsAllocated() const;
222 
223     bool
224     IsNone() const;
225 
226     template<typename T>
227     T AsType() const
228     {
229         if (!T::Check(m_py_obj))
230             return T();
231         return T(PyRefType::Borrowed, m_py_obj);
232     }
233 
234     StructuredData::ObjectSP
235     CreateStructuredObject() const;
236 
237 protected:
238     PyObject* m_py_obj;
239 };
240 
241 class PythonString : public PythonObject
242 {
243 public:
244     PythonString();
245     explicit PythonString(llvm::StringRef string);
246     explicit PythonString(const char *string);
247     PythonString(PyRefType type, PyObject *o);
248     PythonString(const PythonString &object);
249 
250     ~PythonString() override;
251 
252     static bool Check(PyObject *py_obj);
253 
254     // Bring in the no-argument base class version
255     using PythonObject::Reset;
256 
257     void Reset(PyRefType type, PyObject *py_obj) override;
258 
259     llvm::StringRef
260     GetString() const;
261 
262     size_t
263     GetSize() const;
264 
265     void SetString(llvm::StringRef string);
266 
267     StructuredData::StringSP CreateStructuredString() const;
268 };
269 
270 class PythonInteger : public PythonObject
271 {
272 public:
273     PythonInteger();
274     explicit PythonInteger(int64_t value);
275     PythonInteger(PyRefType type, PyObject *o);
276     PythonInteger(const PythonInteger &object);
277 
278     ~PythonInteger() override;
279 
280     static bool Check(PyObject *py_obj);
281 
282     // Bring in the no-argument base class version
283     using PythonObject::Reset;
284 
285     void Reset(PyRefType type, PyObject *py_obj) override;
286 
287     int64_t GetInteger() const;
288 
289     void
290     SetInteger (int64_t value);
291 
292     StructuredData::IntegerSP CreateStructuredInteger() const;
293 };
294 
295 class PythonList : public PythonObject
296 {
297 public:
298     explicit PythonList(PyInitialValue value);
299     explicit PythonList(int list_size);
300     PythonList(PyRefType type, PyObject *o);
301     PythonList(const PythonList &list);
302 
303     ~PythonList() override;
304 
305     static bool Check(PyObject *py_obj);
306 
307     // Bring in the no-argument base class version
308     using PythonObject::Reset;
309 
310     void Reset(PyRefType type, PyObject *py_obj) override;
311 
312     uint32_t GetSize() const;
313 
314     PythonObject GetItemAtIndex(uint32_t index) const;
315 
316     void SetItemAtIndex(uint32_t index, const PythonObject &object);
317 
318     void AppendItem(const PythonObject &object);
319 
320     StructuredData::ArraySP CreateStructuredArray() const;
321 };
322 
323 class PythonDictionary : public PythonObject
324 {
325 public:
326     explicit PythonDictionary(PyInitialValue value);
327     PythonDictionary(PyRefType type, PyObject *o);
328     PythonDictionary(const PythonDictionary &dict);
329 
330     ~PythonDictionary() override;
331 
332     static bool Check(PyObject *py_obj);
333 
334     // Bring in the no-argument base class version
335     using PythonObject::Reset;
336 
337     void Reset(PyRefType type, PyObject *py_obj) override;
338 
339     uint32_t GetSize() const;
340 
341     PythonList GetKeys() const;
342 
343     PythonObject GetItemForKey(const PythonObject &key) const;
344     void SetItemForKey(const PythonObject &key, const PythonObject &value);
345 
346     StructuredData::DictionarySP CreateStructuredDictionary() const;
347 };
348 
349 class PythonModule : public PythonObject
350 {
351   public:
352     PythonModule();
353     PythonModule(PyRefType type, PyObject *o);
354     PythonModule(const PythonModule &dict);
355 
356     ~PythonModule() override;
357 
358     static bool Check(PyObject *py_obj);
359 
360     static PythonModule MainModule();
361 
362     // Bring in the no-argument base class version
363     using PythonObject::Reset;
364 
365     void Reset(PyRefType type, PyObject *py_obj) override;
366 
367     PythonDictionary GetDictionary() const;
368 };
369 
370 class PythonFile : public PythonObject
371 {
372   public:
373     PythonFile();
374     PythonFile(File &file, const char *mode);
375     PythonFile(const char *path, const char *mode);
376     PythonFile(PyRefType type, PyObject *o);
377 
378     ~PythonFile() override;
379 
380     static bool Check(PyObject *py_obj);
381 
382     using PythonObject::Reset;
383 
384     void Reset(PyRefType type, PyObject *py_obj) override;
385     void Reset(File &file, const char *mode);
386 
387     bool GetUnderlyingFile(File &file) const;
388 };
389 
390 } // namespace lldb_private
391 
392 #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
393