aboutsummaryrefslogtreecommitdiffhomepage
path: root/python/google/protobuf/pyext
diff options
context:
space:
mode:
Diffstat (limited to 'python/google/protobuf/pyext')
-rw-r--r--python/google/protobuf/pyext/descriptor.cc93
-rw-r--r--python/google/protobuf/pyext/descriptor_containers.cc530
-rw-r--r--python/google/protobuf/pyext/descriptor_pool.cc122
-rw-r--r--python/google/protobuf/pyext/extension_dict.cc3
-rw-r--r--python/google/protobuf/pyext/extension_dict.h15
-rw-r--r--python/google/protobuf/pyext/map_container.cc29
-rw-r--r--python/google/protobuf/pyext/map_container.h17
-rw-r--r--python/google/protobuf/pyext/message.cc141
-rw-r--r--python/google/protobuf/pyext/message.h46
-rw-r--r--python/google/protobuf/pyext/message_factory.cc8
-rw-r--r--python/google/protobuf/pyext/message_module.cc17
-rw-r--r--python/google/protobuf/pyext/repeated_composite_container.cc129
-rw-r--r--python/google/protobuf/pyext/repeated_composite_container.h21
-rw-r--r--python/google/protobuf/pyext/repeated_scalar_container.cc162
-rw-r--r--python/google/protobuf/pyext/repeated_scalar_container.h19
-rw-r--r--python/google/protobuf/pyext/thread_unsafe_shared_ptr.h104
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__