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