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 |