diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
commit | 0b57cec536236d46e3dba9bd041533462f33dbb7 (patch) | |
tree | 56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h | |
parent | 718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff) |
Notes
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h')
-rw-r--r-- | contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h | 479 |
1 files changed, 479 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h new file mode 100644 index 000000000000..049ce90bb1b1 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -0,0 +1,479 @@ +//===-- PythonDataObjects.h--------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H + +#ifndef LLDB_DISABLE_PYTHON + +// LLDB Python header must be included first +#include "lldb-python.h" + +#include "lldb/Host/File.h" +#include "lldb/Utility/StructuredData.h" + +#include "llvm/ADT/ArrayRef.h" + +namespace lldb_private { + +class PythonBytes; +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, bool pretty_print = true) const override; + +private: + DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject); +}; + +enum class PyObjectType { + Unknown, + None, + Boolean, + Integer, + Dictionary, + List, + String, + Bytes, + ByteArray, + 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 PythonBytes : public PythonObject { +public: + PythonBytes(); + explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes); + PythonBytes(const uint8_t *bytes, size_t length); + PythonBytes(PyRefType type, PyObject *o); + + ~PythonBytes() 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::ArrayRef<uint8_t> GetBytes() const; + + size_t GetSize() const; + + void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); + + StructuredData::StringSP CreateStructuredString() const; +}; + +class PythonByteArray : public PythonObject { +public: + PythonByteArray(); + explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes); + PythonByteArray(const uint8_t *bytes, size_t length); + PythonByteArray(PyRefType type, PyObject *o); + PythonByteArray(const PythonBytes &object); + + ~PythonByteArray() 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::ArrayRef<uint8_t> GetBytes() const; + + size_t GetSize() const; + + void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); + + StructuredData::StringSP CreateStructuredString() const; +}; + +class PythonString : public PythonObject { +public: + PythonString(); + explicit PythonString(llvm::StringRef string); + explicit PythonString(const char *string); + PythonString(PyRefType type, PyObject *o); + + ~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() 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 PythonBoolean : public PythonObject { +public: + PythonBoolean() = default; + explicit PythonBoolean(bool value); + PythonBoolean(PyRefType type, PyObject *o); + + ~PythonBoolean() override = default; + + 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; + + bool GetValue() const; + + void SetValue(bool value); + + StructuredData::BooleanSP CreateStructuredBoolean() const; +}; + +class PythonList : public PythonObject { +public: + PythonList() {} + explicit PythonList(PyInitialValue value); + explicit PythonList(int list_size); + PythonList(PyRefType type, PyObject *o); + + ~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(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() 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() 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 is_bound_method : 1; + bool has_varargs : 1; + bool has_kwargs : 1; + }; + + PythonCallable(); + PythonCallable(PyRefType type, PyObject *o); + + ~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); + + static uint32_t GetOptionsFromMode(llvm::StringRef mode); + + bool GetUnderlyingFile(File &file) const; +}; + +} // namespace lldb_private + +#endif + +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H |