forked from OSchip/llvm-project
Convert SWIG typemap string operations to PythonObjects.
llvm-svn: 250530
This commit is contained in:
parent
a6760f98cf
commit
7d6d218e12
|
@ -63,34 +63,38 @@
|
|||
int i;
|
||||
len = 0;
|
||||
while ($1[len]) len++;
|
||||
lldb_private::PythonList list(len);
|
||||
using namespace lldb_private;
|
||||
PythonList list(len);
|
||||
for (i = 0; i < len; i++)
|
||||
list.SetItemAtIndex(i, lldb_private::PythonString($1[i]));
|
||||
list.SetItemAtIndex(i, PythonString($1[i]));
|
||||
$result = list.release();
|
||||
}
|
||||
|
||||
%typemap(in) char const ** {
|
||||
/* Check if is a list */
|
||||
if (PyList_Check($input)) {
|
||||
int size = PyList_Size($input);
|
||||
int i = 0;
|
||||
$1 = (char **) malloc((size+1) * sizeof(char*));
|
||||
for (i = 0; i < size; i++) {
|
||||
PyObject *o = PyList_GetItem($input,i);
|
||||
if (PyString_Check(o))
|
||||
$1[i] = PyString_AsString(o);
|
||||
else {
|
||||
using namespace lldb_private;
|
||||
if (PythonList::Check($input)) {
|
||||
PythonList py_list(PyRefType::Borrowed, $input);
|
||||
int size = py_list.GetSize();
|
||||
|
||||
$1 = (char**)malloc((size+1)*sizeof(char*));
|
||||
for (int i = 0; i < size; i++) {
|
||||
PythonObject o = py_list.GetItemAtIndex(i);
|
||||
if (!PythonString::Check(o.get())) {
|
||||
PyErr_SetString(PyExc_TypeError,"list must contain strings");
|
||||
free($1);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
auto py_str = o.AsType<PythonString>();
|
||||
$1[i] = const_cast<char*>(py_str.GetString().data());
|
||||
}
|
||||
$1[i] = 0;
|
||||
|
||||
$1[size] = 0;
|
||||
} else if ($input == Py_None) {
|
||||
$1 = NULL;
|
||||
$1 = nullptr;
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError,"not a list");
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -501,12 +505,13 @@
|
|||
}
|
||||
|
||||
%typemap(in) FILE * {
|
||||
using namespace lldb_private;
|
||||
if ($input == Py_None)
|
||||
$1 = NULL;
|
||||
$1 = nullptr;
|
||||
else if (!lldb_private::PythonFile::Check($input)) {
|
||||
int fd = PyObject_AsFileDescriptor($input);
|
||||
lldb_private::PythonString py_mode(lldb_private::PyRefType::Owned,
|
||||
PyObject_GetAttrString($input, "mode"));
|
||||
PythonObject py_input(PyRefType::Borrowed, $input);
|
||||
PythonString py_mode = py_input.GetAttributeValue("mode").AsType<PythonString>();
|
||||
|
||||
if (-1 != fd && py_mode.IsValid()) {
|
||||
FILE *f;
|
||||
|
@ -521,10 +526,10 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
lldb_private::File file;
|
||||
lldb_private::PythonFile py_file(lldb_private::PyRefType::Borrowed, $input);
|
||||
if (!py_file.GetUnderlyingFile(file))
|
||||
return nullptr;
|
||||
PythonFile py_file(PyRefType::Borrowed, $input);
|
||||
File file;
|
||||
if (!py_file.GetUnderlyingFile(file))
|
||||
return nullptr;
|
||||
|
||||
$1 = file.GetStream();
|
||||
}
|
||||
|
@ -543,26 +548,34 @@
|
|||
else // if (flags & __SRW)
|
||||
mode[i++] = 'a';
|
||||
#endif
|
||||
lldb_private::File file($1, false);
|
||||
lldb_private::PythonFile py_file(file, mode);
|
||||
using namespace lldb_private;
|
||||
File file($1, false);
|
||||
PythonFile py_file(file, mode);
|
||||
$result = py_file.release();
|
||||
}
|
||||
|
||||
%typemap(in) (const char* string, int len) {
|
||||
using namespace lldb_private;
|
||||
if ($input == Py_None)
|
||||
{
|
||||
$1 = NULL;
|
||||
$2 = 0;
|
||||
}
|
||||
else if (PyUnicode_Check($input))
|
||||
else if (PythonString::Check($input))
|
||||
{
|
||||
$1 = PyString_AsString(PyUnicode_AsUTF8String($input));
|
||||
$2 = strlen($1);
|
||||
}
|
||||
else if (PyString_Check($input))
|
||||
{
|
||||
$1 = PyString_AsString($input);
|
||||
$2 = PyString_Size($input);
|
||||
PythonString py_str(PyRefType::Borrowed, $input);
|
||||
llvm::StringRef str = py_str.GetString();
|
||||
$1 = const_cast<char*>(str.data());
|
||||
$2 = str.size();
|
||||
// In Python 2, if $input is a PyUnicode object then this
|
||||
// will trigger a Unicode -> String conversion, in which
|
||||
// case the `PythonString` will now own the PyString. Thus
|
||||
// if it goes out of scope, the data will be deleted. The
|
||||
// only way to avoid this is to leak the Python object in
|
||||
// that case. Note that if there was no conversion, then
|
||||
// releasing the string will not leak anything, since we
|
||||
// created this as a borrowed reference.
|
||||
py_str.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -111,6 +111,20 @@ PythonObject::HasAttribute(llvm::StringRef attr) const
|
|||
return !!PyObject_HasAttr(m_py_obj, py_attr.get());
|
||||
}
|
||||
|
||||
PythonObject
|
||||
PythonObject::GetAttributeValue(llvm::StringRef attr) const
|
||||
{
|
||||
if (!IsValid())
|
||||
return PythonObject();
|
||||
|
||||
PythonString py_attr(attr);
|
||||
if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
|
||||
return PythonObject();
|
||||
|
||||
return PythonObject(PyRefType::Owned,
|
||||
PyObject_GetAttr(m_py_obj, py_attr.get()));
|
||||
}
|
||||
|
||||
bool
|
||||
PythonObject::IsNone() const
|
||||
{
|
||||
|
@ -191,11 +205,13 @@ PythonString::Check(PyObject *py_obj)
|
|||
if (!py_obj)
|
||||
return false;
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyUnicode_Check(py_obj);
|
||||
#else
|
||||
return PyString_Check(py_obj);
|
||||
if (PyUnicode_Check(py_obj))
|
||||
return true;
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
if (PyString_Check(py_obj))
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -210,7 +226,13 @@ PythonString::Reset(PyRefType type, PyObject *py_obj)
|
|||
PythonObject::Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
// In Python 2, Don't store PyUnicode objects directly, because we need
|
||||
// access to their underlying character buffers which Python 2 doesn't
|
||||
// provide.
|
||||
if (PyUnicode_Check(py_obj))
|
||||
result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
|
||||
#endif
|
||||
// Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
|
||||
// back into the virtual implementation.
|
||||
PythonObject::Reset(PyRefType::Borrowed, result.get());
|
||||
|
@ -271,6 +293,12 @@ PythonString::CreateStructuredString() const
|
|||
// PythonInteger
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
PythonInteger::PythonInteger()
|
||||
: PythonObject()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
|
||||
: PythonObject()
|
||||
{
|
||||
|
|
|
@ -201,6 +201,9 @@ public:
|
|||
bool
|
||||
HasAttribute(llvm::StringRef attribute) const;
|
||||
|
||||
PythonObject
|
||||
GetAttributeValue(llvm::StringRef attribute) const;
|
||||
|
||||
bool
|
||||
IsValid() const;
|
||||
|
||||
|
@ -210,6 +213,14 @@ public:
|
|||
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:
|
||||
|
|
|
@ -382,3 +382,14 @@ TEST_F(PythonDataObjectsTest, TestPythonFile)
|
|||
PythonFile py_file(file, "r");
|
||||
EXPECT_TRUE(PythonFile::Check(py_file.get()));
|
||||
}
|
||||
|
||||
TEST_F(PythonDataObjectsTest, TestObjectAttributes)
|
||||
{
|
||||
PythonInteger py_int(42);
|
||||
EXPECT_TRUE(py_int.HasAttribute("numerator"));
|
||||
EXPECT_FALSE(py_int.HasAttribute("this_should_not_exist"));
|
||||
|
||||
PythonInteger numerator_attr = py_int.GetAttributeValue("numerator").AsType<PythonInteger>();
|
||||
EXPECT_TRUE(numerator_attr.IsAllocated());
|
||||
EXPECT_EQ(42, numerator_attr.GetInteger());
|
||||
}
|
Loading…
Reference in New Issue