[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