diff options
Diffstat (limited to 'python/google/protobuf/pyext')
-rw-r--r-- | python/google/protobuf/pyext/descriptor.cc | 93 | ||||
-rw-r--r-- | python/google/protobuf/pyext/descriptor_containers.cc | 530 | ||||
-rw-r--r-- | python/google/protobuf/pyext/descriptor_pool.cc | 122 | ||||
-rw-r--r-- | python/google/protobuf/pyext/extension_dict.cc | 3 | ||||
-rw-r--r-- | python/google/protobuf/pyext/extension_dict.h | 15 | ||||
-rw-r--r-- | python/google/protobuf/pyext/map_container.cc | 29 | ||||
-rw-r--r-- | python/google/protobuf/pyext/map_container.h | 17 | ||||
-rw-r--r-- | python/google/protobuf/pyext/message.cc | 141 | ||||
-rw-r--r-- | python/google/protobuf/pyext/message.h | 46 | ||||
-rw-r--r-- | python/google/protobuf/pyext/message_factory.cc | 8 | ||||
-rw-r--r-- | python/google/protobuf/pyext/message_module.cc | 17 | ||||
-rw-r--r-- | python/google/protobuf/pyext/repeated_composite_container.cc | 129 | ||||
-rw-r--r-- | python/google/protobuf/pyext/repeated_composite_container.h | 21 | ||||
-rw-r--r-- | python/google/protobuf/pyext/repeated_scalar_container.cc | 162 | ||||
-rw-r--r-- | python/google/protobuf/pyext/repeated_scalar_container.h | 19 | ||||
-rw-r--r-- | python/google/protobuf/pyext/thread_unsafe_shared_ptr.h | 104 |
16 files changed, 853 insertions, 603 deletions
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc index 9634ea05..8af0cb12 100644 --- a/python/google/protobuf/pyext/descriptor.cc +++ b/python/google/protobuf/pyext/descriptor.cc @@ -107,10 +107,6 @@ bool _CalledFromGeneratedFile(int stacklevel) { return false; } } - if (frame->f_globals != frame->f_locals) { - // Not at global module scope - return false; - } if (frame->f_code->co_filename == NULL) { return false; @@ -123,6 +119,10 @@ bool _CalledFromGeneratedFile(int stacklevel) { PyErr_Clear(); return false; } + if ((filename_size < 3) || (strcmp(&filename[filename_size - 3], ".py") != 0)) { + // Cython's stack does not have .py file name and is not at global module scope. + return true; + } if (filename_size < 7) { // filename is too short. return false; @@ -131,6 +131,11 @@ bool _CalledFromGeneratedFile(int stacklevel) { // Filename is not ending with _pb2. return false; } + + if (frame->f_globals != frame->f_locals) { + // Not at global module scope + return false; + } #endif return true; } @@ -188,39 +193,36 @@ const FileDescriptor* GetFileDescriptor(const MethodDescriptor* descriptor) { // Always returns a new reference. template<class DescriptorClass> static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) { - // Options (and their extensions) are completely resolved in the proto file - // containing the descriptor. - PyDescriptorPool* pool = GetDescriptorPool_FromPool( + // Options are cached in the pool that owns the descriptor. + // First search in the cache. + PyDescriptorPool* caching_pool = GetDescriptorPool_FromPool( GetFileDescriptor(descriptor)->pool()); - hash_map<const void*, PyObject*>* descriptor_options = - pool->descriptor_options; - // First search in the cache. + caching_pool->descriptor_options; if (descriptor_options->find(descriptor) != descriptor_options->end()) { PyObject *value = (*descriptor_options)[descriptor]; Py_INCREF(value); return value; } + // Similar to the C++ implementation, we return an Options object from the + // default (generated) factory, so that client code know that they can use + // extensions from generated files: + // d.GetOptions().Extensions[some_pb2.extension] + // + // The consequence is that extensions not defined in the default pool won't + // be available. If needed, we could add an optional 'message_factory' + // parameter to the GetOptions() function. + PyMessageFactory* message_factory = + GetDefaultDescriptorPool()->py_message_factory; + // Build the Options object: get its Python class, and make a copy of the C++ // read-only instance. const Message& options(descriptor->options()); const Descriptor *message_type = options.GetDescriptor(); - PyMessageFactory* message_factory = pool->py_message_factory; - CMessageClass* message_class = message_factory::GetMessageClass( + CMessageClass* message_class = message_factory::GetOrCreateMessageClass( message_factory, message_type); if (message_class == NULL) { - // The Options message was not found in the current DescriptorPool. - // This means that the pool cannot contain any extensions to the Options - // message either, so falling back to the basic pool we can only increase - // the chances of successfully parsing the options. - PyErr_Clear(); - pool = GetDefaultDescriptorPool(); - message_factory = pool->py_message_factory; - message_class = message_factory::GetMessageClass( - message_factory, message_type); - } - if (message_class == NULL) { PyErr_Format(PyExc_TypeError, "Could not retrieve class for Options: %s", message_type->full_name().c_str()); return NULL; @@ -248,7 +250,8 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) { options.SerializeToString(&serialized); io::CodedInputStream input( reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size()); - input.SetExtensionRegistry(pool->pool, message_factory->message_factory); + input.SetExtensionRegistry(message_factory->pool->pool, + message_factory->message_factory); bool success = cmsg->message->MergePartialFromCodedStream(&input); if (!success) { PyErr_Format(PyExc_ValueError, "Error parsing Options message"); @@ -564,6 +567,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} + static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) { return CopyToPythonProto<DescriptorProto>(_GetDescriptor(self), target); } @@ -623,6 +631,8 @@ static PyGetSetDef Getters[] = { { "is_extendable", (getter)IsExtendable, (setter)NULL}, { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, { "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"}, {NULL} }; @@ -785,7 +795,7 @@ static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) { break; } case FieldDescriptor::CPPTYPE_STRING: { - string value = _GetDescriptor(self)->default_value_string(); + const string& value = _GetDescriptor(self)->default_value_string(); result = ToStringObject(_GetDescriptor(self), value); break; } @@ -897,6 +907,10 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} static PyGetSetDef Getters[] = { { "full_name", (getter)GetFullName, NULL, "Full name"}, @@ -926,6 +940,8 @@ static PyGetSetDef Getters[] = { "Containing oneof"}, { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, {NULL} }; @@ -1055,6 +1071,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} + static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) { return CopyToPythonProto<EnumDescriptorProto>(_GetDescriptor(self), target); } @@ -1079,6 +1100,8 @@ static PyGetSetDef Getters[] = { "Containing type"}, { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, {NULL} }; @@ -1179,6 +1202,10 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} static PyGetSetDef Getters[] = { { "name", (getter)GetName, NULL, "name"}, @@ -1188,6 +1215,8 @@ static PyGetSetDef Getters[] = { { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, {NULL} }; @@ -1330,6 +1359,11 @@ static int SetOptions(PyFileDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyFileDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} + static PyObject* GetSyntax(PyFileDescriptor *self, void *closure) { return PyString_InternFromString( FileDescriptor::SyntaxName(_GetDescriptor(self)->syntax())); @@ -1355,6 +1389,8 @@ static PyGetSetDef Getters[] = { { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, { "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"}, {NULL} }; @@ -1500,6 +1536,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} + static PyGetSetDef Getters[] = { { "name", (getter)GetName, NULL, "Name"}, { "full_name", (getter)GetFullName, NULL, "Full name"}, @@ -1508,6 +1549,8 @@ static PyGetSetDef Getters[] = { { "containing_type", (getter)GetContainingType, NULL, "Containing type"}, { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, { "fields", (getter)GetFields, NULL, "Fields"}, {NULL} }; diff --git a/python/google/protobuf/pyext/descriptor_containers.cc b/python/google/protobuf/pyext/descriptor_containers.cc index d0aae9c9..bc007f7e 100644 --- a/python/google/protobuf/pyext/descriptor_containers.cc +++ b/python/google/protobuf/pyext/descriptor_containers.cc @@ -957,55 +957,55 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->field_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, const string& name) { return GetDescriptor(self)->FindFieldByName(name); } -static ItemDescriptor GetByCamelcaseName(PyContainer* self, +static const void* GetByCamelcaseName(PyContainer* self, const string& name) { return GetDescriptor(self)->FindFieldByCamelcaseName(name); } -static ItemDescriptor GetByNumber(PyContainer* self, int number) { +static const void* GetByNumber(PyContainer* self, int number) { return GetDescriptor(self)->FindFieldByNumber(number); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->field(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFieldDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyFieldDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const string& GetItemName(const void* item) { + return static_cast<ItemDescriptor>(item)->name(); } -static const string& GetItemCamelcaseName(ItemDescriptor item) { - return item->camelcase_name(); +static const string& GetItemCamelcaseName(const void* item) { + return static_cast<ItemDescriptor>(item)->camelcase_name(); } -static int GetItemNumber(ItemDescriptor item) { - return item->number(); +static int GetItemNumber(const void* item) { + return static_cast<ItemDescriptor>(item)->number(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast<ItemDescriptor>(item)->index(); } static DescriptorContainerDef ContainerDef = { "MessageFields", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)GetByCamelcaseName, - (GetByNumberMethod)GetByNumber, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)GetItemCamelcaseName, - (GetItemNumberMethod)GetItemNumber, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + GetByCamelcaseName, + GetByNumber, + NewObjectFromItem, + GetItemName, + GetItemCamelcaseName, + GetItemNumber, + GetItemIndex, }; } // namespace fields @@ -1035,38 +1035,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->nested_type_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, const string& name) { return GetDescriptor(self)->FindNestedTypeByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->nested_type(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyMessageDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyMessageDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const string& GetItemName(const void* item) { + return static_cast<ItemDescriptor>(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast<ItemDescriptor>(item)->index(); } static DescriptorContainerDef ContainerDef = { "MessageNestedTypes", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace nested_types @@ -1087,38 +1087,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->enum_type_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, const string& name) { return GetDescriptor(self)->FindEnumTypeByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->enum_type(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyEnumDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyEnumDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const string& GetItemName(const void* item) { + return static_cast<ItemDescriptor>(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast<ItemDescriptor>(item)->index(); } static DescriptorContainerDef ContainerDef = { "MessageNestedEnums", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace enums @@ -1150,11 +1150,11 @@ static int Count(PyContainer* self) { return count; } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, const string& name) { return GetDescriptor(self)->FindEnumValueByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { // This is not optimal, but the number of enums *types* in a given message // is small. This function is only used when iterating over the mapping. const EnumDescriptor* enum_type = NULL; @@ -1173,26 +1173,27 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) { return enum_type->value(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyEnumValueDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyEnumValueDescriptor_FromDescriptor( + static_cast<ItemDescriptor>(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const string& GetItemName(const void* item) { + return static_cast<ItemDescriptor>(item)->name(); } static DescriptorContainerDef ContainerDef = { "MessageEnumValues", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)NULL, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + NULL, }; } // namespace enumvalues @@ -1209,38 +1210,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->extension_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, const string& name) { return GetDescriptor(self)->FindExtensionByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->extension(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFieldDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyFieldDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const string& GetItemName(const void* item) { + return static_cast<ItemDescriptor>(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast<ItemDescriptor>(item)->index(); } static DescriptorContainerDef ContainerDef = { "MessageExtensions", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace extensions @@ -1261,38 +1262,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->oneof_decl_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, const string& name) { return GetDescriptor(self)->FindOneofByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->oneof_decl(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyOneofDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyOneofDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const string& GetItemName(const void* item) { + return static_cast<ItemDescriptor>(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast<ItemDescriptor>(item)->index(); } static DescriptorContainerDef ContainerDef = { "MessageOneofs", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace oneofs @@ -1323,46 +1324,47 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->value_count(); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->value(index); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, const string& name) { return GetDescriptor(self)->FindValueByName(name); } -static ItemDescriptor GetByNumber(PyContainer* self, int number) { +static const void* GetByNumber(PyContainer* self, int number) { return GetDescriptor(self)->FindValueByNumber(number); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyEnumValueDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyEnumValueDescriptor_FromDescriptor( + static_cast<ItemDescriptor>(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const string& GetItemName(const void* item) { + return static_cast<ItemDescriptor>(item)->name(); } -static int GetItemNumber(ItemDescriptor item) { - return item->number(); +static int GetItemNumber(const void* item) { + return static_cast<ItemDescriptor>(item)->number(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast<ItemDescriptor>(item)->index(); } static DescriptorContainerDef ContainerDef = { "EnumValues", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)GetByNumber, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)GetItemNumber, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + GetByNumber, + NewObjectFromItem, + GetItemName, + NULL, + GetItemNumber, + GetItemIndex, }; } // namespace enumvalues @@ -1397,30 +1399,30 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->field_count(); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->field(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFieldDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyFieldDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item)); } -static int GetItemIndex(ItemDescriptor item) { - return item->index_in_oneof(); +static int GetItemIndex(const void* item) { + return static_cast<ItemDescriptor>(item)->index_in_oneof(); } static DescriptorContainerDef ContainerDef = { "OneofFields", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)NULL, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)NULL, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + NULL, + NULL, + NULL, + NewObjectFromItem, + NULL, + NULL, + NULL, + GetItemIndex, }; } // namespace fields @@ -1447,38 +1449,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->method_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, const string& name) { return GetDescriptor(self)->FindMethodByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->method(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyMethodDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyMethodDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const string& GetItemName(const void* item) { + return static_cast<ItemDescriptor>(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast<ItemDescriptor>(item)->index(); } static DescriptorContainerDef ContainerDef = { "ServiceMethods", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace methods @@ -1509,38 +1511,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->message_type_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, const string& name) { return GetDescriptor(self)->FindMessageTypeByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->message_type(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyMessageDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyMessageDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const string& GetItemName(const void* item) { + return static_cast<ItemDescriptor>(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast<ItemDescriptor>(item)->index(); } static DescriptorContainerDef ContainerDef = { "FileMessages", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace messages @@ -1557,38 +1559,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->enum_type_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, const string& name) { return GetDescriptor(self)->FindEnumTypeByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->enum_type(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyEnumDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyEnumDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const string& GetItemName(const void* item) { + return static_cast<ItemDescriptor>(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast<ItemDescriptor>(item)->index(); } static DescriptorContainerDef ContainerDef = { "FileEnums", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace enums @@ -1605,38 +1607,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->extension_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, const string& name) { return GetDescriptor(self)->FindExtensionByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->extension(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFieldDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyFieldDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const string& GetItemName(const void* item) { + return static_cast<ItemDescriptor>(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast<ItemDescriptor>(item)->index(); } static DescriptorContainerDef ContainerDef = { "FileExtensions", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace extensions @@ -1653,38 +1655,38 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->service_count(); } -static ItemDescriptor GetByName(PyContainer* self, const string& name) { +static const void* GetByName(PyContainer* self, const string& name) { return GetDescriptor(self)->FindServiceByName(name); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->service(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyServiceDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyServiceDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item)); } -static const string& GetItemName(ItemDescriptor item) { - return item->name(); +static const string& GetItemName(const void* item) { + return static_cast<ItemDescriptor>(item)->name(); } -static int GetItemIndex(ItemDescriptor item) { - return item->index(); +static int GetItemIndex(const void* item) { + return static_cast<ItemDescriptor>(item)->index(); } static DescriptorContainerDef ContainerDef = { "FileServices", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)GetByName, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)GetItemName, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)GetItemIndex, + Count, + GetByIndex, + GetByName, + NULL, + NULL, + NewObjectFromItem, + GetItemName, + NULL, + NULL, + GetItemIndex, }; } // namespace services @@ -1701,26 +1703,26 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->dependency_count(); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->dependency(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFileDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyFileDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item)); } static DescriptorContainerDef ContainerDef = { "FileDependencies", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)NULL, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)NULL, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)NULL, + Count, + GetByIndex, + NULL, + NULL, + NULL, + NewObjectFromItem, + NULL, + NULL, + NULL, + NULL, }; } // namespace dependencies @@ -1737,26 +1739,26 @@ static int Count(PyContainer* self) { return GetDescriptor(self)->public_dependency_count(); } -static ItemDescriptor GetByIndex(PyContainer* self, int index) { +static const void* GetByIndex(PyContainer* self, int index) { return GetDescriptor(self)->public_dependency(index); } -static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFileDescriptor_FromDescriptor(item); +static PyObject* NewObjectFromItem(const void* item) { + return PyFileDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item)); } static DescriptorContainerDef ContainerDef = { "FilePublicDependencies", - (CountMethod)Count, - (GetByIndexMethod)GetByIndex, - (GetByNameMethod)NULL, - (GetByCamelcaseNameMethod)NULL, - (GetByNumberMethod)NULL, - (NewObjectFromItemMethod)NewObjectFromItem, - (GetItemNameMethod)NULL, - (GetItemCamelcaseNameMethod)NULL, - (GetItemNumberMethod)NULL, - (GetItemIndexMethod)NULL, + Count, + GetByIndex, + NULL, + NULL, + NULL, + NewObjectFromItem, + NULL, + NULL, + NULL, + NULL, }; } // namespace public_dependencies diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc index 16f4d49d..95882aeb 100644 --- a/python/google/protobuf/pyext/descriptor_pool.cc +++ b/python/google/protobuf/pyext/descriptor_pool.cc @@ -149,7 +149,8 @@ static PyObject* New(PyTypeObject* type, PyDescriptorPool_NewWithDatabase(database)); } -static void Dealloc(PyDescriptorPool* self) { +static void Dealloc(PyObject* pself) { + PyDescriptorPool* self = reinterpret_cast<PyDescriptorPool*>(pself); descriptor_pool_map.erase(self->pool); Py_CLEAR(self->py_message_factory); for (hash_map<const void*, PyObject*>::iterator it = @@ -163,7 +164,7 @@ static void Dealloc(PyDescriptorPool* self) { Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); } -PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) { +static PyObject* FindMessageByName(PyObject* self, PyObject* arg) { Py_ssize_t name_size; char* name; if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { @@ -171,7 +172,8 @@ PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) { } const Descriptor* message_descriptor = - self->pool->FindMessageTypeByName(string(name, name_size)); + reinterpret_cast<PyDescriptorPool*>(self)->pool->FindMessageTypeByName( + string(name, name_size)); if (message_descriptor == NULL) { PyErr_Format(PyExc_KeyError, "Couldn't find message %.200s", name); @@ -184,7 +186,7 @@ PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) { -PyObject* FindFileByName(PyDescriptorPool* self, PyObject* arg) { +static PyObject* FindFileByName(PyObject* self, PyObject* arg) { Py_ssize_t name_size; char* name; if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { @@ -192,7 +194,8 @@ PyObject* FindFileByName(PyDescriptorPool* self, PyObject* arg) { } const FileDescriptor* file_descriptor = - self->pool->FindFileByName(string(name, name_size)); + reinterpret_cast<PyDescriptorPool*>(self)->pool->FindFileByName( + string(name, name_size)); if (file_descriptor == NULL) { PyErr_Format(PyExc_KeyError, "Couldn't find file %.200s", name); return NULL; @@ -218,6 +221,10 @@ PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* arg) { return PyFieldDescriptor_FromDescriptor(field_descriptor); } +static PyObject* FindFieldByNameMethod(PyObject* self, PyObject* arg) { + return FindFieldByName(reinterpret_cast<PyDescriptorPool*>(self), arg); +} + PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) { Py_ssize_t name_size; char* name; @@ -235,6 +242,10 @@ PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) { return PyFieldDescriptor_FromDescriptor(field_descriptor); } +static PyObject* FindExtensionByNameMethod(PyObject* self, PyObject* arg) { + return FindExtensionByName(reinterpret_cast<PyDescriptorPool*>(self), arg); +} + PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) { Py_ssize_t name_size; char* name; @@ -252,6 +263,10 @@ PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) { return PyEnumDescriptor_FromDescriptor(enum_descriptor); } +static PyObject* FindEnumTypeByNameMethod(PyObject* self, PyObject* arg) { + return FindEnumTypeByName(reinterpret_cast<PyDescriptorPool*>(self), arg); +} + PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) { Py_ssize_t name_size; char* name; @@ -269,7 +284,11 @@ PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) { return PyOneofDescriptor_FromDescriptor(oneof_descriptor); } -PyObject* FindServiceByName(PyDescriptorPool* self, PyObject* arg) { +static PyObject* FindOneofByNameMethod(PyObject* self, PyObject* arg) { + return FindOneofByName(reinterpret_cast<PyDescriptorPool*>(self), arg); +} + +static PyObject* FindServiceByName(PyObject* self, PyObject* arg) { Py_ssize_t name_size; char* name; if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { @@ -277,7 +296,8 @@ PyObject* FindServiceByName(PyDescriptorPool* self, PyObject* arg) { } const ServiceDescriptor* service_descriptor = - self->pool->FindServiceByName(string(name, name_size)); + reinterpret_cast<PyDescriptorPool*>(self)->pool->FindServiceByName( + string(name, name_size)); if (service_descriptor == NULL) { PyErr_Format(PyExc_KeyError, "Couldn't find service %.200s", name); return NULL; @@ -286,7 +306,7 @@ PyObject* FindServiceByName(PyDescriptorPool* self, PyObject* arg) { return PyServiceDescriptor_FromDescriptor(service_descriptor); } -PyObject* FindMethodByName(PyDescriptorPool* self, PyObject* arg) { +static PyObject* FindMethodByName(PyObject* self, PyObject* arg) { Py_ssize_t name_size; char* name; if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { @@ -294,7 +314,8 @@ PyObject* FindMethodByName(PyDescriptorPool* self, PyObject* arg) { } const MethodDescriptor* method_descriptor = - self->pool->FindMethodByName(string(name, name_size)); + reinterpret_cast<PyDescriptorPool*>(self)->pool->FindMethodByName( + string(name, name_size)); if (method_descriptor == NULL) { PyErr_Format(PyExc_KeyError, "Couldn't find method %.200s", name); return NULL; @@ -303,7 +324,7 @@ PyObject* FindMethodByName(PyDescriptorPool* self, PyObject* arg) { return PyMethodDescriptor_FromDescriptor(method_descriptor); } -PyObject* FindFileContainingSymbol(PyDescriptorPool* self, PyObject* arg) { +static PyObject* FindFileContainingSymbol(PyObject* self, PyObject* arg) { Py_ssize_t name_size; char* name; if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { @@ -311,7 +332,8 @@ PyObject* FindFileContainingSymbol(PyDescriptorPool* self, PyObject* arg) { } const FileDescriptor* file_descriptor = - self->pool->FindFileContainingSymbol(string(name, name_size)); + reinterpret_cast<PyDescriptorPool*>(self)->pool->FindFileContainingSymbol( + string(name, name_size)); if (file_descriptor == NULL) { PyErr_Format(PyExc_KeyError, "Couldn't find symbol %.200s", name); return NULL; @@ -320,7 +342,7 @@ PyObject* FindFileContainingSymbol(PyDescriptorPool* self, PyObject* arg) { return PyFileDescriptor_FromDescriptor(file_descriptor); } -PyObject* FindExtensionByNumber(PyDescriptorPool* self, PyObject* args) { +static PyObject* FindExtensionByNumber(PyObject* self, PyObject* args) { PyObject* message_descriptor; int number; if (!PyArg_ParseTuple(args, "Oi", &message_descriptor, &number)) { @@ -333,7 +355,8 @@ PyObject* FindExtensionByNumber(PyDescriptorPool* self, PyObject* args) { } const FieldDescriptor* extension_descriptor = - self->pool->FindExtensionByNumber(descriptor, number); + reinterpret_cast<PyDescriptorPool*>(self)->pool->FindExtensionByNumber( + descriptor, number); if (extension_descriptor == NULL) { PyErr_Format(PyExc_KeyError, "Couldn't find extension %d", number); return NULL; @@ -342,14 +365,15 @@ PyObject* FindExtensionByNumber(PyDescriptorPool* self, PyObject* args) { return PyFieldDescriptor_FromDescriptor(extension_descriptor); } -PyObject* FindAllExtensions(PyDescriptorPool* self, PyObject* arg) { +static PyObject* FindAllExtensions(PyObject* self, PyObject* arg) { const Descriptor* descriptor = PyMessageDescriptor_AsDescriptor(arg); if (descriptor == NULL) { return NULL; } std::vector<const FieldDescriptor*> extensions; - self->pool->FindAllExtensions(descriptor, &extensions); + reinterpret_cast<PyDescriptorPool*>(self)->pool->FindAllExtensions( + descriptor, &extensions); ScopedPyObjectPtr result(PyList_New(extensions.size())); if (result == NULL) { @@ -374,14 +398,15 @@ PyObject* FindAllExtensions(PyDescriptorPool* self, PyObject* arg) { // call a function that will just be a no-op? // TODO(amauryfa): Need to investigate further. -PyObject* AddFileDescriptor(PyDescriptorPool* self, PyObject* descriptor) { +static PyObject* AddFileDescriptor(PyObject* self, PyObject* descriptor) { const FileDescriptor* file_descriptor = PyFileDescriptor_AsDescriptor(descriptor); if (!file_descriptor) { return NULL; } if (file_descriptor != - self->pool->FindFileByName(file_descriptor->name())) { + reinterpret_cast<PyDescriptorPool*>(self)->pool->FindFileByName( + file_descriptor->name())) { PyErr_Format(PyExc_ValueError, "The file descriptor %s does not belong to this pool", file_descriptor->name().c_str()); @@ -390,14 +415,15 @@ PyObject* AddFileDescriptor(PyDescriptorPool* self, PyObject* descriptor) { Py_RETURN_NONE; } -PyObject* AddDescriptor(PyDescriptorPool* self, PyObject* descriptor) { +static PyObject* AddDescriptor(PyObject* self, PyObject* descriptor) { const Descriptor* message_descriptor = PyMessageDescriptor_AsDescriptor(descriptor); if (!message_descriptor) { return NULL; } if (message_descriptor != - self->pool->FindMessageTypeByName(message_descriptor->full_name())) { + reinterpret_cast<PyDescriptorPool*>(self)->pool->FindMessageTypeByName( + message_descriptor->full_name())) { PyErr_Format(PyExc_ValueError, "The message descriptor %s does not belong to this pool", message_descriptor->full_name().c_str()); @@ -406,14 +432,15 @@ PyObject* AddDescriptor(PyDescriptorPool* self, PyObject* descriptor) { Py_RETURN_NONE; } -PyObject* AddEnumDescriptor(PyDescriptorPool* self, PyObject* descriptor) { +static PyObject* AddEnumDescriptor(PyObject* self, PyObject* descriptor) { const EnumDescriptor* enum_descriptor = PyEnumDescriptor_AsDescriptor(descriptor); if (!enum_descriptor) { return NULL; } if (enum_descriptor != - self->pool->FindEnumTypeByName(enum_descriptor->full_name())) { + reinterpret_cast<PyDescriptorPool*>(self)->pool->FindEnumTypeByName( + enum_descriptor->full_name())) { PyErr_Format(PyExc_ValueError, "The enum descriptor %s does not belong to this pool", enum_descriptor->full_name().c_str()); @@ -422,14 +449,15 @@ PyObject* AddEnumDescriptor(PyDescriptorPool* self, PyObject* descriptor) { Py_RETURN_NONE; } -PyObject* AddExtensionDescriptor(PyDescriptorPool* self, PyObject* descriptor) { +static PyObject* AddExtensionDescriptor(PyObject* self, PyObject* descriptor) { const FieldDescriptor* extension_descriptor = PyFieldDescriptor_AsDescriptor(descriptor); if (!extension_descriptor) { return NULL; } if (extension_descriptor != - self->pool->FindExtensionByName(extension_descriptor->full_name())) { + reinterpret_cast<PyDescriptorPool*>(self)->pool->FindExtensionByName( + extension_descriptor->full_name())) { PyErr_Format(PyExc_ValueError, "The extension descriptor %s does not belong to this pool", extension_descriptor->full_name().c_str()); @@ -438,14 +466,15 @@ PyObject* AddExtensionDescriptor(PyDescriptorPool* self, PyObject* descriptor) { Py_RETURN_NONE; } -PyObject* AddServiceDescriptor(PyDescriptorPool* self, PyObject* descriptor) { +static PyObject* AddServiceDescriptor(PyObject* self, PyObject* descriptor) { const ServiceDescriptor* service_descriptor = PyServiceDescriptor_AsDescriptor(descriptor); if (!service_descriptor) { return NULL; } if (service_descriptor != - self->pool->FindServiceByName(service_descriptor->full_name())) { + reinterpret_cast<PyDescriptorPool*>(self)->pool->FindServiceByName( + service_descriptor->full_name())) { PyErr_Format(PyExc_ValueError, "The service descriptor %s does not belong to this pool", service_descriptor->full_name().c_str()); @@ -481,7 +510,8 @@ class BuildFileErrorCollector : public DescriptorPool::ErrorCollector { bool had_errors; }; -PyObject* AddSerializedFile(PyDescriptorPool* self, PyObject* serialized_pb) { +static PyObject* AddSerializedFile(PyObject* pself, PyObject* serialized_pb) { + PyDescriptorPool* self = reinterpret_cast<PyDescriptorPool*>(pself); char* message_type; Py_ssize_t message_len; @@ -529,7 +559,7 @@ PyObject* AddSerializedFile(PyDescriptorPool* self, PyObject* serialized_pb) { descriptor, serialized_pb); } -PyObject* Add(PyDescriptorPool* self, PyObject* file_descriptor_proto) { +static PyObject* Add(PyObject* self, PyObject* file_descriptor_proto) { ScopedPyObjectPtr serialized_pb( PyObject_CallMethod(file_descriptor_proto, "SerializeToString", NULL)); if (serialized_pb == NULL) { @@ -539,46 +569,46 @@ PyObject* Add(PyDescriptorPool* self, PyObject* file_descriptor_proto) { } static PyMethodDef Methods[] = { - { "Add", (PyCFunction)Add, METH_O, + { "Add", Add, METH_O, "Adds the FileDescriptorProto and its types to this pool." }, - { "AddSerializedFile", (PyCFunction)AddSerializedFile, METH_O, + { "AddSerializedFile", AddSerializedFile, METH_O, "Adds a serialized FileDescriptorProto to this pool." }, // TODO(amauryfa): Understand why the Python implementation differs from // this one, ask users to use another API and deprecate these functions. - { "AddFileDescriptor", (PyCFunction)AddFileDescriptor, METH_O, + { "AddFileDescriptor", AddFileDescriptor, METH_O, "No-op. Add() must have been called before." }, - { "AddDescriptor", (PyCFunction)AddDescriptor, METH_O, + { "AddDescriptor", AddDescriptor, METH_O, "No-op. Add() must have been called before." }, - { "AddEnumDescriptor", (PyCFunction)AddEnumDescriptor, METH_O, + { "AddEnumDescriptor", AddEnumDescriptor, METH_O, "No-op. Add() must have been called before." }, - { "AddExtensionDescriptor", (PyCFunction)AddExtensionDescriptor, METH_O, + { "AddExtensionDescriptor", AddExtensionDescriptor, METH_O, "No-op. Add() must have been called before." }, - { "AddServiceDescriptor", (PyCFunction)AddServiceDescriptor, METH_O, + { "AddServiceDescriptor", AddServiceDescriptor, METH_O, "No-op. Add() must have been called before." }, - { "FindFileByName", (PyCFunction)FindFileByName, METH_O, + { "FindFileByName", FindFileByName, METH_O, "Searches for a file descriptor by its .proto name." }, - { "FindMessageTypeByName", (PyCFunction)FindMessageByName, METH_O, + { "FindMessageTypeByName", FindMessageByName, METH_O, "Searches for a message descriptor by full name." }, - { "FindFieldByName", (PyCFunction)FindFieldByName, METH_O, + { "FindFieldByName", FindFieldByNameMethod, METH_O, "Searches for a field descriptor by full name." }, - { "FindExtensionByName", (PyCFunction)FindExtensionByName, METH_O, + { "FindExtensionByName", FindExtensionByNameMethod, METH_O, "Searches for extension descriptor by full name." }, - { "FindEnumTypeByName", (PyCFunction)FindEnumTypeByName, METH_O, + { "FindEnumTypeByName", FindEnumTypeByNameMethod, METH_O, "Searches for enum type descriptor by full name." }, - { "FindOneofByName", (PyCFunction)FindOneofByName, METH_O, + { "FindOneofByName", FindOneofByNameMethod, METH_O, "Searches for oneof descriptor by full name." }, - { "FindServiceByName", (PyCFunction)FindServiceByName, METH_O, + { "FindServiceByName", FindServiceByName, METH_O, "Searches for service descriptor by full name." }, - { "FindMethodByName", (PyCFunction)FindMethodByName, METH_O, + { "FindMethodByName", FindMethodByName, METH_O, "Searches for method descriptor by full name." }, - { "FindFileContainingSymbol", (PyCFunction)FindFileContainingSymbol, METH_O, + { "FindFileContainingSymbol", FindFileContainingSymbol, METH_O, "Gets the FileDescriptor containing the specified symbol." }, - { "FindExtensionByNumber", (PyCFunction)FindExtensionByNumber, METH_VARARGS, + { "FindExtensionByNumber", FindExtensionByNumber, METH_VARARGS, "Gets the extension descriptor for the given number." }, - { "FindAllExtensions", (PyCFunction)FindAllExtensions, METH_O, + { "FindAllExtensions", FindAllExtensions, METH_O, "Gets all known extensions of the given message descriptor." }, {NULL} }; @@ -590,7 +620,7 @@ PyTypeObject PyDescriptorPool_Type = { FULL_MODULE_NAME ".DescriptorPool", // tp_name sizeof(PyDescriptorPool), // tp_basicsize 0, // tp_itemsize - (destructor)cdescriptor_pool::Dealloc, // tp_dealloc + cdescriptor_pool::Dealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc index 6830b10d..018b5c2c 100644 --- a/python/google/protobuf/pyext/extension_dict.cc +++ b/python/google/protobuf/pyext/extension_dict.cc @@ -33,9 +33,6 @@ #include <google/protobuf/pyext/extension_dict.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> diff --git a/python/google/protobuf/pyext/extension_dict.h b/python/google/protobuf/pyext/extension_dict.h index 65b87862..0de2c4ee 100644 --- a/python/google/protobuf/pyext/extension_dict.h +++ b/python/google/protobuf/pyext/extension_dict.h @@ -37,9 +37,8 @@ #include <Python.h> #include <memory> -#ifndef _SHARED_PTR_H -#include <google/protobuf/stubs/shared_ptr.h> -#endif + +#include <google/protobuf/pyext/message.h> namespace google { namespace protobuf { @@ -47,16 +46,8 @@ namespace protobuf { class Message; class FieldDescriptor; -#ifdef _SHARED_PTR_H -using std::shared_ptr; -#else -using internal::shared_ptr; -#endif - namespace python { -struct CMessage; - typedef struct ExtensionDict { PyObject_HEAD; @@ -64,7 +55,7 @@ typedef struct ExtensionDict { // proto tree. Every Python container class holds a // reference to it in order to keep it alive as long as there's a // Python object that references any part of the tree. - shared_ptr<Message> owner; + CMessage::OwnerRef owner; // Weak reference to parent message. Used to make sure // the parent is writable when an extension field is modified. diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc index abd15b77..6d7ee285 100644 --- a/python/google/protobuf/pyext/map_container.cc +++ b/python/google/protobuf/pyext/map_container.cc @@ -33,9 +33,6 @@ #include <google/protobuf/pyext/map_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> @@ -76,7 +73,7 @@ class MapReflectionFriend { struct MapIterator { PyObject_HEAD; - google::protobuf::scoped_ptr< ::google::protobuf::MapIterator> iter; + std::unique_ptr<::google::protobuf::MapIterator> iter; // A pointer back to the container, so we can notice changes to the version. // We own a ref on this. @@ -94,7 +91,7 @@ struct MapIterator { // as this iterator does. This is solely for the benefit of the MapIterator // destructor -- we should never actually access the iterator in this state // except to delete it. - shared_ptr<Message> owner; + CMessage::OwnerRef owner; // The version of the map when we took the iterator to it. // @@ -339,6 +336,24 @@ PyObject* GetEntryClass(PyObject* _self) { return reinterpret_cast<PyObject*>(message_class); } +PyObject* MergeFrom(PyObject* _self, PyObject* arg) { + MapContainer* self = GetMap(_self); + MapContainer* other_map = GetMap(arg); + Message* message = self->GetMutableMessage(); + const Message* other_message = other_map->message; + const Reflection* reflection = message->GetReflection(); + const Reflection* other_reflection = other_message->GetReflection(); + int count = other_reflection->FieldSize( + *other_message, other_map->parent_field_descriptor); + for (int i = 0 ; i < count; i ++) { + reflection->AddMessage(message, self->parent_field_descriptor)->MergeFrom( + other_reflection->GetRepeatedMessage( + *other_message, other_map->parent_field_descriptor, i)); + } + self->version++; + Py_RETURN_NONE; +} + PyObject* MapReflectionFriend::Contains(PyObject* _self, PyObject* key) { MapContainer* self = GetMap(_self); @@ -535,6 +550,8 @@ static PyMethodDef ScalarMapMethods[] = { "Gets the value for the given key if present, or otherwise a default" }, { "GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS, "Return the class used to build Entries of (key, value) pairs." }, + { "MergeFrom", (PyCFunction)MergeFrom, METH_O, + "Merges a map into the current map." }, /* { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, "Makes a deep copy of the class." }, @@ -810,6 +827,8 @@ static PyMethodDef MessageMapMethods[] = { "Alias for getitem, useful to make explicit that the map is mutated." }, { "GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS, "Return the class used to build Entries of (key, value) pairs." }, + { "MergeFrom", (PyCFunction)MergeFrom, METH_O, + "Merges a map into the current map." }, /* { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, "Makes a deep copy of the class." }, diff --git a/python/google/protobuf/pyext/map_container.h b/python/google/protobuf/pyext/map_container.h index 615657b0..111fafbf 100644 --- a/python/google/protobuf/pyext/map_container.h +++ b/python/google/protobuf/pyext/map_container.h @@ -34,27 +34,18 @@ #include <Python.h> #include <memory> -#ifndef _SHARED_PTR_H -#include <google/protobuf/stubs/shared_ptr.h> -#endif #include <google/protobuf/descriptor.h> #include <google/protobuf/message.h> +#include <google/protobuf/pyext/message.h> namespace google { namespace protobuf { class Message; -#ifdef _SHARED_PTR_H -using std::shared_ptr; -#else -using internal::shared_ptr; -#endif - namespace python { -struct CMessage; struct CMessageClass; // This struct is used directly for ScalarMap, and is the base class of @@ -66,7 +57,7 @@ struct MapContainer { // proto tree. Every Python MapContainer holds a // reference to it in order to keep it alive as long as there's a // Python object that references any part of the tree. - shared_ptr<Message> owner; + CMessage::OwnerRef owner; // Pointer to the C++ Message that contains this container. The // MapContainer does not own this pointer. @@ -99,9 +90,7 @@ struct MapContainer { int Release(); // Set the owner field of self and any children of self. - void SetOwner(const shared_ptr<Message>& new_owner) { - owner = new_owner; - } + void SetOwner(const CMessage::OwnerRef& new_owner) { owner = new_owner; } }; struct MessageMapContainer : public MapContainer { diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc index ef75acab..53736b9c 100644 --- a/python/google/protobuf/pyext/message.cc +++ b/python/google/protobuf/pyext/message.cc @@ -35,9 +35,6 @@ #include <map> #include <memory> -#ifndef _SHARED_PTR_H -#include <google/protobuf/stubs/shared_ptr.h> -#endif #include <string> #include <vector> #include <structmember.h> // A Python header file. @@ -605,18 +602,16 @@ void OutOfRangeError(PyObject* arg) { template<class RangeType, class ValueType> bool VerifyIntegerCastAndRange(PyObject* arg, ValueType value) { - if - GOOGLE_PREDICT_FALSE(value == -1 && PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) { - // Replace it with the same ValueError as pure python protos instead of - // the default one. - PyErr_Clear(); - OutOfRangeError(arg); - } // Otherwise propagate existing error. - return false; + if (GOOGLE_PREDICT_FALSE(value == -1 && PyErr_Occurred())) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + // Replace it with the same ValueError as pure python protos instead of + // the default one. + PyErr_Clear(); + OutOfRangeError(arg); + } // Otherwise propagate existing error. + return false; } - if - GOOGLE_PREDICT_FALSE(!IsValidNumericCast<RangeType>(value)) { + if (GOOGLE_PREDICT_FALSE(!IsValidNumericCast<RangeType>(value))) { OutOfRangeError(arg); return false; } @@ -628,26 +623,22 @@ bool CheckAndGetInteger(PyObject* arg, T* value) { // The fast path. #if PY_MAJOR_VERSION < 3 // For the typical case, offer a fast path. - if - GOOGLE_PREDICT_TRUE(PyInt_Check(arg)) { - long int_result = PyInt_AsLong(arg); - if - GOOGLE_PREDICT_TRUE(IsValidNumericCast<T>(int_result)) { - *value = static_cast<T>(int_result); - return true; - } - else { - OutOfRangeError(arg); - return false; - } + if (GOOGLE_PREDICT_TRUE(PyInt_Check(arg))) { + long int_result = PyInt_AsLong(arg); + if (GOOGLE_PREDICT_TRUE(IsValidNumericCast<T>(int_result))) { + *value = static_cast<T>(int_result); + return true; + } else { + OutOfRangeError(arg); + return false; + } } #endif // This effectively defines an integer as "an object that can be cast as // an integer and can be used as an ordinal number". // This definition includes everything that implements numbers.Integral // and shouldn't cast the net too wide. - if - GOOGLE_PREDICT_FALSE(!PyIndex_Check(arg)) { + if (GOOGLE_PREDICT_FALSE(!PyIndex_Check(arg))) { FormatTypeError(arg, "int, long"); return false; } @@ -664,10 +655,9 @@ bool CheckAndGetInteger(PyObject* arg, T* value) { // Unlike PyLong_AsLongLong, PyLong_AsUnsignedLongLong is very // picky about the exact type. PyObject* casted = PyNumber_Long(arg); - if - GOOGLE_PREDICT_FALSE(casted == NULL) { - // Propagate existing error. - return false; + if (GOOGLE_PREDICT_FALSE(casted == nullptr)) { + // Propagate existing error. + return false; } ulong_result = PyLong_AsUnsignedLongLong(casted); Py_DECREF(casted); @@ -690,10 +680,9 @@ bool CheckAndGetInteger(PyObject* arg, T* value) { // Valid subclasses of numbers.Integral should have a __long__() method // so fall back to that. PyObject* casted = PyNumber_Long(arg); - if - GOOGLE_PREDICT_FALSE(casted == NULL) { - // Propagate existing error. - return false; + if (GOOGLE_PREDICT_FALSE(casted == nullptr)) { + // Propagate existing error. + return false; } long_result = PyLong_AsLongLong(casted); Py_DECREF(casted); @@ -717,10 +706,9 @@ template bool CheckAndGetInteger<uint64>(PyObject*, uint64*); bool CheckAndGetDouble(PyObject* arg, double* value) { *value = PyFloat_AsDouble(arg); - if - GOOGLE_PREDICT_FALSE(*value == -1 && PyErr_Occurred()) { - FormatTypeError(arg, "int, long, float"); - return false; + if (GOOGLE_PREDICT_FALSE(*value == -1 && PyErr_Occurred())) { + FormatTypeError(arg, "int, long, float"); + return false; } return true; } @@ -839,7 +827,8 @@ bool CheckAndSetString( return true; } -PyObject* ToStringObject(const FieldDescriptor* descriptor, string value) { +PyObject* ToStringObject(const FieldDescriptor* descriptor, + const string& value) { if (descriptor->type() != FieldDescriptor::TYPE_STRING) { return PyBytes_FromStringAndSize(value.c_str(), value.length()); } @@ -1187,7 +1176,7 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { continue; } if (descriptor->is_map()) { - ScopedPyObjectPtr map(GetAttr(self, name)); + ScopedPyObjectPtr map(GetAttr(reinterpret_cast<PyObject*>(self), name)); const FieldDescriptor* value_descriptor = descriptor->message_type()->FindFieldByName("value"); if (value_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { @@ -1215,7 +1204,8 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { } } } else if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { - ScopedPyObjectPtr container(GetAttr(self, name)); + ScopedPyObjectPtr container( + GetAttr(reinterpret_cast<PyObject*>(self), name)); if (container == NULL) { return -1; } @@ -1282,7 +1272,8 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { } } } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - ScopedPyObjectPtr message(GetAttr(self, name)); + ScopedPyObjectPtr message( + GetAttr(reinterpret_cast<PyObject*>(self), name)); if (message == NULL) { return -1; } @@ -1307,8 +1298,8 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { return -1; } } - if (SetAttr(self, name, (new_val.get() == NULL) ? value : new_val.get()) < - 0) { + if (SetAttr(reinterpret_cast<PyObject*>(self), name, + (new_val.get() == NULL) ? value : new_val.get()) < 0) { return -1; } } @@ -1325,6 +1316,8 @@ CMessage* NewEmptyMessage(CMessageClass* type) { return NULL; } + // Use "placement new" syntax to initialize the C++ object. + new (&self->owner) CMessage::OwnerRef(NULL); self->message = NULL; self->parent = NULL; self->parent_field_descriptor = NULL; @@ -1421,7 +1414,7 @@ static void Dealloc(CMessage* self) { Py_CLEAR(self->extensions); Py_CLEAR(self->composite_fields); - self->owner.reset(); + self->owner.~ThreadUnsafeSharedPtr<Message>(); Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); } @@ -1623,9 +1616,10 @@ PyObject* HasExtension(CMessage* self, PyObject* extension) { // * Clear the weak references from the released container to the // parent. -struct SetOwnerVisitor : public ChildVisitor { +class SetOwnerVisitor : public ChildVisitor { + public: // new_owner must outlive this object. - explicit SetOwnerVisitor(const shared_ptr<Message>& new_owner) + explicit SetOwnerVisitor(const CMessage::OwnerRef& new_owner) : new_owner_(new_owner) {} int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { @@ -1649,11 +1643,11 @@ struct SetOwnerVisitor : public ChildVisitor { } private: - const shared_ptr<Message>& new_owner_; + const CMessage::OwnerRef& new_owner_; }; // Change the owner of this CMessage and all its children, recursively. -int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner) { +int SetOwner(CMessage* self, const CMessage::OwnerRef& new_owner) { self->owner = new_owner; if (ForEachCompositeField(self, SetOwnerVisitor(new_owner)) == -1) return -1; @@ -1686,7 +1680,7 @@ int ReleaseSubMessage(CMessage* self, const FieldDescriptor* field_descriptor, CMessage* child_cmessage) { // Release the Message - shared_ptr<Message> released_message(ReleaseMessage( + CMessage::OwnerRef released_message(ReleaseMessage( self, child_cmessage->message->GetDescriptor(), field_descriptor)); child_cmessage->message = released_message.get(); child_cmessage->owner.swap(released_message); @@ -2211,7 +2205,8 @@ static PyObject* ListFields(CMessage* self) { return NULL; } - PyObject* field_value = GetAttr(self, py_field_name.get()); + PyObject* field_value = + GetAttr(reinterpret_cast<PyObject*>(self), py_field_name.get()); if (field_value == NULL) { PyErr_SetObject(PyExc_ValueError, py_field_name.get()); return NULL; @@ -2335,7 +2330,9 @@ PyObject* InternalGetScalar(const Message* message, break; } case FieldDescriptor::CPPTYPE_STRING: { - string value = reflection->GetString(*message, field_descriptor); + string scratch; + const string& value = + reflection->GetStringReference(*message, field_descriptor, &scratch); result = ToStringObject(field_descriptor, value); break; } @@ -2707,7 +2704,8 @@ static bool SetCompositeField( return PyDict_SetItem(self->composite_fields, name, value) == 0; } -PyObject* GetAttr(CMessage* self, PyObject* name) { +PyObject* GetAttr(PyObject* pself, PyObject* name) { + CMessage* self = reinterpret_cast<CMessage*>(pself); PyObject* value = self->composite_fields ? PyDict_GetItem(self->composite_fields, name) : NULL; if (value != NULL) { @@ -2785,7 +2783,8 @@ PyObject* GetAttr(CMessage* self, PyObject* name) { return InternalGetScalar(self->message, field_descriptor); } -int SetAttr(CMessage* self, PyObject* name, PyObject* value) { +int SetAttr(PyObject* pself, PyObject* name, PyObject* value) { + CMessage* self = reinterpret_cast<CMessage*>(pself); if (self->composite_fields && PyDict_Contains(self->composite_fields, name)) { PyErr_SetString(PyExc_TypeError, "Can't set composite field"); return -1; @@ -2837,8 +2836,8 @@ PyTypeObject CMessage_Type = { PyObject_HashNotImplemented, // tp_hash 0, // tp_call (reprfunc)cmessage::ToStr, // tp_str - (getattrofunc)cmessage::GetAttr, // tp_getattro - (setattrofunc)cmessage::SetAttr, // tp_setattro + cmessage::GetAttr, // tp_getattro + cmessage::SetAttr, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags "A ProtocolMessage", // tp_doc @@ -2867,17 +2866,38 @@ const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg); Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg); static const Message* GetCProtoInsidePyProtoImpl(PyObject* msg) { + const Message* message = PyMessage_GetMessagePointer(msg); + if (message == NULL) { + PyErr_Clear(); + return NULL; + } + return message; +} + +static Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) { + Message* message = PyMessage_GetMutableMessagePointer(msg); + if (message == NULL) { + PyErr_Clear(); + return NULL; + } + return message; +} + +const Message* PyMessage_GetMessagePointer(PyObject* msg) { if (!PyObject_TypeCheck(msg, &CMessage_Type)) { + PyErr_SetString(PyExc_TypeError, "Not a Message instance"); return NULL; } CMessage* cmsg = reinterpret_cast<CMessage*>(msg); return cmsg->message; } -static Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) { +Message* PyMessage_GetMutableMessagePointer(PyObject* msg) { if (!PyObject_TypeCheck(msg, &CMessage_Type)) { + PyErr_SetString(PyExc_TypeError, "Not a Message instance"); return NULL; } + CMessage* cmsg = reinterpret_cast<CMessage*>(msg); if ((cmsg->composite_fields && PyDict_Size(cmsg->composite_fields) != 0) || (cmsg->extensions != NULL && @@ -2886,6 +2906,9 @@ static Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) { // the underlying C++ message back to the CMessage (e.g. removed repeated // composite containers). We only allow direct mutation of the underlying // C++ message if there is no child data in the CMessage. + PyErr_SetString(PyExc_ValueError, + "Cannot reliably get a mutable pointer " + "to a message with extra references"); return NULL; } cmessage::AssureWritable(cmsg); diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h index ce80497e..d754e62a 100644 --- a/python/google/protobuf/pyext/message.h +++ b/python/google/protobuf/pyext/message.h @@ -37,11 +37,11 @@ #include <Python.h> #include <memory> -#ifndef _SHARED_PTR_H -#include <google/protobuf/stubs/shared_ptr.h> -#endif #include <string> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/pyext/thread_unsafe_shared_ptr.h> + namespace google { namespace protobuf { @@ -52,13 +52,6 @@ class Descriptor; class DescriptorPool; class MessageFactory; -#ifdef _SHARED_PTR_H -using std::shared_ptr; -using std::string; -#else -using internal::shared_ptr; -#endif - namespace python { struct ExtensionDict; @@ -71,7 +64,9 @@ typedef struct CMessage { // proto tree. Every Python CMessage holds a reference to it in // order to keep it alive as long as there's a Python object that // references any part of the tree. - shared_ptr<Message> owner; + + typedef ThreadUnsafeSharedPtr<Message> OwnerRef; + OwnerRef owner; // Weak reference to a parent CMessage object. This is NULL for any top-level // message and is set for any child message (i.e. a child submessage or a @@ -240,22 +235,22 @@ PyObject* MergeFrom(CMessage* self, PyObject* arg); // has been registered with the same field number on this class. PyObject* RegisterExtension(PyObject* cls, PyObject* extension_handle); -// Retrieves an attribute named 'name' from CMessage 'self'. Returns -// the attribute value on success, or NULL on failure. +// Retrieves an attribute named 'name' from 'self', which is interpreted as a +// CMessage. Returns the attribute value on success, or null on failure. // // Returns a new reference. -PyObject* GetAttr(CMessage* self, PyObject* name); +PyObject* GetAttr(PyObject* self, PyObject* name); -// Set the value of the attribute named 'name', for CMessage 'self', -// to the value 'value'. Returns -1 on failure. -int SetAttr(CMessage* self, PyObject* name, PyObject* value); +// Set the value of the attribute named 'name', for 'self', which is interpreted +// as a CMessage, to the value 'value'. Returns -1 on failure. +int SetAttr(PyObject* self, PyObject* name, PyObject* value); PyObject* FindInitializationErrors(CMessage* self); // Set the owner field of self and any children of self, recursively. // Used when self is being released and thus has a new owner (the // released Message.) -int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner); +int SetOwner(CMessage* self, const CMessage::OwnerRef& new_owner); int AssureWritable(CMessage* self); @@ -336,7 +331,8 @@ bool CheckAndSetString( const Reflection* reflection, bool append, int index); -PyObject* ToStringObject(const FieldDescriptor* descriptor, string value); +PyObject* ToStringObject(const FieldDescriptor* descriptor, + const string& value); // Check if the passed field descriptor belongs to the given message. // If not, return false and set a Python exception (a KeyError) @@ -345,8 +341,20 @@ bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor, extern PyObject* PickleError_class; +const Message* PyMessage_GetMessagePointer(PyObject* msg); +Message* PyMessage_GetMutableMessagePointer(PyObject* msg); + bool InitProto2MessageModule(PyObject *m); +#if LANG_CXX11 +// These are referenced by repeated_scalar_container, and must +// be explicitly instantiated. +extern template bool CheckAndGetInteger<int32>(PyObject*, int32*); +extern template bool CheckAndGetInteger<int64>(PyObject*, int64*); +extern template bool CheckAndGetInteger<uint32>(PyObject*, uint32*); +extern template bool CheckAndGetInteger<uint64>(PyObject*, uint64*); +#endif + } // namespace python } // namespace protobuf diff --git a/python/google/protobuf/pyext/message_factory.cc b/python/google/protobuf/pyext/message_factory.cc index 571bae2b..bacc76a6 100644 --- a/python/google/protobuf/pyext/message_factory.cc +++ b/python/google/protobuf/pyext/message_factory.cc @@ -100,7 +100,9 @@ PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) { NewMessageFactory(type, reinterpret_cast<PyDescriptorPool*>(pool))); } -static void Dealloc(PyMessageFactory* self) { +static void Dealloc(PyObject* pself) { + PyMessageFactory* self = reinterpret_cast<PyMessageFactory*>(pself); + // TODO(amauryfa): When the MessageFactory is not created from the // DescriptorPool this reference should be owned, not borrowed. // Py_CLEAR(self->pool); @@ -111,7 +113,7 @@ static void Dealloc(PyMessageFactory* self) { } delete self->classes_by_descriptor; delete self->message_factory; - Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); + Py_TYPE(self)->tp_free(pself); } // Add a message class to our database. @@ -231,7 +233,7 @@ PyTypeObject PyMessageFactory_Type = { ".MessageFactory", // tp_name sizeof(PyMessageFactory), // tp_basicsize 0, // tp_itemsize - (destructor)message_factory::Dealloc, // tp_dealloc + message_factory::Dealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr diff --git a/python/google/protobuf/pyext/message_module.cc b/python/google/protobuf/pyext/message_module.cc index 7c4df47f..f5c8f295 100644 --- a/python/google/protobuf/pyext/message_module.cc +++ b/python/google/protobuf/pyext/message_module.cc @@ -31,9 +31,26 @@ #include <Python.h> #include <google/protobuf/pyext/message.h> +#include <google/protobuf/proto_api.h> #include <google/protobuf/message_lite.h> +namespace { + +// C++ API. Clients get at this via proto_api.h +struct ApiImplementation : google::protobuf::python::PyProto_API { + const google::protobuf::Message* + GetMessagePointer(PyObject* msg) const override { + return google::protobuf::python::PyMessage_GetMessagePointer(msg); + } + google::protobuf::Message* + GetMutableMessagePointer(PyObject* msg) const override { + return google::protobuf::python::PyMessage_GetMutableMessagePointer(msg); + } +}; + +} // namespace + static PyObject* GetPythonProto3PreserveUnknownsDefault( PyObject* /*m*/, PyObject* /*args*/) { if (google::protobuf::internal::GetProto3PreserveUnknownsDefault()) { diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc index 5ad71db5..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> @@ -81,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, @@ -102,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(); @@ -191,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() @@ -226,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; @@ -233,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; @@ -242,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) { @@ -265,7 +281,7 @@ 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 @@ -290,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; } @@ -305,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; } @@ -340,12 +366,13 @@ static PyObject* RichCompare(RepeatedCompositeContainer* self, } } -static PyObject* ToStr(RepeatedCompositeContainer* self) { +static PyObject* ToStr(PyObject* pself) { ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); if (full_slice == NULL) { return NULL; } - ScopedPyObjectPtr list(Subscript(self, full_slice.get())); + ScopedPyObjectPtr list(Subscript( + reinterpret_cast<RepeatedCompositeContainer*>(pself), full_slice.get())); if (list == NULL) { return NULL; } @@ -359,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 @@ -390,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) { @@ -416,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; } @@ -432,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)); @@ -460,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. @@ -503,7 +534,10 @@ int Release(RepeatedCompositeContainer* self) { return 0; } -PyObject* DeepCopy(RepeatedCompositeContainer* self, PyObject* arg) { +PyObject* DeepCopy(PyObject* pself, PyObject* arg) { + RepeatedCompositeContainer* self = + reinterpret_cast<RepeatedCompositeContainer*>(pself); + ScopedPyObjectPtr cloneObj( PyType_GenericAlloc(&RepeatedCompositeContainer_Type, 0)); if (cloneObj == NULL) { @@ -530,7 +564,7 @@ PyObject* DeepCopy(RepeatedCompositeContainer* self, PyObject* arg) { } int SetOwner(RepeatedCompositeContainer* self, - const shared_ptr<Message>& new_owner) { + const CMessage::OwnerRef& new_owner) { GOOGLE_CHECK_ATTACHED(self); self->owner = new_owner; @@ -571,43 +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[] = { - { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, + { "__deepcopy__", DeepCopy, METH_VARARGS, "Makes a deep copy of the class." }, - { "add", (PyCFunction) Add, METH_VARARGS | METH_KEYWORDS, + { "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 } }; @@ -619,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 - (reprfunc)repeated_composite_container::ToStr, // 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 @@ -638,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 diff --git a/python/google/protobuf/pyext/repeated_composite_container.h b/python/google/protobuf/pyext/repeated_composite_container.h index a7b56b61..e5e946aa 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.h +++ b/python/google/protobuf/pyext/repeated_composite_container.h @@ -37,27 +37,19 @@ #include <Python.h> #include <memory> -#ifndef _SHARED_PTR_H -#include <google/protobuf/stubs/shared_ptr.h> -#endif #include <string> #include <vector> +#include <google/protobuf/pyext/message.h> + namespace google { namespace protobuf { class FieldDescriptor; class Message; -#ifdef _SHARED_PTR_H -using std::shared_ptr; -#else -using internal::shared_ptr; -#endif - namespace python { -struct CMessage; struct CMessageClass; // A RepeatedCompositeContainer can be in one of two states: attached @@ -77,7 +69,7 @@ typedef struct RepeatedCompositeContainer { // proto tree. Every Python RepeatedCompositeContainer holds a // reference to it in order to keep it alive as long as there's a // Python object that references any part of the tree. - shared_ptr<Message> owner; + CMessage::OwnerRef owner; // Weak reference to parent object. May be NULL. Used to make sure // the parent is writable before modifying the @@ -148,11 +140,6 @@ int AssignSubscript(RepeatedCompositeContainer* self, PyObject* slice, PyObject* value); -// Releases the messages in the container to the given message. -// -// Returns 0 on success, -1 on failure. -int ReleaseToMessage(RepeatedCompositeContainer* self, Message* new_message); - // Releases the messages in the container to a new message. // // Returns 0 on success, -1 on failure. @@ -160,7 +147,7 @@ int Release(RepeatedCompositeContainer* self); // Returns 0 on success, -1 on failure. int SetOwner(RepeatedCompositeContainer* self, - const shared_ptr<Message>& new_owner); + const CMessage::OwnerRef& new_owner); // Removes the last element of the repeated message field 'field' on // the Message 'parent', and transfers the ownership of the released diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc index 5a7832cd..de3b6e14 100644 --- a/python/google/protobuf/pyext/repeated_scalar_container.cc +++ b/python/google/protobuf/pyext/repeated_scalar_container.cc @@ -34,9 +34,6 @@ #include <google/protobuf/pyext/repeated_scalar_container.h> #include <memory> -#ifndef _SHARED_PTR_H -#include <google/protobuf/stubs/shared_ptr.h> -#endif #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/logging.h> @@ -77,15 +74,18 @@ static int InternalAssignRepeatedField( return 0; } -static Py_ssize_t Len(RepeatedScalarContainer* self) { +static Py_ssize_t Len(PyObject* pself) { + RepeatedScalarContainer* self = + reinterpret_cast<RepeatedScalarContainer*>(pself); Message* message = self->message; return message->GetReflection()->FieldSize(*message, self->parent_field_descriptor); } -static int AssignItem(RepeatedScalarContainer* self, - Py_ssize_t index, - PyObject* arg) { +static int AssignItem(PyObject* pself, Py_ssize_t index, PyObject* arg) { + RepeatedScalarContainer* self = + reinterpret_cast<RepeatedScalarContainer*>(pself); + cmessage::AssureWritable(self->parent); Message* message = self->message; const FieldDescriptor* field_descriptor = self->parent_field_descriptor; @@ -188,7 +188,10 @@ static int AssignItem(RepeatedScalarContainer* self, return 0; } -static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) { +static PyObject* Item(PyObject* pself, Py_ssize_t index) { + RepeatedScalarContainer* self = + reinterpret_cast<RepeatedScalarContainer*>(pself); + Message* message = self->message; const FieldDescriptor* field_descriptor = self->parent_field_descriptor; const Reflection* reflection = message->GetReflection(); @@ -256,8 +259,9 @@ static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) { break; } case FieldDescriptor::CPPTYPE_STRING: { - string value = reflection->GetRepeatedString( - *message, field_descriptor, index); + string scratch; + const string& value = reflection->GetRepeatedStringReference( + *message, field_descriptor, index, &scratch); result = ToStringObject(field_descriptor, value); break; } @@ -271,7 +275,7 @@ static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) { return result; } -static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) { +static PyObject* Subscript(PyObject* pself, PyObject* slice) { Py_ssize_t from; Py_ssize_t to; Py_ssize_t step; @@ -286,14 +290,13 @@ static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) { if (PyLong_Check(slice)) { from = to = PyLong_AsLong(slice); } else if (PySlice_Check(slice)) { - length = Len(self); + length = Len(pself); #if PY_MAJOR_VERSION >= 3 if (PySlice_GetIndicesEx(slice, length, &from, &to, &step, &slicelength) == -1) { #else if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice), length, &from, &to, &step, &slicelength) == -1) { - #endif return NULL; } @@ -304,7 +307,7 @@ static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) { } if (!return_list) { - return Item(self, from); + return Item(pself, from); } PyObject* list = PyList_New(0); @@ -319,7 +322,7 @@ static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) { if (index < 0 || index >= length) { break; } - ScopedPyObjectPtr s(Item(self, index)); + ScopedPyObjectPtr s(Item(pself, index)); PyList_Append(list, s.get()); } } else { @@ -330,7 +333,7 @@ static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) { if (index < 0 || index >= length) { break; } - ScopedPyObjectPtr s(Item(self, index)); + ScopedPyObjectPtr s(Item(pself, index)); PyList_Append(list, s.get()); } } @@ -417,9 +420,14 @@ PyObject* Append(RepeatedScalarContainer* self, PyObject* item) { Py_RETURN_NONE; } -static int AssSubscript(RepeatedScalarContainer* self, - PyObject* slice, - PyObject* value) { +static PyObject* AppendMethod(PyObject* self, PyObject* item) { + return Append(reinterpret_cast<RepeatedScalarContainer*>(self), item); +} + +static int AssSubscript(PyObject* pself, PyObject* slice, PyObject* value) { + RepeatedScalarContainer* self = + reinterpret_cast<RepeatedScalarContainer*>(pself); + Py_ssize_t from; Py_ssize_t to; Py_ssize_t step; @@ -435,7 +443,7 @@ static int AssSubscript(RepeatedScalarContainer* self, #if PY_MAJOR_VERSION < 3 if (PyInt_Check(slice)) { from = to = PyInt_AsLong(slice); - } else + } else // NOLINT #endif if (PyLong_Check(slice)) { from = to = PyLong_AsLong(slice); @@ -463,14 +471,14 @@ static int AssSubscript(RepeatedScalarContainer* self, } if (!create_list) { - return AssignItem(self, from, value); + return AssignItem(pself, from, value); } ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); if (full_slice == NULL) { return -1; } - ScopedPyObjectPtr new_list(Subscript(self, full_slice.get())); + ScopedPyObjectPtr new_list(Subscript(pself, full_slice.get())); if (new_list == NULL) { return -1; } @@ -509,14 +517,17 @@ PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) { Py_RETURN_NONE; } -static PyObject* Insert(RepeatedScalarContainer* self, PyObject* args) { +static PyObject* Insert(PyObject* pself, PyObject* args) { + RepeatedScalarContainer* self = + reinterpret_cast<RepeatedScalarContainer*>(pself); + Py_ssize_t index; PyObject* value; if (!PyArg_ParseTuple(args, "lO", &index, &value)) { return NULL; } ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); - ScopedPyObjectPtr new_list(Subscript(self, full_slice.get())); + ScopedPyObjectPtr new_list(Subscript(pself, full_slice.get())); if (PyList_Insert(new_list.get(), index, value) < 0) { return NULL; } @@ -527,10 +538,10 @@ static PyObject* Insert(RepeatedScalarContainer* self, PyObject* args) { Py_RETURN_NONE; } -static PyObject* Remove(RepeatedScalarContainer* self, PyObject* value) { +static PyObject* Remove(PyObject* pself, PyObject* value) { Py_ssize_t match_index = -1; - for (Py_ssize_t i = 0; i < Len(self); ++i) { - ScopedPyObjectPtr elem(Item(self, i)); + for (Py_ssize_t i = 0; i < Len(pself); ++i) { + ScopedPyObjectPtr elem(Item(pself, i)); if (PyObject_RichCompareBool(elem.get(), value, Py_EQ)) { match_index = i; break; @@ -540,15 +551,17 @@ static PyObject* Remove(RepeatedScalarContainer* self, PyObject* value) { PyErr_SetString(PyExc_ValueError, "remove(x): x not in container"); return NULL; } - if (AssignItem(self, match_index, NULL) < 0) { + if (AssignItem(pself, match_index, NULL) < 0) { return NULL; } Py_RETURN_NONE; } -static PyObject* RichCompare(RepeatedScalarContainer* self, - PyObject* other, - int opid) { +static PyObject* ExtendMethod(PyObject* self, PyObject* value) { + return Extend(reinterpret_cast<RepeatedScalarContainer*>(self), value); +} + +static PyObject* RichCompare(PyObject* pself, PyObject* other, int opid) { if (opid != Py_EQ && opid != Py_NE) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; @@ -565,28 +578,25 @@ static PyObject* RichCompare(RepeatedScalarContainer* self, ScopedPyObjectPtr other_list_deleter; if (PyObject_TypeCheck(other, &RepeatedScalarContainer_Type)) { - other_list_deleter.reset(Subscript( - reinterpret_cast<RepeatedScalarContainer*>(other), full_slice.get())); + other_list_deleter.reset(Subscript(other, full_slice.get())); other = other_list_deleter.get(); } - ScopedPyObjectPtr list(Subscript(self, full_slice.get())); + ScopedPyObjectPtr list(Subscript(pself, full_slice.get())); if (list == NULL) { return NULL; } return PyObject_RichCompare(list.get(), other, opid); } -PyObject* Reduce(RepeatedScalarContainer* unused_self) { +PyObject* Reduce(PyObject* unused_self, PyObject* unused_other) { PyErr_Format( PickleError_class, "can't pickle repeated message fields, convert to list first"); return NULL; } -static PyObject* Sort(RepeatedScalarContainer* self, - PyObject* args, - PyObject* kwds) { +static PyObject* Sort(PyObject* pself, PyObject* args, PyObject* kwds) { // Support the old sort_function argument for backwards // compatibility. if (kwds != NULL) { @@ -605,7 +615,7 @@ static PyObject* Sort(RepeatedScalarContainer* self, if (full_slice == NULL) { return NULL; } - ScopedPyObjectPtr list(Subscript(self, full_slice.get())); + ScopedPyObjectPtr list(Subscript(pself, full_slice.get())); if (list == NULL) { return NULL; } @@ -617,38 +627,36 @@ static PyObject* Sort(RepeatedScalarContainer* self, if (res == NULL) { return NULL; } - int ret = InternalAssignRepeatedField(self, list.get()); + int ret = InternalAssignRepeatedField( + reinterpret_cast<RepeatedScalarContainer*>(pself), list.get()); if (ret < 0) { return NULL; } Py_RETURN_NONE; } -static PyObject* Pop(RepeatedScalarContainer* self, - PyObject* args) { +static PyObject* Pop(PyObject* pself, PyObject* args) { 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; } - if (AssignItem(self, index, NULL) < 0) { + if (AssignItem(pself, index, NULL) < 0) { return NULL; } return item; } -static PyObject* ToStr(RepeatedScalarContainer* self) { +static PyObject* ToStr(PyObject* pself) { ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); if (full_slice == NULL) { return NULL; } - ScopedPyObjectPtr list(Subscript(self, full_slice.get())); + ScopedPyObjectPtr list(Subscript(pself, full_slice.get())); if (list == NULL) { return NULL; } @@ -687,7 +695,8 @@ static int InitializeAndCopyToParentContainer( if (full_slice == NULL) { return -1; } - ScopedPyObjectPtr values(Subscript(from, full_slice.get())); + ScopedPyObjectPtr values( + Subscript(reinterpret_cast<PyObject*>(from), full_slice.get())); if (values == NULL) { return -1; } @@ -706,7 +715,10 @@ int Release(RepeatedScalarContainer* self) { return InitializeAndCopyToParentContainer(self, self); } -PyObject* DeepCopy(RepeatedScalarContainer* self, PyObject* arg) { +PyObject* DeepCopy(PyObject* pself, PyObject* arg) { + RepeatedScalarContainer* self = + reinterpret_cast<RepeatedScalarContainer*>(pself); + RepeatedScalarContainer* clone = reinterpret_cast<RepeatedScalarContainer*>( PyType_GenericAlloc(&RepeatedScalarContainer_Type, 0)); if (clone == NULL) { @@ -720,45 +732,47 @@ PyObject* DeepCopy(RepeatedScalarContainer* self, PyObject* arg) { return reinterpret_cast<PyObject*>(clone); } -static void Dealloc(RepeatedScalarContainer* self) { +static void Dealloc(PyObject* pself) { + RepeatedScalarContainer* self = + reinterpret_cast<RepeatedScalarContainer*>(pself); self->owner.reset(); - Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); + Py_TYPE(self)->tp_free(pself); } void SetOwner(RepeatedScalarContainer* self, - const shared_ptr<Message>& new_owner) { + const CMessage::OwnerRef& new_owner) { self->owner = new_owner; } static PySequenceMethods SqMethods = { - (lenfunc)Len, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - (ssizeargfunc)Item, /* sq_item */ - 0, /* sq_slice */ - (ssizeobjargproc)AssignItem /* sq_ass_item */ + Len, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + Item, /* sq_item */ + 0, /* sq_slice */ + AssignItem /* sq_ass_item */ }; static PyMappingMethods MpMethods = { - (lenfunc)Len, /* mp_length */ - (binaryfunc)Subscript, /* mp_subscript */ - (objobjargproc)AssSubscript, /* mp_ass_subscript */ + Len, /* mp_length */ + Subscript, /* mp_subscript */ + AssSubscript, /* mp_ass_subscript */ }; static PyMethodDef Methods[] = { - { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, + { "__deepcopy__", DeepCopy, METH_VARARGS, "Makes a deep copy of the class." }, - { "__reduce__", (PyCFunction)Reduce, METH_NOARGS, + { "__reduce__", Reduce, METH_NOARGS, "Outputs picklable representation of the repeated field." }, - { "append", (PyCFunction)Append, METH_O, + { "append", AppendMethod, METH_O, "Appends an object to the repeated container." }, - { "extend", (PyCFunction)Extend, METH_O, - "Appends objects to the repeated container." }, - { "insert", (PyCFunction)Insert, METH_VARARGS, + { "extend", ExtendMethod, METH_O, "Appends objects to the repeated container." }, - { "pop", (PyCFunction)Pop, METH_VARARGS, + { "insert", Insert, METH_VARARGS, + "Inserts an object at the specified position in the container." }, + { "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, "Sorts the repeated container."}, @@ -772,12 +786,12 @@ PyTypeObject RepeatedScalarContainer_Type = { FULL_MODULE_NAME ".RepeatedScalarContainer", // tp_name sizeof(RepeatedScalarContainer), // tp_basicsize 0, // tp_itemsize - (destructor)repeated_scalar_container::Dealloc, // tp_dealloc + repeated_scalar_container::Dealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr 0, // tp_compare - (reprfunc)repeated_scalar_container::ToStr, // tp_repr + repeated_scalar_container::ToStr, // tp_repr 0, // tp_as_number &repeated_scalar_container::SqMethods, // tp_as_sequence &repeated_scalar_container::MpMethods, // tp_as_mapping @@ -791,7 +805,7 @@ PyTypeObject RepeatedScalarContainer_Type = { "A Repeated scalar container", // tp_doc 0, // tp_traverse 0, // tp_clear - (richcmpfunc)repeated_scalar_container::RichCompare, // tp_richcompare + repeated_scalar_container::RichCompare, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter 0, // tp_iternext diff --git a/python/google/protobuf/pyext/repeated_scalar_container.h b/python/google/protobuf/pyext/repeated_scalar_container.h index 555e621c..559dec98 100644 --- a/python/google/protobuf/pyext/repeated_scalar_container.h +++ b/python/google/protobuf/pyext/repeated_scalar_container.h @@ -37,27 +37,14 @@ #include <Python.h> #include <memory> -#ifndef _SHARED_PTR_H -#include <google/protobuf/stubs/shared_ptr.h> -#endif #include <google/protobuf/descriptor.h> +#include <google/protobuf/pyext/message.h> namespace google { namespace protobuf { - -class Message; - -#ifdef _SHARED_PTR_H -using std::shared_ptr; -#else -using internal::shared_ptr; -#endif - namespace python { -struct CMessage; - typedef struct RepeatedScalarContainer { PyObject_HEAD; @@ -65,7 +52,7 @@ typedef struct RepeatedScalarContainer { // proto tree. Every Python RepeatedScalarContainer holds a // reference to it in order to keep it alive as long as there's a // Python object that references any part of the tree. - shared_ptr<Message> owner; + CMessage::OwnerRef owner; // Pointer to the C++ Message that contains this container. The // RepeatedScalarContainer does not own this pointer. @@ -112,7 +99,7 @@ PyObject* Extend(RepeatedScalarContainer* self, PyObject* value); // Set the owner field of self and any children of self. void SetOwner(RepeatedScalarContainer* self, - const shared_ptr<Message>& new_owner); + const CMessage::OwnerRef& new_owner); } // namespace repeated_scalar_container } // namespace python diff --git a/python/google/protobuf/pyext/thread_unsafe_shared_ptr.h b/python/google/protobuf/pyext/thread_unsafe_shared_ptr.h new file mode 100644 index 00000000..ad804b5f --- /dev/null +++ b/python/google/protobuf/pyext/thread_unsafe_shared_ptr.h @@ -0,0 +1,104 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ThreadUnsafeSharedPtr<T> is the same as shared_ptr<T> without the locking +// overhread (and thread-safety). +#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_THREAD_UNSAFE_SHARED_PTR_H__ +#define GOOGLE_PROTOBUF_PYTHON_CPP_THREAD_UNSAFE_SHARED_PTR_H__ + +#include <algorithm> +#include <utility> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> + +namespace google { +namespace protobuf { +namespace python { + +template <typename T> +class ThreadUnsafeSharedPtr { + public: + // Takes ownership. + explicit ThreadUnsafeSharedPtr(T* ptr) + : ptr_(ptr), refcount_(ptr ? new RefcountT(1) : nullptr) { + } + + ThreadUnsafeSharedPtr(const ThreadUnsafeSharedPtr& other) + : ThreadUnsafeSharedPtr(nullptr) { + *this = other; + } + + ThreadUnsafeSharedPtr& operator=(const ThreadUnsafeSharedPtr& other) { + if (other.refcount_ == refcount_) { + return *this; + } + this->~ThreadUnsafeSharedPtr(); + ptr_ = other.ptr_; + refcount_ = other.refcount_; + if (refcount_) { + ++*refcount_; + } + return *this; + } + + ~ThreadUnsafeSharedPtr() { + if (refcount_ == nullptr) { + GOOGLE_DCHECK(ptr_ == nullptr); + return; + } + if (--*refcount_ == 0) { + delete refcount_; + delete ptr_; + } + } + + void reset(T* ptr = nullptr) { *this = ThreadUnsafeSharedPtr(ptr); } + + T* get() { return ptr_; } + const T* get() const { return ptr_; } + + void swap(ThreadUnsafeSharedPtr& other) { + using std::swap; + swap(ptr_, other.ptr_); + swap(refcount_, other.refcount_); + } + + private: + typedef int RefcountT; + T* ptr_; + RefcountT* refcount_; +}; + +} // namespace python +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_PYTHON_CPP_THREAD_UNSAFE_SHARED_PTR_H__ |