Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: third_party/protobuf/python/google/protobuf/pyext/message_factory.cc

Issue 2495533002: third_party/protobuf: Update to HEAD (83d681ee2c) (Closed)
Patch Set: Make chrome settings proto generated file a component Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 #include <Python.h>
32
33 #include <google/protobuf/dynamic_message.h>
34 #include <google/protobuf/pyext/descriptor.h>
35 #include <google/protobuf/pyext/message.h>
36 #include <google/protobuf/pyext/message_factory.h>
37 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
38
39 #if PY_MAJOR_VERSION >= 3
40 #if PY_VERSION_HEX < 0x03030000
41 #error "Python 3.0 - 3.2 are not supported."
42 #endif
43 #define PyString_AsStringAndSize(ob, charpp, sizep) \
44 (PyUnicode_Check(ob)? \
45 ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
46 PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
47 #endif
48
49 namespace google {
50 namespace protobuf {
51 namespace python {
52
53 namespace message_factory {
54
55 PyMessageFactory* NewMessageFactory(PyTypeObject* type, PyDescriptorPool* pool) {
56 PyMessageFactory* factory = reinterpret_cast<PyMessageFactory*>(
57 PyType_GenericAlloc(type, 0));
58 if (factory == NULL) {
59 return NULL;
60 }
61
62 DynamicMessageFactory* message_factory = new DynamicMessageFactory();
63 // This option might be the default some day.
64 message_factory->SetDelegateToGeneratedFactory(true);
65 factory->message_factory = message_factory;
66
67 factory->pool = pool;
68 // TODO(amauryfa): When the MessageFactory is not created from the
69 // DescriptorPool this reference should be owned, not borrowed.
70 // Py_INCREF(pool);
71
72 factory->classes_by_descriptor = new PyMessageFactory::ClassesByMessageMap();
73
74 return factory;
75 }
76
77 PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
78 static char* kwlist[] = {"pool", 0};
79 PyObject* pool = NULL;
80 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &pool)) {
81 return NULL;
82 }
83 ScopedPyObjectPtr owned_pool;
84 if (pool == NULL || pool == Py_None) {
85 owned_pool.reset(PyObject_CallFunction(
86 reinterpret_cast<PyObject*>(&PyDescriptorPool_Type), NULL));
87 if (owned_pool == NULL) {
88 return NULL;
89 }
90 pool = owned_pool.get();
91 } else {
92 if (!PyObject_TypeCheck(pool, &PyDescriptorPool_Type)) {
93 PyErr_Format(PyExc_TypeError, "Expected a DescriptorPool, got %s",
94 pool->ob_type->tp_name);
95 return NULL;
96 }
97 }
98
99 return reinterpret_cast<PyObject*>(
100 NewMessageFactory(type, reinterpret_cast<PyDescriptorPool*>(pool)));
101 }
102
103 static void Dealloc(PyMessageFactory* self) {
104 // TODO(amauryfa): When the MessageFactory is not created from the
105 // DescriptorPool this reference should be owned, not borrowed.
106 // Py_CLEAR(self->pool);
107 typedef PyMessageFactory::ClassesByMessageMap::iterator iterator;
108 for (iterator it = self->classes_by_descriptor->begin();
109 it != self->classes_by_descriptor->end(); ++it) {
110 Py_DECREF(it->second);
111 }
112 delete self->classes_by_descriptor;
113 delete self->message_factory;
114 Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
115 }
116
117 // Add a message class to our database.
118 int RegisterMessageClass(PyMessageFactory* self,
119 const Descriptor* message_descriptor,
120 CMessageClass* message_class) {
121 Py_INCREF(message_class);
122 typedef PyMessageFactory::ClassesByMessageMap::iterator iterator;
123 std::pair<iterator, bool> ret = self->classes_by_descriptor->insert(
124 std::make_pair(message_descriptor, message_class));
125 if (!ret.second) {
126 // Update case: DECREF the previous value.
127 Py_DECREF(ret.first->second);
128 ret.first->second = message_class;
129 }
130 return 0;
131 }
132
133 CMessageClass* GetOrCreateMessageClass(PyMessageFactory* self,
134 const Descriptor* descriptor) {
135 // This is the same implementation as MessageFactory.GetPrototype().
136 ScopedPyObjectPtr py_descriptor(
137 PyMessageDescriptor_FromDescriptor(descriptor));
138 if (py_descriptor == NULL) {
139 return NULL;
140 }
141 // Do not create a MessageClass that already exists.
142 hash_map<const Descriptor*, CMessageClass*>::iterator it =
143 self->classes_by_descriptor->find(descriptor);
144 if (it != self->classes_by_descriptor->end()) {
145 Py_INCREF(it->second);
146 return it->second;
147 }
148 // Create a new message class.
149 ScopedPyObjectPtr args(Py_BuildValue(
150 "s(){sOsOsO}", descriptor->name().c_str(),
151 "DESCRIPTOR", py_descriptor.get(),
152 "__module__", Py_None,
153 "message_factory", self));
154 if (args == NULL) {
155 return NULL;
156 }
157 ScopedPyObjectPtr message_class(PyObject_CallObject(
158 reinterpret_cast<PyObject*>(&CMessageClass_Type), args.get()));
159 if (message_class == NULL) {
160 return NULL;
161 }
162 // Create messages class for the messages used by the fields, and registers
163 // all extensions for these messages during the recursion.
164 for (int field_idx = 0; field_idx < descriptor->field_count(); field_idx++) {
165 const Descriptor* sub_descriptor =
166 descriptor->field(field_idx)->message_type();
167 // It is NULL if the field type is not a message.
168 if (sub_descriptor != NULL) {
169 CMessageClass* result = GetOrCreateMessageClass(self, sub_descriptor);
170 if (result == NULL) {
171 return NULL;
172 }
173 Py_DECREF(result);
174 }
175 }
176
177 // Register extensions defined in this message.
178 for (int ext_idx = 0 ; ext_idx < descriptor->extension_count() ; ext_idx++) {
179 const FieldDescriptor* extension = descriptor->extension(ext_idx);
180 ScopedPyObjectPtr py_extended_class(
181 GetOrCreateMessageClass(self, extension->containing_type())
182 ->AsPyObject());
183 if (py_extended_class == NULL) {
184 return NULL;
185 }
186 ScopedPyObjectPtr py_extension(PyFieldDescriptor_FromDescriptor(extension));
187 if (py_extension == NULL) {
188 return NULL;
189 }
190 ScopedPyObjectPtr result(cmessage::RegisterExtension(
191 py_extended_class.get(), py_extension.get()));
192 if (result == NULL) {
193 return NULL;
194 }
195 }
196 return reinterpret_cast<CMessageClass*>(message_class.release());
197 }
198
199 // Retrieve the message class added to our database.
200 CMessageClass* GetMessageClass(PyMessageFactory* self,
201 const Descriptor* message_descriptor) {
202 typedef PyMessageFactory::ClassesByMessageMap::iterator iterator;
203 iterator ret = self->classes_by_descriptor->find(message_descriptor);
204 if (ret == self->classes_by_descriptor->end()) {
205 PyErr_Format(PyExc_TypeError, "No message class registered for '%s'",
206 message_descriptor->full_name().c_str());
207 return NULL;
208 } else {
209 return ret->second;
210 }
211 }
212
213 static PyMethodDef Methods[] = {
214 {NULL}};
215
216 static PyObject* GetPool(PyMessageFactory* self, void* closure) {
217 Py_INCREF(self->pool);
218 return reinterpret_cast<PyObject*>(self->pool);
219 }
220
221 static PyGetSetDef Getters[] = {
222 {"pool", (getter)GetPool, NULL, "DescriptorPool"},
223 {NULL}
224 };
225
226 } // namespace message_factory
227
228 PyTypeObject PyMessageFactory_Type = {
229 PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
230 ".MessageFactory", // tp_name
231 sizeof(PyMessageFactory), // tp_basicsize
232 0, // tp_itemsize
233 (destructor)message_factory::Dealloc, // tp_dealloc
234 0, // tp_print
235 0, // tp_getattr
236 0, // tp_setattr
237 0, // tp_compare
238 0, // tp_repr
239 0, // tp_as_number
240 0, // tp_as_sequence
241 0, // tp_as_mapping
242 0, // tp_hash
243 0, // tp_call
244 0, // tp_str
245 0, // tp_getattro
246 0, // tp_setattro
247 0, // tp_as_buffer
248 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags
249 "A static Message Factory", // tp_doc
250 0, // tp_traverse
251 0, // tp_clear
252 0, // tp_richcompare
253 0, // tp_weaklistoffset
254 0, // tp_iter
255 0, // tp_iternext
256 message_factory::Methods, // tp_methods
257 0, // tp_members
258 message_factory::Getters, // tp_getset
259 0, // tp_base
260 0, // tp_dict
261 0, // tp_descr_get
262 0, // tp_descr_set
263 0, // tp_dictoffset
264 0, // tp_init
265 0, // tp_alloc
266 message_factory::New, // tp_new
267 PyObject_Del, // tp_free
268 };
269
270 bool InitMessageFactory() {
271 if (PyType_Ready(&PyMessageFactory_Type) < 0) {
272 return false;
273 }
274
275 return true;
276 }
277
278 } // namespace python
279 } // namespace protobuf
280 } // namespace google
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698