diff options
Diffstat (limited to 'source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp')
-rw-r--r-- | source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp | 138 |
1 files changed, 134 insertions, 4 deletions
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index 23bacc932c03..1fdf4c70a5dc 100644 --- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -19,10 +19,15 @@ #include "lldb/Core/Stream.h" #include "lldb/Host/File.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Interpreter/ScriptInterpreter.h" +#include "llvm/Support/ConvertUTF.h" + #include <stdio.h> +#include "llvm/ADT/StringSwitch.h" + using namespace lldb_private; using namespace lldb; @@ -81,6 +86,8 @@ PythonObject::GetObjectType() const if (PythonBytes::Check(m_py_obj)) return PyObjectType::Bytes; #endif + if (PythonByteArray::Check(m_py_obj)) + return PyObjectType::ByteArray; if (PythonInteger::Check(m_py_obj)) return PyObjectType::Integer; if (PythonFile::Check(m_py_obj)) @@ -216,6 +223,8 @@ PythonObject::CreateStructuredObject() const return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); case PyObjectType::Bytes: return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); + case PyObjectType::ByteArray: + return PythonByteArray(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); case PyObjectType::None: return StructuredData::ObjectSP(); default: @@ -321,6 +330,87 @@ PythonBytes::CreateStructuredString() const return result; } +PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) : PythonByteArray(bytes.data(), bytes.size()) +{ +} + +PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) +{ + const char *str = reinterpret_cast<const char *>(bytes); + Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length)); +} + +PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) +{ + Reset(type, o); +} + +PythonByteArray::PythonByteArray(const PythonBytes &object) : PythonObject(object) +{ +} + +PythonByteArray::~PythonByteArray() +{ +} + +bool +PythonByteArray::Check(PyObject *py_obj) +{ + if (!py_obj) + return false; + if (PyByteArray_Check(py_obj)) + return true; + return false; +} + +void +PythonByteArray::Reset(PyRefType type, PyObject *py_obj) +{ + // Grab the desired reference type so that if we end up rejecting + // `py_obj` it still gets decremented if necessary. + PythonObject result(type, py_obj); + + if (!PythonByteArray::Check(py_obj)) + { + PythonObject::Reset(); + return; + } + + // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls + // back into the virtual implementation. + PythonObject::Reset(PyRefType::Borrowed, result.get()); +} + +llvm::ArrayRef<uint8_t> +PythonByteArray::GetBytes() const +{ + if (!IsValid()) + return llvm::ArrayRef<uint8_t>(); + + char *c = PyByteArray_AsString(m_py_obj); + size_t size = GetSize(); + return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size); +} + +size_t +PythonByteArray::GetSize() const +{ + if (!IsValid()) + return 0; + + return PyByteArray_Size(m_py_obj); +} + +StructuredData::StringSP +PythonByteArray::CreateStructuredString() const +{ + StructuredData::StringSP result(new StructuredData::String); + llvm::ArrayRef<uint8_t> bytes = GetBytes(); + const char *str = reinterpret_cast<const char *>(bytes.data()); + result->SetValue(std::string(str, bytes.size())); + return result; +} + //---------------------------------------------------------------------- // PythonString //---------------------------------------------------------------------- @@ -1019,13 +1109,37 @@ PythonCallable::Reset(PyRefType type, PyObject *py_obj) PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { - ArgInfo result = { 0, false, false }; + ArgInfo result = { 0, false, false, false }; if (!IsValid()) return result; PyObject *py_func_obj = m_py_obj; if (PyMethod_Check(py_func_obj)) + { py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); + PythonObject im_self = GetAttributeValue("im_self"); + if (im_self.IsValid() && !im_self.IsNone()) + result.is_bound_method = true; + } + else + { + // see if this is a callable object with an __call__ method + if (!PyFunction_Check(py_func_obj)) + { + PythonObject __call__ = GetAttributeValue("__call__"); + if (__call__.IsValid()) + { + auto __callable__ = __call__.AsType<PythonCallable>(); + if (__callable__.IsValid()) + { + py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); + PythonObject im_self = GetAttributeValue("im_self"); + if (im_self.IsValid() && !im_self.IsNone()) + result.is_bound_method = true; + } + } + } + } if (!py_func_obj) return result; @@ -1075,9 +1189,7 @@ PythonFile::PythonFile(File &file, const char *mode) PythonFile::PythonFile(const char *path, const char *mode) { - FILE *fp = nullptr; - fp = fopen(path, mode); - lldb_private::File file(fp, true); + lldb_private::File file(path, GetOptionsFromMode(mode)); Reset(file, mode); } @@ -1156,6 +1268,22 @@ PythonFile::Reset(File &file, const char *mode) #endif } +uint32_t +PythonFile::GetOptionsFromMode(llvm::StringRef mode) +{ + if (mode.empty()) + return 0; + + return llvm::StringSwitch<uint32_t>(mode.str().c_str()) + .Case("r", File::eOpenOptionRead) + .Case("w", File::eOpenOptionWrite) + .Case("a", File::eOpenOptionWrite|File::eOpenOptionAppend|File::eOpenOptionCanCreate) + .Case("r+", File::eOpenOptionRead|File::eOpenOptionWrite) + .Case("w+", File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionCanCreate|File::eOpenOptionTruncate) + .Case("a+", File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionAppend|File::eOpenOptionCanCreate) + .Default(0); +} + bool PythonFile::GetUnderlyingFile(File &file) const { @@ -1166,6 +1294,8 @@ PythonFile::GetUnderlyingFile(File &file) const // We don't own the file descriptor returned by this function, make sure the // File object knows about that. file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); + PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); + file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString())); return file.IsValid(); } |