aboutsummaryrefslogtreecommitdiff
path: root/python/google/protobuf/pyext/descriptor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'python/google/protobuf/pyext/descriptor.cc')
-rw-r--r--python/google/protobuf/pyext/descriptor.cc51
1 files changed, 34 insertions, 17 deletions
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index 8af0cb12..3cb16b74 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -32,8 +32,8 @@
#include <Python.h>
#include <frameobject.h>
-#include <google/protobuf/stubs/hash.h>
#include <string>
+#include <unordered_map>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/descriptor.pb.h>
@@ -44,6 +44,7 @@
#include <google/protobuf/pyext/message.h>
#include <google/protobuf/pyext/message_factory.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+#include <google/protobuf/stubs/hash.h>
#if PY_MAJOR_VERSION >= 3
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
@@ -54,10 +55,12 @@
#if PY_VERSION_HEX < 0x03030000
#error "Python 3.0 - 3.2 are not supported."
#endif
- #define PyString_AsStringAndSize(ob, charpp, sizep) \
- (PyUnicode_Check(ob)? \
- ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
- PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
+#define PyString_AsStringAndSize(ob, charpp, sizep) \
+ (PyUnicode_Check(ob) ? ((*(charpp) = const_cast<char*>( \
+ PyUnicode_AsUTF8AndSize(ob, (sizep)))) == NULL \
+ ? -1 \
+ : 0) \
+ : PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
#endif
namespace google {
@@ -70,7 +73,7 @@ namespace python {
// released.
// This is enough to support the "is" operator on live objects.
// All descriptors are stored here.
-hash_map<const void*, PyObject*> interned_descriptors;
+std::unordered_map<const void*, PyObject*>* interned_descriptors;
PyObject* PyString_FromCppString(const string& str) {
return PyString_FromStringAndSize(str.c_str(), str.size());
@@ -119,8 +122,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.
+ 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) {
@@ -131,7 +136,7 @@ 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;
@@ -197,7 +202,7 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
// First search in the cache.
PyDescriptorPool* caching_pool = GetDescriptorPool_FromPool(
GetFileDescriptor(descriptor)->pool());
- hash_map<const void*, PyObject*>* descriptor_options =
+ std::unordered_map<const void*, PyObject*>* descriptor_options =
caching_pool->descriptor_options;
if (descriptor_options->find(descriptor) != descriptor_options->end()) {
PyObject *value = (*descriptor_options)[descriptor];
@@ -232,7 +237,7 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
if (value == NULL) {
return NULL;
}
- if (!PyObject_TypeCheck(value.get(), &CMessage_Type)) {
+ if (!PyObject_TypeCheck(value.get(), CMessage_Type)) {
PyErr_Format(PyExc_TypeError, "Invalid class for %s: %s",
message_type->full_name().c_str(),
Py_TYPE(value.get())->tp_name);
@@ -275,7 +280,7 @@ static PyObject* CopyToPythonProto(const DescriptorClass *descriptor,
const Descriptor* self_descriptor =
DescriptorProtoClass::default_instance().GetDescriptor();
CMessage* message = reinterpret_cast<CMessage*>(target);
- if (!PyObject_TypeCheck(target, &CMessage_Type) ||
+ if (!PyObject_TypeCheck(target, CMessage_Type) ||
message->message->GetDescriptor() != self_descriptor) {
PyErr_Format(PyExc_TypeError, "Not a %s message",
self_descriptor->full_name().c_str());
@@ -332,9 +337,9 @@ PyObject* NewInternedDescriptor(PyTypeObject* type,
}
// See if the object is in the map of interned descriptors
- hash_map<const void*, PyObject*>::iterator it =
- interned_descriptors.find(descriptor);
- if (it != interned_descriptors.end()) {
+ std::unordered_map<const void*, PyObject*>::iterator it =
+ interned_descriptors->find(descriptor);
+ if (it != interned_descriptors->end()) {
GOOGLE_DCHECK(Py_TYPE(it->second) == type);
Py_INCREF(it->second);
return it->second;
@@ -348,7 +353,7 @@ PyObject* NewInternedDescriptor(PyTypeObject* type,
py_descriptor->descriptor = descriptor;
// and cache it.
- interned_descriptors.insert(
+ interned_descriptors->insert(
std::make_pair(descriptor, reinterpret_cast<PyObject*>(py_descriptor)));
// Ensures that the DescriptorPool stays alive.
@@ -370,7 +375,7 @@ PyObject* NewInternedDescriptor(PyTypeObject* type,
static void Dealloc(PyBaseDescriptor* self) {
// Remove from interned dictionary
- interned_descriptors.erase(self->descriptor);
+ interned_descriptors->erase(self->descriptor);
Py_CLEAR(self->pool);
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
}
@@ -758,6 +763,11 @@ static PyObject* HasDefaultValue(PyBaseDescriptor *self, void *closure) {
static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) {
PyObject *result;
+ if (_GetDescriptor(self)->is_repeated()) {
+ return PyList_New(0);
+ }
+
+
switch (_GetDescriptor(self)->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32: {
int32 value = _GetDescriptor(self)->default_value_int32();
@@ -805,6 +815,10 @@ static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) {
result = PyInt_FromLong(value->number());
break;
}
+ case FieldDescriptor::CPPTYPE_MESSAGE: {
+ Py_RETURN_NONE;
+ break;
+ }
default:
PyErr_Format(PyExc_NotImplementedError, "default value for %s",
_GetDescriptor(self)->full_name().c_str());
@@ -1919,6 +1933,9 @@ bool InitDescriptor() {
if (!InitDescriptorMappingTypes())
return false;
+ // Initialize globals defined in this file.
+ interned_descriptors = new std::unordered_map<const void*, PyObject*>;
+
return true;
}