| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 // Author: anuraag@google.com (Anuraag Agrawal) | 31 // Author: anuraag@google.com (Anuraag Agrawal) |
| 32 // Author: tibell@google.com (Johan Tibell) | 32 // Author: tibell@google.com (Johan Tibell) |
| 33 | 33 |
| 34 #include <google/protobuf/pyext/extension_dict.h> | 34 #include <google/protobuf/pyext/extension_dict.h> |
| 35 | 35 |
| 36 #include <google/protobuf/stubs/logging.h> | 36 #include <google/protobuf/stubs/logging.h> |
| 37 #include <google/protobuf/stubs/common.h> | 37 #include <google/protobuf/stubs/common.h> |
| 38 #include <google/protobuf/descriptor.h> | 38 #include <google/protobuf/descriptor.h> |
| 39 #include <google/protobuf/dynamic_message.h> | 39 #include <google/protobuf/dynamic_message.h> |
| 40 #include <google/protobuf/message.h> | 40 #include <google/protobuf/message.h> |
| 41 #include <google/protobuf/descriptor.pb.h> |
| 41 #include <google/protobuf/pyext/descriptor.h> | 42 #include <google/protobuf/pyext/descriptor.h> |
| 42 #include <google/protobuf/pyext/descriptor_pool.h> | |
| 43 #include <google/protobuf/pyext/message.h> | 43 #include <google/protobuf/pyext/message.h> |
| 44 #include <google/protobuf/pyext/message_factory.h> |
| 44 #include <google/protobuf/pyext/repeated_composite_container.h> | 45 #include <google/protobuf/pyext/repeated_composite_container.h> |
| 45 #include <google/protobuf/pyext/repeated_scalar_container.h> | 46 #include <google/protobuf/pyext/repeated_scalar_container.h> |
| 46 #include <google/protobuf/pyext/scoped_pyobject_ptr.h> | 47 #include <google/protobuf/pyext/scoped_pyobject_ptr.h> |
| 47 #include <google/protobuf/stubs/shared_ptr.h> | 48 #include <google/protobuf/stubs/shared_ptr.h> |
| 48 | 49 |
| 50 #if PY_MAJOR_VERSION >= 3 |
| 51 #if PY_VERSION_HEX < 0x03030000 |
| 52 #error "Python 3.0 - 3.2 are not supported." |
| 53 #endif |
| 54 #define PyString_AsStringAndSize(ob, charpp, sizep) \ |
| 55 (PyUnicode_Check(ob)? \ |
| 56 ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \ |
| 57 PyBytes_AsStringAndSize(ob, (charpp), (sizep))) |
| 58 #endif |
| 59 |
| 49 namespace google { | 60 namespace google { |
| 50 namespace protobuf { | 61 namespace protobuf { |
| 51 namespace python { | 62 namespace python { |
| 52 | 63 |
| 53 namespace extension_dict { | 64 namespace extension_dict { |
| 54 | 65 |
| 55 PyObject* len(ExtensionDict* self) { | 66 PyObject* len(ExtensionDict* self) { |
| 56 #if PY_MAJOR_VERSION >= 3 | 67 #if PY_MAJOR_VERSION >= 3 |
| 57 return PyLong_FromLong(PyDict_Size(self->values)); | 68 return PyLong_FromLong(PyDict_Size(self->values)); |
| 58 #else | 69 #else |
| 59 return PyInt_FromLong(PyDict_Size(self->values)); | 70 return PyInt_FromLong(PyDict_Size(self->values)); |
| 60 #endif | 71 #endif |
| 61 } | 72 } |
| 62 | 73 |
| 63 // TODO(tibell): Use VisitCompositeField. | |
| 64 int ReleaseExtension(ExtensionDict* self, | |
| 65 PyObject* extension, | |
| 66 const FieldDescriptor* descriptor) { | |
| 67 if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { | |
| 68 if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | |
| 69 if (repeated_composite_container::Release( | |
| 70 reinterpret_cast<RepeatedCompositeContainer*>( | |
| 71 extension)) < 0) { | |
| 72 return -1; | |
| 73 } | |
| 74 } else { | |
| 75 if (repeated_scalar_container::Release( | |
| 76 reinterpret_cast<RepeatedScalarContainer*>( | |
| 77 extension)) < 0) { | |
| 78 return -1; | |
| 79 } | |
| 80 } | |
| 81 } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | |
| 82 if (cmessage::ReleaseSubMessage( | |
| 83 self->parent, descriptor, | |
| 84 reinterpret_cast<CMessage*>(extension)) < 0) { | |
| 85 return -1; | |
| 86 } | |
| 87 } | |
| 88 | |
| 89 return 0; | |
| 90 } | |
| 91 | |
| 92 PyObject* subscript(ExtensionDict* self, PyObject* key) { | 74 PyObject* subscript(ExtensionDict* self, PyObject* key) { |
| 93 const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key); | 75 const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key); |
| 94 if (descriptor == NULL) { | 76 if (descriptor == NULL) { |
| 95 return NULL; | 77 return NULL; |
| 96 } | 78 } |
| 97 if (!CheckFieldBelongsToMessage(descriptor, self->message)) { | 79 if (!CheckFieldBelongsToMessage(descriptor, self->message)) { |
| 98 return NULL; | 80 return NULL; |
| 99 } | 81 } |
| 100 | 82 |
| 101 if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && | 83 if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && |
| (...skipping 10 matching lines...) Expand all Loading... |
| 112 if (self->parent == NULL) { | 94 if (self->parent == NULL) { |
| 113 // We are in "detached" state. Don't allow further modifications. | 95 // We are in "detached" state. Don't allow further modifications. |
| 114 // TODO(amauryfa): Support adding non-scalars to a detached extension dict. | 96 // TODO(amauryfa): Support adding non-scalars to a detached extension dict. |
| 115 // This probably requires to store the type of the main message. | 97 // This probably requires to store the type of the main message. |
| 116 PyErr_SetObject(PyExc_KeyError, key); | 98 PyErr_SetObject(PyExc_KeyError, key); |
| 117 return NULL; | 99 return NULL; |
| 118 } | 100 } |
| 119 | 101 |
| 120 if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && | 102 if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && |
| 121 descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | 103 descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
| 104 // TODO(plabatut): consider building the class on the fly! |
| 122 PyObject* sub_message = cmessage::InternalGetSubMessage( | 105 PyObject* sub_message = cmessage::InternalGetSubMessage( |
| 123 self->parent, descriptor); | 106 self->parent, descriptor); |
| 124 if (sub_message == NULL) { | 107 if (sub_message == NULL) { |
| 125 return NULL; | 108 return NULL; |
| 126 } | 109 } |
| 127 PyDict_SetItem(self->values, key, sub_message); | 110 PyDict_SetItem(self->values, key, sub_message); |
| 128 return sub_message; | 111 return sub_message; |
| 129 } | 112 } |
| 130 | 113 |
| 131 if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { | 114 if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { |
| 132 if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | 115 if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
| 133 CMessageClass* message_class = cdescriptor_pool::GetMessageClass( | 116 // On the fly message class creation is needed to support the following |
| 134 cmessage::GetDescriptorPoolForMessage(self->parent), | 117 // situation: |
| 118 // 1- add FileDescriptor to the pool that contains extensions of a message |
| 119 // defined by another proto file. Do not create any message classes. |
| 120 // 2- instantiate an extended message, and access the extension using |
| 121 // the field descriptor. |
| 122 // 3- the extension submessage fails to be returned, because no class has |
| 123 // been created. |
| 124 // It happens when deserializing text proto format, or when enumerating |
| 125 // fields of a deserialized message. |
| 126 CMessageClass* message_class = message_factory::GetOrCreateMessageClass( |
| 127 cmessage::GetFactoryForMessage(self->parent), |
| 135 descriptor->message_type()); | 128 descriptor->message_type()); |
| 136 if (message_class == NULL) { | 129 if (message_class == NULL) { |
| 137 return NULL; | 130 return NULL; |
| 138 } | 131 } |
| 139 PyObject* py_container = repeated_composite_container::NewContainer( | 132 PyObject* py_container = repeated_composite_container::NewContainer( |
| 140 self->parent, descriptor, message_class); | 133 self->parent, descriptor, message_class); |
| 141 if (py_container == NULL) { | 134 if (py_container == NULL) { |
| 142 return NULL; | 135 return NULL; |
| 143 } | 136 } |
| 144 PyDict_SetItem(self->values, key, py_container); | 137 PyDict_SetItem(self->values, key, py_container); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 cmessage::AssureWritable(self->parent); | 169 cmessage::AssureWritable(self->parent); |
| 177 if (cmessage::InternalSetScalar(self->parent, descriptor, value) < 0) { | 170 if (cmessage::InternalSetScalar(self->parent, descriptor, value) < 0) { |
| 178 return -1; | 171 return -1; |
| 179 } | 172 } |
| 180 } | 173 } |
| 181 // TODO(tibell): We shouldn't write scalars to the cache. | 174 // TODO(tibell): We shouldn't write scalars to the cache. |
| 182 PyDict_SetItem(self->values, key, value); | 175 PyDict_SetItem(self->values, key, value); |
| 183 return 0; | 176 return 0; |
| 184 } | 177 } |
| 185 | 178 |
| 186 PyObject* ClearExtension(ExtensionDict* self, PyObject* extension) { | 179 PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* arg) { |
| 187 const FieldDescriptor* descriptor = | 180 char* name; |
| 188 cmessage::GetExtensionDescriptor(extension); | 181 Py_ssize_t name_size; |
| 189 if (descriptor == NULL) { | 182 if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { |
| 190 return NULL; | 183 return NULL; |
| 191 } | 184 } |
| 192 PyObject* value = PyDict_GetItem(self->values, extension); | 185 |
| 193 if (self->parent) { | 186 PyDescriptorPool* pool = cmessage::GetFactoryForMessage(self->parent)->pool; |
| 194 if (value != NULL) { | 187 const FieldDescriptor* message_extension = |
| 195 if (ReleaseExtension(self, value, descriptor) < 0) { | 188 pool->pool->FindExtensionByName(string(name, name_size)); |
| 196 return NULL; | 189 if (message_extension == NULL) { |
| 190 // Is is the name of a message set extension? |
| 191 const Descriptor* message_descriptor = pool->pool->FindMessageTypeByName( |
| 192 string(name, name_size)); |
| 193 if (message_descriptor && message_descriptor->extension_count() > 0) { |
| 194 const FieldDescriptor* extension = message_descriptor->extension(0); |
| 195 if (extension->is_extension() && |
| 196 extension->containing_type()->options().message_set_wire_format() && |
| 197 extension->type() == FieldDescriptor::TYPE_MESSAGE && |
| 198 extension->label() == FieldDescriptor::LABEL_OPTIONAL) { |
| 199 message_extension = extension; |
| 197 } | 200 } |
| 198 } | 201 } |
| 199 if (ScopedPyObjectPtr(cmessage::ClearFieldByDescriptor( | |
| 200 self->parent, descriptor)) == NULL) { | |
| 201 return NULL; | |
| 202 } | |
| 203 } | 202 } |
| 204 if (PyDict_DelItem(self->values, extension) < 0) { | 203 if (message_extension == NULL) { |
| 205 PyErr_Clear(); | 204 Py_RETURN_NONE; |
| 206 } | 205 } |
| 207 Py_RETURN_NONE; | 206 |
| 207 return PyFieldDescriptor_FromDescriptor(message_extension); |
| 208 } | 208 } |
| 209 | 209 |
| 210 PyObject* HasExtension(ExtensionDict* self, PyObject* extension) { | 210 PyObject* _FindExtensionByNumber(ExtensionDict* self, PyObject* arg) { |
| 211 const FieldDescriptor* descriptor = | 211 int64 number = PyLong_AsLong(arg); |
| 212 cmessage::GetExtensionDescriptor(extension); | 212 if (number == -1 && PyErr_Occurred()) { |
| 213 if (descriptor == NULL) { | |
| 214 return NULL; | 213 return NULL; |
| 215 } | 214 } |
| 216 if (self->parent) { | 215 |
| 217 return cmessage::HasFieldByDescriptor(self->parent, descriptor); | 216 PyDescriptorPool* pool = cmessage::GetFactoryForMessage(self->parent)->pool; |
| 218 } else { | 217 const FieldDescriptor* message_extension = pool->pool->FindExtensionByNumber( |
| 219 int exists = PyDict_Contains(self->values, extension); | 218 self->parent->message->GetDescriptor(), number); |
| 220 if (exists < 0) { | 219 if (message_extension == NULL) { |
| 221 return NULL; | 220 Py_RETURN_NONE; |
| 222 } | |
| 223 return PyBool_FromLong(exists); | |
| 224 } | 221 } |
| 225 } | |
| 226 | 222 |
| 227 PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* name) { | 223 return PyFieldDescriptor_FromDescriptor(message_extension); |
| 228 ScopedPyObjectPtr extensions_by_name(PyObject_GetAttrString( | |
| 229 reinterpret_cast<PyObject*>(self->parent), "_extensions_by_name")); | |
| 230 if (extensions_by_name == NULL) { | |
| 231 return NULL; | |
| 232 } | |
| 233 PyObject* result = PyDict_GetItem(extensions_by_name.get(), name); | |
| 234 if (result == NULL) { | |
| 235 Py_RETURN_NONE; | |
| 236 } else { | |
| 237 Py_INCREF(result); | |
| 238 return result; | |
| 239 } | |
| 240 } | |
| 241 | |
| 242 PyObject* _FindExtensionByNumber(ExtensionDict* self, PyObject* number) { | |
| 243 ScopedPyObjectPtr extensions_by_number(PyObject_GetAttrString( | |
| 244 reinterpret_cast<PyObject*>(self->parent), "_extensions_by_number")); | |
| 245 if (extensions_by_number == NULL) { | |
| 246 return NULL; | |
| 247 } | |
| 248 PyObject* result = PyDict_GetItem(extensions_by_number.get(), number); | |
| 249 if (result == NULL) { | |
| 250 Py_RETURN_NONE; | |
| 251 } else { | |
| 252 Py_INCREF(result); | |
| 253 return result; | |
| 254 } | |
| 255 } | 224 } |
| 256 | 225 |
| 257 ExtensionDict* NewExtensionDict(CMessage *parent) { | 226 ExtensionDict* NewExtensionDict(CMessage *parent) { |
| 258 ExtensionDict* self = reinterpret_cast<ExtensionDict*>( | 227 ExtensionDict* self = reinterpret_cast<ExtensionDict*>( |
| 259 PyType_GenericAlloc(&ExtensionDict_Type, 0)); | 228 PyType_GenericAlloc(&ExtensionDict_Type, 0)); |
| 260 if (self == NULL) { | 229 if (self == NULL) { |
| 261 return NULL; | 230 return NULL; |
| 262 } | 231 } |
| 263 | 232 |
| 264 self->parent = parent; // Store a borrowed reference. | 233 self->parent = parent; // Store a borrowed reference. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 275 } | 244 } |
| 276 | 245 |
| 277 static PyMappingMethods MpMethods = { | 246 static PyMappingMethods MpMethods = { |
| 278 (lenfunc)len, /* mp_length */ | 247 (lenfunc)len, /* mp_length */ |
| 279 (binaryfunc)subscript, /* mp_subscript */ | 248 (binaryfunc)subscript, /* mp_subscript */ |
| 280 (objobjargproc)ass_subscript,/* mp_ass_subscript */ | 249 (objobjargproc)ass_subscript,/* mp_ass_subscript */ |
| 281 }; | 250 }; |
| 282 | 251 |
| 283 #define EDMETHOD(name, args, doc) { #name, (PyCFunction)name, args, doc } | 252 #define EDMETHOD(name, args, doc) { #name, (PyCFunction)name, args, doc } |
| 284 static PyMethodDef Methods[] = { | 253 static PyMethodDef Methods[] = { |
| 285 EDMETHOD(ClearExtension, METH_O, "Clears an extension from the object."), | |
| 286 EDMETHOD(HasExtension, METH_O, "Checks if the object has an extension."), | |
| 287 EDMETHOD(_FindExtensionByName, METH_O, | 254 EDMETHOD(_FindExtensionByName, METH_O, |
| 288 "Finds an extension by name."), | 255 "Finds an extension by name."), |
| 289 EDMETHOD(_FindExtensionByNumber, METH_O, | 256 EDMETHOD(_FindExtensionByNumber, METH_O, |
| 290 "Finds an extension by field number."), | 257 "Finds an extension by field number."), |
| 291 { NULL, NULL } | 258 { NULL, NULL } |
| 292 }; | 259 }; |
| 293 | 260 |
| 294 } // namespace extension_dict | 261 } // namespace extension_dict |
| 295 | 262 |
| 296 PyTypeObject ExtensionDict_Type = { | 263 PyTypeObject ExtensionDict_Type = { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 0, // tp_dict | 295 0, // tp_dict |
| 329 0, // tp_descr_get | 296 0, // tp_descr_get |
| 330 0, // tp_descr_set | 297 0, // tp_descr_set |
| 331 0, // tp_dictoffset | 298 0, // tp_dictoffset |
| 332 0, // tp_init | 299 0, // tp_init |
| 333 }; | 300 }; |
| 334 | 301 |
| 335 } // namespace python | 302 } // namespace python |
| 336 } // namespace protobuf | 303 } // namespace protobuf |
| 337 } // namespace google | 304 } // namespace google |
| OLD | NEW |