aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h')
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h498
1 files changed, 498 insertions, 0 deletions
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
new file mode 100644
index 000000000000..c9d17c0f0fad
--- /dev/null
+++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -0,0 +1,498 @@
+//===-- PythonDataObjects.h--------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
+
+#ifndef LLDB_DISABLE_PYTHON
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-defines.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/StructuredData.h"
+#include "lldb/Core/Flags.h"
+#include "lldb/Host/File.h"
+#include "lldb/Interpreter/OptionValue.h"
+
+namespace lldb_private {
+
+class PythonString;
+class PythonList;
+class PythonDictionary;
+class PythonInteger;
+
+class StructuredPythonObject : public StructuredData::Generic
+{
+public:
+ StructuredPythonObject()
+ : StructuredData::Generic()
+ {
+ }
+
+ StructuredPythonObject(void *obj)
+ : StructuredData::Generic(obj)
+ {
+ Py_XINCREF(GetValue());
+ }
+
+ ~StructuredPythonObject() override
+ {
+ if (Py_IsInitialized())
+ Py_XDECREF(GetValue());
+ SetValue(nullptr);
+ }
+
+ bool
+ IsValid() const override
+ {
+ return GetValue() && GetValue() != Py_None;
+ }
+
+ void Dump(Stream &s) const override;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
+};
+
+enum class PyObjectType
+{
+ Unknown,
+ None,
+ Integer,
+ Dictionary,
+ List,
+ String,
+ Module,
+ Callable,
+ Tuple,
+ File
+};
+
+enum class PyRefType
+{
+ Borrowed, // We are not given ownership of the incoming PyObject.
+ // We cannot safely hold it without calling Py_INCREF.
+ Owned // We have ownership of the incoming PyObject. We should
+ // not call Py_INCREF.
+};
+
+enum class PyInitialValue
+{
+ Invalid,
+ Empty
+};
+
+class PythonObject
+{
+public:
+ PythonObject()
+ : m_py_obj(nullptr)
+ {
+ }
+
+ PythonObject(PyRefType type, PyObject *py_obj)
+ : m_py_obj(nullptr)
+ {
+ Reset(type, py_obj);
+ }
+
+ PythonObject(const PythonObject &rhs)
+ : m_py_obj(nullptr)
+ {
+ Reset(rhs);
+ }
+
+ virtual ~PythonObject()
+ {
+ Reset();
+ }
+
+ void
+ Reset()
+ {
+ // Avoid calling the virtual method since it's not necessary
+ // to actually validate the type of the PyObject if we're
+ // just setting to null.
+ if (Py_IsInitialized())
+ Py_XDECREF(m_py_obj);
+ m_py_obj = nullptr;
+ }
+
+ void
+ Reset(const PythonObject &rhs)
+ {
+ // Avoid calling the virtual method if it's not necessary
+ // to actually validate the type of the PyObject.
+ if (!rhs.IsValid())
+ Reset();
+ else
+ Reset(PyRefType::Borrowed, rhs.m_py_obj);
+ }
+
+ // PythonObject is implicitly convertible to PyObject *, which will call the
+ // wrong overload. We want to explicitly disallow this, since a PyObject
+ // *always* owns its reference. Therefore the overload which takes a
+ // PyRefType doesn't make sense, and the copy constructor should be used.
+ void
+ Reset(PyRefType type, const PythonObject &ref) = delete;
+
+ virtual void
+ Reset(PyRefType type, PyObject *py_obj)
+ {
+ if (py_obj == m_py_obj)
+ return;
+
+ if (Py_IsInitialized())
+ Py_XDECREF(m_py_obj);
+
+ m_py_obj = py_obj;
+
+ // If this is a borrowed reference, we need to convert it to
+ // an owned reference by incrementing it. If it is an owned
+ // reference (for example the caller allocated it with PyDict_New()
+ // then we must *not* increment it.
+ if (Py_IsInitialized() && type == PyRefType::Borrowed)
+ Py_XINCREF(m_py_obj);
+ }
+
+ void
+ Dump () const
+ {
+ if (m_py_obj)
+ _PyObject_Dump (m_py_obj);
+ else
+ puts ("NULL");
+ }
+
+ void
+ Dump (Stream &strm) const;
+
+ PyObject*
+ get() const
+ {
+ return m_py_obj;
+ }
+
+ PyObject*
+ release()
+ {
+ PyObject *result = m_py_obj;
+ m_py_obj = nullptr;
+ return result;
+ }
+
+ PythonObject &
+ operator=(const PythonObject &other)
+ {
+ Reset(PyRefType::Borrowed, other.get());
+ return *this;
+ }
+
+ PyObjectType
+ GetObjectType() const;
+
+ PythonString
+ Repr() const;
+
+ PythonString
+ Str() const;
+
+ static PythonObject
+ ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict);
+
+ template<typename T>
+ static T
+ ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict)
+ {
+ return ResolveNameWithDictionary(name, dict).AsType<T>();
+ }
+
+ PythonObject
+ ResolveName(llvm::StringRef name) const;
+
+ template<typename T>
+ T
+ ResolveName(llvm::StringRef name) const
+ {
+ return ResolveName(name).AsType<T>();
+ }
+
+ bool
+ HasAttribute(llvm::StringRef attribute) const;
+
+ PythonObject
+ GetAttributeValue(llvm::StringRef attribute) const;
+
+ bool
+ IsValid() const;
+
+ bool
+ IsAllocated() const;
+
+ bool
+ IsNone() const;
+
+ template<typename T>
+ T AsType() const
+ {
+ if (!T::Check(m_py_obj))
+ return T();
+ return T(PyRefType::Borrowed, m_py_obj);
+ }
+
+ StructuredData::ObjectSP
+ CreateStructuredObject() const;
+
+protected:
+ PyObject* m_py_obj;
+};
+
+class PythonString : public PythonObject
+{
+public:
+ PythonString();
+ explicit PythonString(llvm::StringRef string);
+ explicit PythonString(const char *string);
+ PythonString(PyRefType type, PyObject *o);
+ PythonString(const PythonString &object);
+
+ ~PythonString() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ llvm::StringRef
+ GetString() const;
+
+ size_t
+ GetSize() const;
+
+ void SetString(llvm::StringRef string);
+
+ StructuredData::StringSP CreateStructuredString() const;
+};
+
+class PythonInteger : public PythonObject
+{
+public:
+ PythonInteger();
+ explicit PythonInteger(int64_t value);
+ PythonInteger(PyRefType type, PyObject *o);
+ PythonInteger(const PythonInteger &object);
+
+ ~PythonInteger() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ int64_t GetInteger() const;
+
+ void
+ SetInteger (int64_t value);
+
+ StructuredData::IntegerSP CreateStructuredInteger() const;
+};
+
+class PythonList : public PythonObject
+{
+public:
+ PythonList() {}
+ explicit PythonList(PyInitialValue value);
+ explicit PythonList(int list_size);
+ PythonList(PyRefType type, PyObject *o);
+ PythonList(const PythonList &list);
+
+ ~PythonList() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ uint32_t GetSize() const;
+
+ PythonObject GetItemAtIndex(uint32_t index) const;
+
+ void SetItemAtIndex(uint32_t index, const PythonObject &object);
+
+ void AppendItem(const PythonObject &object);
+
+ StructuredData::ArraySP CreateStructuredArray() const;
+};
+
+class PythonTuple : public PythonObject
+{
+public:
+ PythonTuple() {}
+ explicit PythonTuple(PyInitialValue value);
+ explicit PythonTuple(int tuple_size);
+ PythonTuple(PyRefType type, PyObject *o);
+ PythonTuple(const PythonTuple &tuple);
+ PythonTuple(std::initializer_list<PythonObject> objects);
+ PythonTuple(std::initializer_list<PyObject*> objects);
+
+ ~PythonTuple() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ uint32_t GetSize() const;
+
+ PythonObject GetItemAtIndex(uint32_t index) const;
+
+ void SetItemAtIndex(uint32_t index, const PythonObject &object);
+
+ StructuredData::ArraySP CreateStructuredArray() const;
+};
+
+class PythonDictionary : public PythonObject
+{
+public:
+ PythonDictionary() {}
+ explicit PythonDictionary(PyInitialValue value);
+ PythonDictionary(PyRefType type, PyObject *o);
+ PythonDictionary(const PythonDictionary &dict);
+
+ ~PythonDictionary() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ uint32_t GetSize() const;
+
+ PythonList GetKeys() const;
+
+ PythonObject GetItemForKey(const PythonObject &key) const;
+ void SetItemForKey(const PythonObject &key, const PythonObject &value);
+
+ StructuredData::DictionarySP CreateStructuredDictionary() const;
+};
+
+class PythonModule : public PythonObject
+{
+ public:
+ PythonModule();
+ PythonModule(PyRefType type, PyObject *o);
+ PythonModule(const PythonModule &dict);
+
+ ~PythonModule() override;
+
+ static bool Check(PyObject *py_obj);
+
+ static PythonModule
+ BuiltinsModule();
+
+ static PythonModule
+ MainModule();
+
+ static PythonModule
+ AddModule(llvm::StringRef module);
+
+ static PythonModule
+ ImportModule(llvm::StringRef module);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ PythonDictionary GetDictionary() const;
+};
+
+class PythonCallable : public PythonObject
+{
+public:
+ struct ArgInfo {
+ size_t count;
+ bool has_varargs : 1;
+ bool has_kwargs : 1;
+ };
+
+ PythonCallable();
+ PythonCallable(PyRefType type, PyObject *o);
+ PythonCallable(const PythonCallable &dict);
+
+ ~PythonCallable() override;
+
+ static bool
+ Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void
+ Reset(PyRefType type, PyObject *py_obj) override;
+
+ ArgInfo
+ GetNumArguments() const;
+
+ PythonObject
+ operator ()();
+
+ PythonObject
+ operator ()(std::initializer_list<PyObject*> args);
+
+ PythonObject
+ operator ()(std::initializer_list<PythonObject> args);
+
+ template<typename Arg, typename... Args>
+ PythonObject
+ operator ()(const Arg &arg, Args... args)
+ {
+ return operator()({ arg, args... });
+ }
+};
+
+
+class PythonFile : public PythonObject
+{
+ public:
+ PythonFile();
+ PythonFile(File &file, const char *mode);
+ PythonFile(const char *path, const char *mode);
+ PythonFile(PyRefType type, PyObject *o);
+
+ ~PythonFile() override;
+
+ static bool Check(PyObject *py_obj);
+
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+ void Reset(File &file, const char *mode);
+
+ bool GetUnderlyingFile(File &file) const;
+};
+
+} // namespace lldb_private
+
+#endif
+
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H