summaryrefslogtreecommitdiff
path: root/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp')
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp138
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();
}