[Lldb-commits] [lldb] r257397 - Introduce a PythonBytes class into PythonDataObjects.
Zachary Turner via lldb-commits
lldb-commits at lists.llvm.org
Mon Jan 11 14:16:12 PST 2016
Author: zturner
Date: Mon Jan 11 16:16:12 2016
New Revision: 257397
URL: http://llvm.org/viewvc/llvm-project?rev=257397&view=rev
Log:
Introduce a PythonBytes class into PythonDataObjects.
This class behaves the same as PythonString on Python2, but differently
on Python3. Unittests are added as well.
Modified:
lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp?rev=257397&r1=257396&r2=257397&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp Mon Jan 11 16:16:12 2016
@@ -77,6 +77,10 @@ PythonObject::GetObjectType() const
return PyObjectType::Dictionary;
if (PythonString::Check(m_py_obj))
return PyObjectType::String;
+#if PY_MAJOR_VERSION >= 3
+ if (PythonBytes::Check(m_py_obj))
+ return PyObjectType::Bytes;
+#endif
if (PythonInteger::Check(m_py_obj))
return PyObjectType::Integer;
if (PythonFile::Check(m_py_obj))
@@ -210,6 +214,8 @@ PythonObject::CreateStructuredObject() c
return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
case PyObjectType::String:
return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
+ case PyObjectType::Bytes:
+ return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
case PyObjectType::None:
return StructuredData::ObjectSP();
default:
@@ -218,6 +224,104 @@ PythonObject::CreateStructuredObject() c
}
//----------------------------------------------------------------------
+// PythonString
+//----------------------------------------------------------------------
+PythonBytes::PythonBytes() : PythonObject()
+{
+}
+
+PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject()
+{
+ SetBytes(bytes);
+}
+
+PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject()
+{
+ SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
+}
+
+PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject()
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
+}
+
+PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object)
+{
+}
+
+PythonBytes::~PythonBytes()
+{
+}
+
+bool
+PythonBytes::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+ if (PyBytes_Check(py_obj))
+ return true;
+ return false;
+}
+
+void
+PythonBytes::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 (!PythonBytes::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>
+PythonBytes::GetBytes() const
+{
+ if (!IsValid())
+ return llvm::ArrayRef<uint8_t>();
+
+ Py_ssize_t size;
+ char *c;
+
+ PyBytes_AsStringAndSize(m_py_obj, &c, &size);
+ return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
+}
+
+size_t
+PythonBytes::GetSize() const
+{
+ if (!IsValid())
+ return 0;
+ return PyBytes_Size(m_py_obj);
+}
+
+void
+PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes)
+{
+ const char *data = reinterpret_cast<const char *>(bytes.data());
+ PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
+ PythonObject::Reset(PyRefType::Owned, py_bytes);
+}
+
+StructuredData::StringSP
+PythonBytes::CreateStructuredString() const
+{
+ StructuredData::StringSP result(new StructuredData::String);
+ Py_ssize_t size;
+ char *c;
+ PyBytes_AsStringAndSize(m_py_obj, &c, &size);
+ result->SetValue(std::string(c, size));
+ return result;
+}
+
+//----------------------------------------------------------------------
// PythonString
//----------------------------------------------------------------------
Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h?rev=257397&r1=257396&r2=257397&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h (original)
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h Mon Jan 11 16:16:12 2016
@@ -23,8 +23,11 @@
#include "lldb/Host/File.h"
#include "lldb/Interpreter/OptionValue.h"
+#include "llvm/ADT/ArrayRef.h"
+
namespace lldb_private {
+class PythonBytes;
class PythonString;
class PythonList;
class PythonDictionary;
@@ -71,6 +74,11 @@ enum class PyObjectType
Dictionary,
List,
String,
+#if PY_MAJOR_VERSION >= 3
+ Bytes,
+#else
+ Bytes = String,
+#endif
Module,
Callable,
Tuple,
@@ -256,6 +264,39 @@ 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(const PythonBytes &object);
+
+ ~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 PythonString : public PythonObject
{
public:
Modified: lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp?rev=257397&r1=257396&r2=257397&view=diff
==============================================================================
--- lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp (original)
+++ lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp Mon Jan 11 16:16:12 2016
@@ -203,6 +203,27 @@ TEST_F(PythonDataObjectsTest, TestPython
EXPECT_EQ(7, constructed_int.GetInteger());
}
+TEST_F(PythonDataObjectsTest, TestPythonBytes)
+{
+ static const char *test_bytes = "PythonDataObjectsTest::TestPythonBytes";
+ PyObject *py_bytes = PyBytes_FromString(test_bytes);
+ EXPECT_TRUE(PythonBytes::Check(py_bytes));
+ PythonBytes python_bytes(PyRefType::Owned, py_bytes);
+ EXPECT_EQ(PyObjectType::Bytes, python_bytes.GetObjectType());
+
+#if PY_MAJOR_VERSION < 3
+ EXPECT_TRUE(PythonString::Check(py_bytes));
+ EXPECT_EQ(PyObjectType::String, python_bytes.GetObjectType());
+#else
+ EXPECT_FALSE(PythonString::Check(py_bytes));
+ EXPECT_NE(PyObjectType::String, python_bytes.GetObjectType());
+#endif
+
+ llvm::ArrayRef<uint8_t> bytes = python_bytes.GetBytes();
+ EXPECT_EQ(bytes.size(), strlen(test_bytes));
+ EXPECT_EQ(0, ::memcmp(bytes.data(), test_bytes, bytes.size()));
+}
+
TEST_F(PythonDataObjectsTest, TestPythonString)
{
// Test that strings behave correctly when wrapped by a PythonString.
More information about the lldb-commits
mailing list