xref: /llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h (revision eda01c31757db23748a0efa1629442de5cd53282)
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/Host/File.h"
23 #include "lldb/Interpreter/OptionValue.h"
24 
25 namespace lldb_private {
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     virtual ~StructuredPythonObject()
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     File
73 };
74 
75 enum class PyRefType
76 {
77     Borrowed, // We are not given ownership of the incoming PyObject.
78               // We cannot safely hold it without calling Py_INCREF.
79     Owned     // We have ownership of the incoming PyObject.  We should
80               // not call Py_INCREF.
81 };
82 
83 enum class PyInitialValue
84 {
85     Invalid,
86     Empty
87 };
88 
89 class PythonObject
90 {
91 public:
92     PythonObject()
93         : m_py_obj(nullptr)
94     {
95     }
96 
97     PythonObject(PyRefType type, PyObject *py_obj)
98         : m_py_obj(nullptr)
99     {
100         Reset(type, py_obj);
101     }
102 
103     PythonObject(const PythonObject &rhs)
104         : m_py_obj(nullptr)
105     {
106         Reset(rhs);
107     }
108 
109     virtual ~PythonObject() { Reset(); }
110 
111     void
112     Reset()
113     {
114         // Avoid calling the virtual method since it's not necessary
115         // to actually validate the type of the PyObject if we're
116         // just setting to null.
117         if (Py_IsInitialized())
118             Py_XDECREF(m_py_obj);
119         m_py_obj = nullptr;
120     }
121 
122     void
123     Reset(const PythonObject &rhs)
124     {
125         // Avoid calling the virtual method if it's not necessary
126         // to actually validate the type of the PyObject.
127         if (!rhs.IsValid())
128             Reset();
129         else
130             Reset(PyRefType::Borrowed, rhs.m_py_obj);
131     }
132 
133     // PythonObject is implicitly convertible to PyObject *, which will call the
134     // wrong overload.  We want to explicitly disallow this, since a PyObject
135     // *always* owns its reference.  Therefore the overload which takes a
136     // PyRefType doesn't make sense, and the copy constructor should be used.
137     void
138     Reset(PyRefType type, const PythonObject &ref) = delete;
139 
140     virtual void
141     Reset(PyRefType type, PyObject *py_obj)
142     {
143         if (py_obj == m_py_obj)
144             return;
145 
146         if (Py_IsInitialized())
147             Py_XDECREF(m_py_obj);
148 
149         m_py_obj = py_obj;
150 
151         // If this is a borrowed reference, we need to convert it to
152         // an owned reference by incrementing it.  If it is an owned
153         // reference (for example the caller allocated it with PyDict_New()
154         // then we must *not* increment it.
155         if (Py_IsInitialized() && type == PyRefType::Borrowed)
156             Py_XINCREF(m_py_obj);
157     }
158 
159     void
160     Dump () const
161     {
162         if (m_py_obj)
163             _PyObject_Dump (m_py_obj);
164         else
165             puts ("NULL");
166     }
167 
168     void
169     Dump (Stream &strm) const;
170 
171     PyObject*
172     get() const
173     {
174         return m_py_obj;
175     }
176 
177     PyObject*
178     release()
179     {
180         PyObject *result = m_py_obj;
181         m_py_obj = nullptr;
182         return result;
183     }
184 
185     PyObjectType
186     GetObjectType() const;
187 
188     PythonString
189     Repr ();
190 
191     PythonString
192     Str ();
193 
194     PythonObject &
195     operator=(const PythonObject &other)
196     {
197         Reset(PyRefType::Borrowed, other.get());
198         return *this;
199     }
200 
201     bool
202     HasAttribute(llvm::StringRef attribute) const;
203 
204     bool
205     IsValid() const;
206 
207     bool
208     IsAllocated() const;
209 
210     bool
211     IsNone() const;
212 
213     StructuredData::ObjectSP CreateStructuredObject() const;
214 
215 protected:
216     PyObject* m_py_obj;
217 };
218 
219 class PythonString : public PythonObject
220 {
221 public:
222     PythonString();
223     explicit PythonString(llvm::StringRef string);
224     explicit PythonString(const char *string);
225     PythonString(PyRefType type, PyObject *o);
226     PythonString(const PythonString &object);
227     ~PythonString() override;
228 
229     static bool Check(PyObject *py_obj);
230 
231     // Bring in the no-argument base class version
232     using PythonObject::Reset;
233 
234     void Reset(PyRefType type, PyObject *py_obj) override;
235 
236     llvm::StringRef
237     GetString() const;
238 
239     size_t
240     GetSize() const;
241 
242     void SetString(llvm::StringRef string);
243 
244     StructuredData::StringSP CreateStructuredString() const;
245 };
246 
247 class PythonInteger : public PythonObject
248 {
249 public:
250     PythonInteger();
251     explicit PythonInteger(int64_t value);
252     PythonInteger(PyRefType type, PyObject *o);
253     PythonInteger(const PythonInteger &object);
254     ~PythonInteger() override;
255 
256     static bool Check(PyObject *py_obj);
257 
258     // Bring in the no-argument base class version
259     using PythonObject::Reset;
260 
261     void Reset(PyRefType type, PyObject *py_obj) override;
262 
263     int64_t GetInteger() const;
264 
265     void
266     SetInteger (int64_t value);
267 
268     StructuredData::IntegerSP CreateStructuredInteger() const;
269 };
270 
271 class PythonList : public PythonObject
272 {
273 public:
274     explicit PythonList(PyInitialValue value);
275     explicit PythonList(int list_size);
276     PythonList(PyRefType type, PyObject *o);
277     PythonList(const PythonList &list);
278     ~PythonList() 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     uint32_t GetSize() const;
288 
289     PythonObject GetItemAtIndex(uint32_t index) const;
290 
291     void SetItemAtIndex(uint32_t index, const PythonObject &object);
292 
293     void AppendItem(const PythonObject &object);
294 
295     StructuredData::ArraySP CreateStructuredArray() const;
296 };
297 
298 class PythonDictionary : public PythonObject
299 {
300 public:
301     explicit PythonDictionary(PyInitialValue value);
302     PythonDictionary(PyRefType type, PyObject *o);
303     PythonDictionary(const PythonDictionary &dict);
304     ~PythonDictionary() override;
305 
306     static bool Check(PyObject *py_obj);
307 
308     // Bring in the no-argument base class version
309     using PythonObject::Reset;
310 
311     void Reset(PyRefType type, PyObject *py_obj) override;
312 
313     uint32_t GetSize() const;
314 
315     PythonList GetKeys() const;
316 
317     PythonObject GetItemForKey(const PythonObject &key) const;
318     void SetItemForKey(const PythonObject &key, const PythonObject &value);
319 
320     StructuredData::DictionarySP CreateStructuredDictionary() const;
321 };
322 
323 class PythonFile : public PythonObject
324 {
325   public:
326     PythonFile(File &file, const char *mode);
327     PythonFile(const char *path, const char *mode);
328     PythonFile(PyRefType type, PyObject *o);
329     ~PythonFile() override;
330 
331     static bool Check(PyObject *py_obj);
332 
333     using PythonObject::Reset;
334 
335     void Reset(PyRefType type, PyObject *py_obj) override;
336     void Reset(File &file, const char *mode);
337 
338     bool GetUnderlyingFile(File &file) const;
339 };
340 
341 } // namespace lldb_private
342 
343 #endif  // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
344