diff options
Diffstat (limited to 'python/google/protobuf/pyext/repeated_composite_container.cc')
-rw-r--r-- | python/google/protobuf/pyext/repeated_composite_container.cc | 173 |
1 files changed, 128 insertions, 45 deletions
diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc index 43a2bc12..5874d5de 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.cc +++ b/python/google/protobuf/pyext/repeated_composite_container.cc @@ -34,9 +34,6 @@ #include <google/protobuf/pyext/repeated_composite_container.h> #include <memory> -#ifndef _SHARED_PTR_H -#include <google/protobuf/stubs/shared_ptr.h> -#endif #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> @@ -46,7 +43,9 @@ #include <google/protobuf/pyext/descriptor.h> #include <google/protobuf/pyext/descriptor_pool.h> #include <google/protobuf/pyext/message.h> +#include <google/protobuf/pyext/message_factory.h> #include <google/protobuf/pyext/scoped_pyobject_ptr.h> +#include <google/protobuf/reflection.h> #if PY_MAJOR_VERSION >= 3 #define PyInt_Check PyLong_Check @@ -79,7 +78,10 @@ namespace repeated_composite_container { // --------------------------------------------------------------------- // len() -static Py_ssize_t Length(RepeatedCompositeContainer* self) { +static Py_ssize_t Length(PyObject* pself) { + RepeatedCompositeContainer* self = + reinterpret_cast<RepeatedCompositeContainer*>(pself); + Message* message = self->message; if (message != NULL) { return message->GetReflection()->FieldSize(*message, @@ -100,7 +102,7 @@ static int UpdateChildMessages(RepeatedCompositeContainer* self) { // A MergeFrom on a parent message could have caused extra messages to be // added in the underlying protobuf so add them to our list. They can never // be removed in such a way so there's no need to worry about that. - Py_ssize_t message_length = Length(self); + Py_ssize_t message_length = Length(reinterpret_cast<PyObject*>(self)); Py_ssize_t child_length = PyList_GET_SIZE(self->child_messages); Message* message = self->message; const Reflection* reflection = message->GetReflection(); @@ -136,9 +138,12 @@ static PyObject* AddToAttached(RepeatedCompositeContainer* self, if (cmessage::AssureWritable(self->parent) == -1) return NULL; Message* message = self->message; + Message* sub_message = - message->GetReflection()->AddMessage(message, - self->parent_field_descriptor); + message->GetReflection()->AddMessage( + message, + self->parent_field_descriptor, + self->child_message_class->py_message_factory->message_factory); CMessage* cmsg = cmessage::NewEmptyMessage(self->child_message_class); if (cmsg == NULL) return NULL; @@ -186,6 +191,10 @@ PyObject* Add(RepeatedCompositeContainer* self, return AddToAttached(self, args, kwargs); } +static PyObject* AddMethod(PyObject* self, PyObject* args, PyObject* kwargs) { + return Add(reinterpret_cast<RepeatedCompositeContainer*>(self), args, kwargs); +} + // --------------------------------------------------------------------- // extend() @@ -221,6 +230,10 @@ PyObject* Extend(RepeatedCompositeContainer* self, PyObject* value) { Py_RETURN_NONE; } +static PyObject* ExtendMethod(PyObject* self, PyObject* value) { + return Extend(reinterpret_cast<RepeatedCompositeContainer*>(self), value); +} + PyObject* MergeFrom(RepeatedCompositeContainer* self, PyObject* other) { if (UpdateChildMessages(self) < 0) { return NULL; @@ -228,6 +241,10 @@ PyObject* MergeFrom(RepeatedCompositeContainer* self, PyObject* other) { return Extend(self, other); } +static PyObject* MergeFromMethod(PyObject* self, PyObject* other) { + return MergeFrom(reinterpret_cast<RepeatedCompositeContainer*>(self), other); +} + PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* slice) { if (UpdateChildMessages(self) < 0) { return NULL; @@ -237,6 +254,10 @@ PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* slice) { return PyObject_GetItem(self->child_messages, slice); } +static PyObject* SubscriptMethod(PyObject* self, PyObject* slice) { + return Subscript(reinterpret_cast<RepeatedCompositeContainer*>(self), slice); +} + int AssignSubscript(RepeatedCompositeContainer* self, PyObject* slice, PyObject* value) { @@ -260,15 +281,16 @@ int AssignSubscript(RepeatedCompositeContainer* self, Py_ssize_t from; Py_ssize_t to; Py_ssize_t step; - Py_ssize_t length = Length(self); + Py_ssize_t length = Length(reinterpret_cast<PyObject*>(self)); Py_ssize_t slicelength; if (PySlice_Check(slice)) { #if PY_MAJOR_VERSION >= 3 if (PySlice_GetIndicesEx(slice, + length, &from, &to, &step, &slicelength) == -1) { #else if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice), -#endif length, &from, &to, &step, &slicelength) == -1) { +#endif return -1; } return PySequence_DelSlice(self->child_messages, from, to); @@ -284,7 +306,16 @@ int AssignSubscript(RepeatedCompositeContainer* self, return 0; } -static PyObject* Remove(RepeatedCompositeContainer* self, PyObject* value) { +static int AssignSubscriptMethod(PyObject* self, PyObject* slice, + PyObject* value) { + return AssignSubscript(reinterpret_cast<RepeatedCompositeContainer*>(self), + slice, value); +} + +static PyObject* Remove(PyObject* pself, PyObject* value) { + RepeatedCompositeContainer* self = + reinterpret_cast<RepeatedCompositeContainer*>(pself); + if (UpdateChildMessages(self) < 0) { return NULL; } @@ -299,9 +330,10 @@ static PyObject* Remove(RepeatedCompositeContainer* self, PyObject* value) { Py_RETURN_NONE; } -static PyObject* RichCompare(RepeatedCompositeContainer* self, - PyObject* other, - int opid) { +static PyObject* RichCompare(PyObject* pself, PyObject* other, int opid) { + RepeatedCompositeContainer* self = + reinterpret_cast<RepeatedCompositeContainer*>(pself); + if (UpdateChildMessages(self) < 0) { return NULL; } @@ -334,6 +366,19 @@ static PyObject* RichCompare(RepeatedCompositeContainer* self, } } +static PyObject* ToStr(PyObject* pself) { + ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); + if (full_slice == NULL) { + return NULL; + } + ScopedPyObjectPtr list(Subscript( + reinterpret_cast<RepeatedCompositeContainer*>(pself), full_slice.get())); + if (list == NULL) { + return NULL; + } + return PyObject_Repr(list.get()); +} + // --------------------------------------------------------------------- // sort() @@ -341,7 +386,7 @@ static void ReorderAttached(RepeatedCompositeContainer* self) { Message* message = self->message; const Reflection* reflection = message->GetReflection(); const FieldDescriptor* descriptor = self->parent_field_descriptor; - const Py_ssize_t length = Length(self); + const Py_ssize_t length = Length(reinterpret_cast<PyObject*>(self)); // Since Python protobuf objects are never arena-allocated, adding and // removing message pointers to the underlying array is just updating @@ -372,9 +417,10 @@ static int SortPythonMessages(RepeatedCompositeContainer* self, return 0; } -static PyObject* Sort(RepeatedCompositeContainer* self, - PyObject* args, - PyObject* kwds) { +static PyObject* Sort(PyObject* pself, PyObject* args, PyObject* kwds) { + RepeatedCompositeContainer* self = + reinterpret_cast<RepeatedCompositeContainer*>(pself); + // Support the old sort_function argument for backwards // compatibility. if (kwds != NULL) { @@ -398,11 +444,14 @@ static PyObject* Sort(RepeatedCompositeContainer* self, // --------------------------------------------------------------------- -static PyObject* Item(RepeatedCompositeContainer* self, Py_ssize_t index) { +static PyObject* Item(PyObject* pself, Py_ssize_t index) { + RepeatedCompositeContainer* self = + reinterpret_cast<RepeatedCompositeContainer*>(pself); + if (UpdateChildMessages(self) < 0) { return NULL; } - Py_ssize_t length = Length(self); + Py_ssize_t length = Length(pself); if (index < 0) { index = length + index; } @@ -414,17 +463,17 @@ static PyObject* Item(RepeatedCompositeContainer* self, Py_ssize_t index) { return item; } -static PyObject* Pop(RepeatedCompositeContainer* self, - PyObject* args) { +static PyObject* Pop(PyObject* pself, PyObject* args) { + RepeatedCompositeContainer* self = + reinterpret_cast<RepeatedCompositeContainer*>(pself); + Py_ssize_t index = -1; if (!PyArg_ParseTuple(args, "|n", &index)) { return NULL; } - PyObject* item = Item(self, index); + PyObject* item = Item(pself, index); if (item == NULL) { - PyErr_Format(PyExc_IndexError, - "list index (%zd) out of range", - index); + PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index); return NULL; } ScopedPyObjectPtr py_index(PyLong_FromSsize_t(index)); @@ -442,7 +491,7 @@ void ReleaseLastTo(CMessage* parent, GOOGLE_CHECK_NOTNULL(field); GOOGLE_CHECK_NOTNULL(target); - shared_ptr<Message> released_message( + CMessage::OwnerRef released_message( parent->message->GetReflection()->ReleaseLast(parent->message, field)); // TODO(tibell): Deal with proto1. @@ -485,8 +534,37 @@ int Release(RepeatedCompositeContainer* self) { return 0; } +PyObject* DeepCopy(PyObject* pself, PyObject* arg) { + RepeatedCompositeContainer* self = + reinterpret_cast<RepeatedCompositeContainer*>(pself); + + ScopedPyObjectPtr cloneObj( + PyType_GenericAlloc(&RepeatedCompositeContainer_Type, 0)); + if (cloneObj == NULL) { + return NULL; + } + RepeatedCompositeContainer* clone = + reinterpret_cast<RepeatedCompositeContainer*>(cloneObj.get()); + + Message* new_message = self->message->New(); + clone->parent = NULL; + clone->parent_field_descriptor = self->parent_field_descriptor; + clone->message = new_message; + clone->owner.reset(new_message); + Py_INCREF(self->child_message_class); + clone->child_message_class = self->child_message_class; + clone->child_messages = PyList_New(0); + + new_message->GetReflection() + ->GetMutableRepeatedFieldRef<Message>(new_message, + self->parent_field_descriptor) + .MergeFrom(self->message->GetReflection()->GetRepeatedFieldRef<Message>( + *self->message, self->parent_field_descriptor)); + return cloneObj.release(); +} + int SetOwner(RepeatedCompositeContainer* self, - const shared_ptr<Message>& new_owner) { + const CMessage::OwnerRef& new_owner) { GOOGLE_CHECK_ATTACHED(self); self->owner = new_owner; @@ -527,41 +605,46 @@ PyObject *NewContainer( return reinterpret_cast<PyObject*>(self); } -static void Dealloc(RepeatedCompositeContainer* self) { +static void Dealloc(PyObject* pself) { + RepeatedCompositeContainer* self = + reinterpret_cast<RepeatedCompositeContainer*>(pself); + Py_CLEAR(self->child_messages); Py_CLEAR(self->child_message_class); // TODO(tibell): Do we need to call delete on these objects to make // sure their destructors are called? self->owner.reset(); - Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); + Py_TYPE(self)->tp_free(pself); } static PySequenceMethods SqMethods = { - (lenfunc)Length, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - (ssizeargfunc)Item /* sq_item */ + Length, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + Item /* sq_item */ }; static PyMappingMethods MpMethods = { - (lenfunc)Length, /* mp_length */ - (binaryfunc)Subscript, /* mp_subscript */ - (objobjargproc)AssignSubscript,/* mp_ass_subscript */ + Length, /* mp_length */ + SubscriptMethod, /* mp_subscript */ + AssignSubscriptMethod, /* mp_ass_subscript */ }; static PyMethodDef Methods[] = { - { "add", (PyCFunction) Add, METH_VARARGS | METH_KEYWORDS, + { "__deepcopy__", DeepCopy, METH_VARARGS, + "Makes a deep copy of the class." }, + { "add", (PyCFunction)AddMethod, METH_VARARGS | METH_KEYWORDS, "Adds an object to the repeated container." }, - { "extend", (PyCFunction) Extend, METH_O, + { "extend", ExtendMethod, METH_O, "Adds objects to the repeated container." }, - { "pop", (PyCFunction)Pop, METH_VARARGS, + { "pop", Pop, METH_VARARGS, "Removes an object from the repeated container and returns it." }, - { "remove", (PyCFunction) Remove, METH_O, + { "remove", Remove, METH_O, "Removes an object from the repeated container." }, - { "sort", (PyCFunction) Sort, METH_VARARGS | METH_KEYWORDS, + { "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS, "Sorts the repeated container." }, - { "MergeFrom", (PyCFunction) MergeFrom, METH_O, + { "MergeFrom", MergeFromMethod, METH_O, "Adds objects to the repeated container." }, { NULL, NULL } }; @@ -573,12 +656,12 @@ PyTypeObject RepeatedCompositeContainer_Type = { FULL_MODULE_NAME ".RepeatedCompositeContainer", // tp_name sizeof(RepeatedCompositeContainer), // tp_basicsize 0, // tp_itemsize - (destructor)repeated_composite_container::Dealloc, // tp_dealloc + repeated_composite_container::Dealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr 0, // tp_compare - 0, // tp_repr + repeated_composite_container::ToStr, // tp_repr 0, // tp_as_number &repeated_composite_container::SqMethods, // tp_as_sequence &repeated_composite_container::MpMethods, // tp_as_mapping @@ -592,7 +675,7 @@ PyTypeObject RepeatedCompositeContainer_Type = { "A Repeated scalar container", // tp_doc 0, // tp_traverse 0, // tp_clear - (richcmpfunc)repeated_composite_container::RichCompare, // tp_richcompare + repeated_composite_container::RichCompare, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter 0, // tp_iternext |