xref: /llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h (revision b81d715cd25178d413431258667861485bb0ff89)
1 //===-- PythonDataObjects.h--------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
10 #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
11 
12 #ifndef LLDB_DISABLE_PYTHON
13 
14 // LLDB Python header must be included first
15 #include "lldb-python.h"
16 
17 #include "lldb/Utility/Flags.h"
18 
19 #include "lldb/Host/File.h"
20 #include "lldb/Interpreter/OptionValue.h"
21 #include "lldb/Utility/ConstString.h"
22 #include "lldb/Utility/StructuredData.h"
23 #include "lldb/lldb-defines.h"
24 
25 #include "llvm/ADT/ArrayRef.h"
26 
27 namespace lldb_private {
28 
29 class PythonBytes;
30 class PythonString;
31 class PythonList;
32 class PythonDictionary;
33 class PythonInteger;
34 
35 class StructuredPythonObject : public StructuredData::Generic {
36 public:
37   StructuredPythonObject() : StructuredData::Generic() {}
38 
39   StructuredPythonObject(void *obj) : StructuredData::Generic(obj) {
40     Py_XINCREF(GetValue());
41   }
42 
43   ~StructuredPythonObject() override {
44     if (Py_IsInitialized())
45       Py_XDECREF(GetValue());
46     SetValue(nullptr);
47   }
48 
49   bool IsValid() const override { return GetValue() && GetValue() != Py_None; }
50 
51   void Dump(Stream &s, bool pretty_print = true) const override;
52 
53 private:
54   DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
55 };
56 
57 enum class PyObjectType {
58   Unknown,
59   None,
60   Boolean,
61   Integer,
62   Dictionary,
63   List,
64   String,
65   Bytes,
66   ByteArray,
67   Module,
68   Callable,
69   Tuple,
70   File
71 };
72 
73 enum class PyRefType {
74   Borrowed, // We are not given ownership of the incoming PyObject.
75             // We cannot safely hold it without calling Py_INCREF.
76   Owned     // We have ownership of the incoming PyObject.  We should
77             // not call Py_INCREF.
78 };
79 
80 enum class PyInitialValue { Invalid, Empty };
81 
82 class PythonObject {
83 public:
84   PythonObject() : m_py_obj(nullptr) {}
85 
86   PythonObject(PyRefType type, PyObject *py_obj) : m_py_obj(nullptr) {
87     Reset(type, py_obj);
88   }
89 
90   PythonObject(const PythonObject &rhs) : m_py_obj(nullptr) { Reset(rhs); }
91 
92   virtual ~PythonObject() { Reset(); }
93 
94   void Reset() {
95     // Avoid calling the virtual method since it's not necessary
96     // to actually validate the type of the PyObject if we're
97     // just setting to null.
98     if (Py_IsInitialized())
99       Py_XDECREF(m_py_obj);
100     m_py_obj = nullptr;
101   }
102 
103   void Reset(const PythonObject &rhs) {
104     // Avoid calling the virtual method if it's not necessary
105     // to actually validate the type of the PyObject.
106     if (!rhs.IsValid())
107       Reset();
108     else
109       Reset(PyRefType::Borrowed, rhs.m_py_obj);
110   }
111 
112   // PythonObject is implicitly convertible to PyObject *, which will call the
113   // wrong overload.  We want to explicitly disallow this, since a PyObject
114   // *always* owns its reference.  Therefore the overload which takes a
115   // PyRefType doesn't make sense, and the copy constructor should be used.
116   void Reset(PyRefType type, const PythonObject &ref) = delete;
117 
118   virtual void Reset(PyRefType type, PyObject *py_obj) {
119     if (py_obj == m_py_obj)
120       return;
121 
122     if (Py_IsInitialized())
123       Py_XDECREF(m_py_obj);
124 
125     m_py_obj = py_obj;
126 
127     // If this is a borrowed reference, we need to convert it to
128     // an owned reference by incrementing it.  If it is an owned
129     // reference (for example the caller allocated it with PyDict_New()
130     // then we must *not* increment it.
131     if (Py_IsInitialized() && type == PyRefType::Borrowed)
132       Py_XINCREF(m_py_obj);
133   }
134 
135   void Dump() const {
136     if (m_py_obj)
137       _PyObject_Dump(m_py_obj);
138     else
139       puts("NULL");
140   }
141 
142   void Dump(Stream &strm) const;
143 
144   PyObject *get() const { return m_py_obj; }
145 
146   PyObject *release() {
147     PyObject *result = m_py_obj;
148     m_py_obj = nullptr;
149     return result;
150   }
151 
152   PythonObject &operator=(const PythonObject &other) {
153     Reset(PyRefType::Borrowed, other.get());
154     return *this;
155   }
156 
157   PyObjectType GetObjectType() const;
158 
159   PythonString Repr() const;
160 
161   PythonString Str() const;
162 
163   static PythonObject ResolveNameWithDictionary(llvm::StringRef name,
164                                                 const PythonDictionary &dict);
165 
166   template <typename T>
167   static T ResolveNameWithDictionary(llvm::StringRef name,
168                                      const PythonDictionary &dict) {
169     return ResolveNameWithDictionary(name, dict).AsType<T>();
170   }
171 
172   PythonObject ResolveName(llvm::StringRef name) const;
173 
174   template <typename T> T ResolveName(llvm::StringRef name) const {
175     return ResolveName(name).AsType<T>();
176   }
177 
178   bool HasAttribute(llvm::StringRef attribute) const;
179 
180   PythonObject GetAttributeValue(llvm::StringRef attribute) const;
181 
182   bool IsValid() const;
183 
184   bool IsAllocated() const;
185 
186   bool IsNone() const;
187 
188   template <typename T> T AsType() const {
189     if (!T::Check(m_py_obj))
190       return T();
191     return T(PyRefType::Borrowed, m_py_obj);
192   }
193 
194   StructuredData::ObjectSP CreateStructuredObject() const;
195 
196 protected:
197   PyObject *m_py_obj;
198 };
199 
200 class PythonBytes : public PythonObject {
201 public:
202   PythonBytes();
203   explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
204   PythonBytes(const uint8_t *bytes, size_t length);
205   PythonBytes(PyRefType type, PyObject *o);
206   PythonBytes(const PythonBytes &object);
207 
208   ~PythonBytes() override;
209 
210   static bool Check(PyObject *py_obj);
211 
212   // Bring in the no-argument base class version
213   using PythonObject::Reset;
214 
215   void Reset(PyRefType type, PyObject *py_obj) override;
216 
217   llvm::ArrayRef<uint8_t> GetBytes() const;
218 
219   size_t GetSize() const;
220 
221   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
222 
223   StructuredData::StringSP CreateStructuredString() const;
224 };
225 
226 class PythonByteArray : public PythonObject {
227 public:
228   PythonByteArray();
229   explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes);
230   PythonByteArray(const uint8_t *bytes, size_t length);
231   PythonByteArray(PyRefType type, PyObject *o);
232   PythonByteArray(const PythonBytes &object);
233 
234   ~PythonByteArray() override;
235 
236   static bool Check(PyObject *py_obj);
237 
238   // Bring in the no-argument base class version
239   using PythonObject::Reset;
240 
241   void Reset(PyRefType type, PyObject *py_obj) override;
242 
243   llvm::ArrayRef<uint8_t> GetBytes() const;
244 
245   size_t GetSize() const;
246 
247   void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
248 
249   StructuredData::StringSP CreateStructuredString() const;
250 };
251 
252 class PythonString : public PythonObject {
253 public:
254   PythonString();
255   explicit PythonString(llvm::StringRef string);
256   explicit PythonString(const char *string);
257   PythonString(PyRefType type, PyObject *o);
258   PythonString(const PythonString &object);
259 
260   ~PythonString() override;
261 
262   static bool Check(PyObject *py_obj);
263 
264   // Bring in the no-argument base class version
265   using PythonObject::Reset;
266 
267   void Reset(PyRefType type, PyObject *py_obj) override;
268 
269   llvm::StringRef GetString() const;
270 
271   size_t GetSize() const;
272 
273   void SetString(llvm::StringRef string);
274 
275   StructuredData::StringSP CreateStructuredString() const;
276 };
277 
278 class PythonInteger : public PythonObject {
279 public:
280   PythonInteger();
281   explicit PythonInteger(int64_t value);
282   PythonInteger(PyRefType type, PyObject *o);
283   PythonInteger(const PythonInteger &object);
284 
285   ~PythonInteger() override;
286 
287   static bool Check(PyObject *py_obj);
288 
289   // Bring in the no-argument base class version
290   using PythonObject::Reset;
291 
292   void Reset(PyRefType type, PyObject *py_obj) override;
293 
294   int64_t GetInteger() const;
295 
296   void SetInteger(int64_t value);
297 
298   StructuredData::IntegerSP CreateStructuredInteger() const;
299 };
300 
301 class PythonBoolean : public PythonObject {
302 public:
303   PythonBoolean() = default;
304   explicit PythonBoolean(bool value);
305   PythonBoolean(PyRefType type, PyObject *o);
306   PythonBoolean(const PythonBoolean &object);
307 
308   ~PythonBoolean() override = default;
309 
310   static bool Check(PyObject *py_obj);
311 
312   // Bring in the no-argument base class version
313   using PythonObject::Reset;
314 
315   void Reset(PyRefType type, PyObject *py_obj) override;
316 
317   bool GetValue() const;
318 
319   void SetValue(bool value);
320 
321   StructuredData::BooleanSP CreateStructuredBoolean() const;
322 };
323 
324 class PythonList : public PythonObject {
325 public:
326   PythonList() {}
327   explicit PythonList(PyInitialValue value);
328   explicit PythonList(int list_size);
329   PythonList(PyRefType type, PyObject *o);
330   PythonList(const PythonList &list);
331 
332   ~PythonList() override;
333 
334   static bool Check(PyObject *py_obj);
335 
336   // Bring in the no-argument base class version
337   using PythonObject::Reset;
338 
339   void Reset(PyRefType type, PyObject *py_obj) override;
340 
341   uint32_t GetSize() const;
342 
343   PythonObject GetItemAtIndex(uint32_t index) const;
344 
345   void SetItemAtIndex(uint32_t index, const PythonObject &object);
346 
347   void AppendItem(const PythonObject &object);
348 
349   StructuredData::ArraySP CreateStructuredArray() const;
350 };
351 
352 class PythonTuple : public PythonObject {
353 public:
354   PythonTuple() {}
355   explicit PythonTuple(PyInitialValue value);
356   explicit PythonTuple(int tuple_size);
357   PythonTuple(PyRefType type, PyObject *o);
358   PythonTuple(const PythonTuple &tuple);
359   PythonTuple(std::initializer_list<PythonObject> objects);
360   PythonTuple(std::initializer_list<PyObject *> objects);
361 
362   ~PythonTuple() override;
363 
364   static bool Check(PyObject *py_obj);
365 
366   // Bring in the no-argument base class version
367   using PythonObject::Reset;
368 
369   void Reset(PyRefType type, PyObject *py_obj) override;
370 
371   uint32_t GetSize() const;
372 
373   PythonObject GetItemAtIndex(uint32_t index) const;
374 
375   void SetItemAtIndex(uint32_t index, const PythonObject &object);
376 
377   StructuredData::ArraySP CreateStructuredArray() const;
378 };
379 
380 class PythonDictionary : public PythonObject {
381 public:
382   PythonDictionary() {}
383   explicit PythonDictionary(PyInitialValue value);
384   PythonDictionary(PyRefType type, PyObject *o);
385   PythonDictionary(const PythonDictionary &dict);
386 
387   ~PythonDictionary() override;
388 
389   static bool Check(PyObject *py_obj);
390 
391   // Bring in the no-argument base class version
392   using PythonObject::Reset;
393 
394   void Reset(PyRefType type, PyObject *py_obj) override;
395 
396   uint32_t GetSize() const;
397 
398   PythonList GetKeys() const;
399 
400   PythonObject GetItemForKey(const PythonObject &key) const;
401   void SetItemForKey(const PythonObject &key, const PythonObject &value);
402 
403   StructuredData::DictionarySP CreateStructuredDictionary() const;
404 };
405 
406 class PythonModule : public PythonObject {
407 public:
408   PythonModule();
409   PythonModule(PyRefType type, PyObject *o);
410   PythonModule(const PythonModule &dict);
411 
412   ~PythonModule() override;
413 
414   static bool Check(PyObject *py_obj);
415 
416   static PythonModule BuiltinsModule();
417 
418   static PythonModule MainModule();
419 
420   static PythonModule AddModule(llvm::StringRef module);
421 
422   static PythonModule ImportModule(llvm::StringRef module);
423 
424   // Bring in the no-argument base class version
425   using PythonObject::Reset;
426 
427   void Reset(PyRefType type, PyObject *py_obj) override;
428 
429   PythonDictionary GetDictionary() const;
430 };
431 
432 class PythonCallable : public PythonObject {
433 public:
434   struct ArgInfo {
435     size_t count;
436     bool is_bound_method : 1;
437     bool has_varargs : 1;
438     bool has_kwargs : 1;
439   };
440 
441   PythonCallable();
442   PythonCallable(PyRefType type, PyObject *o);
443   PythonCallable(const PythonCallable &dict);
444 
445   ~PythonCallable() override;
446 
447   static bool Check(PyObject *py_obj);
448 
449   // Bring in the no-argument base class version
450   using PythonObject::Reset;
451 
452   void Reset(PyRefType type, PyObject *py_obj) override;
453 
454   ArgInfo GetNumArguments() const;
455 
456   PythonObject operator()();
457 
458   PythonObject operator()(std::initializer_list<PyObject *> args);
459 
460   PythonObject operator()(std::initializer_list<PythonObject> args);
461 
462   template <typename Arg, typename... Args>
463   PythonObject operator()(const Arg &arg, Args... args) {
464     return operator()({arg, args...});
465   }
466 };
467 
468 class PythonFile : public PythonObject {
469 public:
470   PythonFile();
471   PythonFile(File &file, const char *mode);
472   PythonFile(const char *path, const char *mode);
473   PythonFile(PyRefType type, PyObject *o);
474 
475   ~PythonFile() override;
476 
477   static bool Check(PyObject *py_obj);
478 
479   using PythonObject::Reset;
480 
481   void Reset(PyRefType type, PyObject *py_obj) override;
482   void Reset(File &file, const char *mode);
483 
484   static uint32_t GetOptionsFromMode(llvm::StringRef mode);
485 
486   bool GetUnderlyingFile(File &file) const;
487 };
488 
489 } // namespace lldb_private
490 
491 #endif
492 
493 #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
494