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> | |
42 #include <google/protobuf/pyext/descriptor.h> | 41 #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> | |
45 #include <google/protobuf/pyext/repeated_composite_container.h> | 44 #include <google/protobuf/pyext/repeated_composite_container.h> |
46 #include <google/protobuf/pyext/repeated_scalar_container.h> | 45 #include <google/protobuf/pyext/repeated_scalar_container.h> |
47 #include <google/protobuf/pyext/scoped_pyobject_ptr.h> | 46 #include <google/protobuf/pyext/scoped_pyobject_ptr.h> |
48 #include <google/protobuf/stubs/shared_ptr.h> | 47 #include <google/protobuf/stubs/shared_ptr.h> |
49 | 48 |
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 | |
60 namespace google { | 49 namespace google { |
61 namespace protobuf { | 50 namespace protobuf { |
62 namespace python { | 51 namespace python { |
63 | 52 |
64 namespace extension_dict { | 53 namespace extension_dict { |
65 | 54 |
66 PyObject* len(ExtensionDict* self) { | 55 PyObject* len(ExtensionDict* self) { |
67 #if PY_MAJOR_VERSION >= 3 | 56 #if PY_MAJOR_VERSION >= 3 |
68 return PyLong_FromLong(PyDict_Size(self->values)); | 57 return PyLong_FromLong(PyDict_Size(self->values)); |
69 #else | 58 #else |
70 return PyInt_FromLong(PyDict_Size(self->values)); | 59 return PyInt_FromLong(PyDict_Size(self->values)); |
71 #endif | 60 #endif |
72 } | 61 } |
73 | 62 |
| 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 |
74 PyObject* subscript(ExtensionDict* self, PyObject* key) { | 92 PyObject* subscript(ExtensionDict* self, PyObject* key) { |
75 const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key); | 93 const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key); |
76 if (descriptor == NULL) { | 94 if (descriptor == NULL) { |
77 return NULL; | 95 return NULL; |
78 } | 96 } |
79 if (!CheckFieldBelongsToMessage(descriptor, self->message)) { | 97 if (!CheckFieldBelongsToMessage(descriptor, self->message)) { |
80 return NULL; | 98 return NULL; |
81 } | 99 } |
82 | 100 |
83 if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && | 101 if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && |
(...skipping 10 matching lines...) Expand all Loading... |
94 if (self->parent == NULL) { | 112 if (self->parent == NULL) { |
95 // We are in "detached" state. Don't allow further modifications. | 113 // We are in "detached" state. Don't allow further modifications. |
96 // TODO(amauryfa): Support adding non-scalars to a detached extension dict. | 114 // TODO(amauryfa): Support adding non-scalars to a detached extension dict. |
97 // This probably requires to store the type of the main message. | 115 // This probably requires to store the type of the main message. |
98 PyErr_SetObject(PyExc_KeyError, key); | 116 PyErr_SetObject(PyExc_KeyError, key); |
99 return NULL; | 117 return NULL; |
100 } | 118 } |
101 | 119 |
102 if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && | 120 if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && |
103 descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | 121 descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
104 // TODO(plabatut): consider building the class on the fly! | |
105 PyObject* sub_message = cmessage::InternalGetSubMessage( | 122 PyObject* sub_message = cmessage::InternalGetSubMessage( |
106 self->parent, descriptor); | 123 self->parent, descriptor); |
107 if (sub_message == NULL) { | 124 if (sub_message == NULL) { |
108 return NULL; | 125 return NULL; |
109 } | 126 } |
110 PyDict_SetItem(self->values, key, sub_message); | 127 PyDict_SetItem(self->values, key, sub_message); |
111 return sub_message; | 128 return sub_message; |
112 } | 129 } |
113 | 130 |
114 if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { | 131 if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { |
115 if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | 132 if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
116 // On the fly message class creation is needed to support the following | 133 CMessageClass* message_class = cdescriptor_pool::GetMessageClass( |
117 // situation: | 134 cmessage::GetDescriptorPoolForMessage(self->parent), |
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), | |
128 descriptor->message_type()); | 135 descriptor->message_type()); |
129 if (message_class == NULL) { | 136 if (message_class == NULL) { |
130 return NULL; | 137 return NULL; |
131 } | 138 } |
132 PyObject* py_container = repeated_composite_container::NewContainer( | 139 PyObject* py_container = repeated_composite_container::NewContainer( |
133 self->parent, descriptor, message_class); | 140 self->parent, descriptor, message_class); |
134 if (py_container == NULL) { | 141 if (py_container == NULL) { |
135 return NULL; | 142 return NULL; |
136 } | 143 } |
137 PyDict_SetItem(self->values, key, py_container); | 144 PyDict_SetItem(self->values, key, py_container); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 cmessage::AssureWritable(self->parent); | 176 cmessage::AssureWritable(self->parent); |
170 if (cmessage::InternalSetScalar(self->parent, descriptor, value) < 0) { | 177 if (cmessage::InternalSetScalar(self->parent, descriptor, value) < 0) { |
171 return -1; | 178 return -1; |
172 } | 179 } |
173 } | 180 } |
174 // TODO(tibell): We shouldn't write scalars to the cache. | 181 // TODO(tibell): We shouldn't write scalars to the cache. |
175 PyDict_SetItem(self->values, key, value); | 182 PyDict_SetItem(self->values, key, value); |
176 return 0; | 183 return 0; |
177 } | 184 } |
178 | 185 |
179 PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* arg) { | 186 PyObject* ClearExtension(ExtensionDict* self, PyObject* extension) { |
180 char* name; | 187 const FieldDescriptor* descriptor = |
181 Py_ssize_t name_size; | 188 cmessage::GetExtensionDescriptor(extension); |
182 if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { | 189 if (descriptor == NULL) { |
183 return NULL; | 190 return NULL; |
184 } | 191 } |
185 | 192 PyObject* value = PyDict_GetItem(self->values, extension); |
186 PyDescriptorPool* pool = cmessage::GetFactoryForMessage(self->parent)->pool; | 193 if (self->parent) { |
187 const FieldDescriptor* message_extension = | 194 if (value != NULL) { |
188 pool->pool->FindExtensionByName(string(name, name_size)); | 195 if (ReleaseExtension(self, value, descriptor) < 0) { |
189 if (message_extension == NULL) { | 196 return 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; | |
200 } | 197 } |
201 } | 198 } |
| 199 if (ScopedPyObjectPtr(cmessage::ClearFieldByDescriptor( |
| 200 self->parent, descriptor)) == NULL) { |
| 201 return NULL; |
| 202 } |
202 } | 203 } |
203 if (message_extension == NULL) { | 204 if (PyDict_DelItem(self->values, extension) < 0) { |
204 Py_RETURN_NONE; | 205 PyErr_Clear(); |
205 } | 206 } |
206 | 207 Py_RETURN_NONE; |
207 return PyFieldDescriptor_FromDescriptor(message_extension); | |
208 } | 208 } |
209 | 209 |
210 PyObject* _FindExtensionByNumber(ExtensionDict* self, PyObject* arg) { | 210 PyObject* HasExtension(ExtensionDict* self, PyObject* extension) { |
211 int64 number = PyLong_AsLong(arg); | 211 const FieldDescriptor* descriptor = |
212 if (number == -1 && PyErr_Occurred()) { | 212 cmessage::GetExtensionDescriptor(extension); |
| 213 if (descriptor == NULL) { |
213 return NULL; | 214 return NULL; |
214 } | 215 } |
| 216 if (self->parent) { |
| 217 return cmessage::HasFieldByDescriptor(self->parent, descriptor); |
| 218 } else { |
| 219 int exists = PyDict_Contains(self->values, extension); |
| 220 if (exists < 0) { |
| 221 return NULL; |
| 222 } |
| 223 return PyBool_FromLong(exists); |
| 224 } |
| 225 } |
215 | 226 |
216 PyDescriptorPool* pool = cmessage::GetFactoryForMessage(self->parent)->pool; | 227 PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* name) { |
217 const FieldDescriptor* message_extension = pool->pool->FindExtensionByNumber( | 228 ScopedPyObjectPtr extensions_by_name(PyObject_GetAttrString( |
218 self->parent->message->GetDescriptor(), number); | 229 reinterpret_cast<PyObject*>(self->parent), "_extensions_by_name")); |
219 if (message_extension == NULL) { | 230 if (extensions_by_name == NULL) { |
| 231 return NULL; |
| 232 } |
| 233 PyObject* result = PyDict_GetItem(extensions_by_name.get(), name); |
| 234 if (result == NULL) { |
220 Py_RETURN_NONE; | 235 Py_RETURN_NONE; |
| 236 } else { |
| 237 Py_INCREF(result); |
| 238 return result; |
221 } | 239 } |
| 240 } |
222 | 241 |
223 return PyFieldDescriptor_FromDescriptor(message_extension); | 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 } |
224 } | 255 } |
225 | 256 |
226 ExtensionDict* NewExtensionDict(CMessage *parent) { | 257 ExtensionDict* NewExtensionDict(CMessage *parent) { |
227 ExtensionDict* self = reinterpret_cast<ExtensionDict*>( | 258 ExtensionDict* self = reinterpret_cast<ExtensionDict*>( |
228 PyType_GenericAlloc(&ExtensionDict_Type, 0)); | 259 PyType_GenericAlloc(&ExtensionDict_Type, 0)); |
229 if (self == NULL) { | 260 if (self == NULL) { |
230 return NULL; | 261 return NULL; |
231 } | 262 } |
232 | 263 |
233 self->parent = parent; // Store a borrowed reference. | 264 self->parent = parent; // Store a borrowed reference. |
(...skipping 10 matching lines...) Expand all Loading... |
244 } | 275 } |
245 | 276 |
246 static PyMappingMethods MpMethods = { | 277 static PyMappingMethods MpMethods = { |
247 (lenfunc)len, /* mp_length */ | 278 (lenfunc)len, /* mp_length */ |
248 (binaryfunc)subscript, /* mp_subscript */ | 279 (binaryfunc)subscript, /* mp_subscript */ |
249 (objobjargproc)ass_subscript,/* mp_ass_subscript */ | 280 (objobjargproc)ass_subscript,/* mp_ass_subscript */ |
250 }; | 281 }; |
251 | 282 |
252 #define EDMETHOD(name, args, doc) { #name, (PyCFunction)name, args, doc } | 283 #define EDMETHOD(name, args, doc) { #name, (PyCFunction)name, args, doc } |
253 static PyMethodDef Methods[] = { | 284 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."), |
254 EDMETHOD(_FindExtensionByName, METH_O, | 287 EDMETHOD(_FindExtensionByName, METH_O, |
255 "Finds an extension by name."), | 288 "Finds an extension by name."), |
256 EDMETHOD(_FindExtensionByNumber, METH_O, | 289 EDMETHOD(_FindExtensionByNumber, METH_O, |
257 "Finds an extension by field number."), | 290 "Finds an extension by field number."), |
258 { NULL, NULL } | 291 { NULL, NULL } |
259 }; | 292 }; |
260 | 293 |
261 } // namespace extension_dict | 294 } // namespace extension_dict |
262 | 295 |
263 PyTypeObject ExtensionDict_Type = { | 296 PyTypeObject ExtensionDict_Type = { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 0, // tp_dict | 328 0, // tp_dict |
296 0, // tp_descr_get | 329 0, // tp_descr_get |
297 0, // tp_descr_set | 330 0, // tp_descr_set |
298 0, // tp_dictoffset | 331 0, // tp_dictoffset |
299 0, // tp_init | 332 0, // tp_init |
300 }; | 333 }; |
301 | 334 |
302 } // namespace python | 335 } // namespace python |
303 } // namespace protobuf | 336 } // namespace protobuf |
304 } // namespace google | 337 } // namespace google |
OLD | NEW |