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 // Mappings and Sequences of descriptors.
32 // Used by Descriptor.fields_by_name, EnumDescriptor.values...
33 //
34 // They avoid the allocation of a full dictionary or a full list: they simply
35 // store a pointer to the parent descriptor, use the C++ Descriptor methods (see
36 // google/protobuf/descriptor.h) to retrieve other descriptors, and create
37 // Python objects on the fly.
38 //
39 // The containers fully conform to abc.Mapping and abc.Sequence, and behave just
40 // like read-only dictionaries and lists.
41 //
42 // Because the interface of C++ Descriptors is quite regular, this file actually
43 // defines only three types, the exact behavior of a container is controlled by
44 // a DescriptorContainerDef structure, which contains functions that uses the
45 // public Descriptor API.
46 //
47 // Note: This DescriptorContainerDef is similar to the "virtual methods table"
48 // that a C++ compiler generates for a class. We have to make it explicit
49 // because the Python API is based on C, and does not play well with C++
50 // inheritance.
51
52 #include <Python.h>
53
54 #include <google/protobuf/descriptor.h>
55 #include <google/protobuf/pyext/descriptor_containers.h>
56 #include <google/protobuf/pyext/descriptor_pool.h>
57 #include <google/protobuf/pyext/descriptor.h>
58 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
59
60 #if PY_MAJOR_VERSION >= 3
61 #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
62 #define PyString_FromFormat PyUnicode_FromFormat
63 #define PyInt_FromLong PyLong_FromLong
64 #if PY_VERSION_HEX < 0x03030000
65 #error "Python 3.0 - 3.2 are not supported."
66 #endif
67 #define PyString_AsStringAndSize(ob, charpp, sizep) \
68 (PyUnicode_Check(ob)? \
69 ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
70 PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
71 #endif
72
73 namespace google {
74 namespace protobuf {
75 namespace python {
76
77 struct PyContainer;
78
79 typedef int (*CountMethod)(PyContainer* self);
80 typedef const void* (*GetByIndexMethod)(PyContainer* self, int index);
81 typedef const void* (*GetByNameMethod)(PyContainer* self, const string& name);
82 typedef const void* (*GetByCamelcaseNameMethod)(PyContainer* self,
83 const string& name);
84 typedef const void* (*GetByNumberMethod)(PyContainer* self, int index);
85 typedef PyObject* (*NewObjectFromItemMethod)(const void* descriptor);
86 typedef const string& (*GetItemNameMethod)(const void* descriptor);
87 typedef const string& (*GetItemCamelcaseNameMethod)(const void* descriptor);
88 typedef int (*GetItemNumberMethod)(const void* descriptor);
89 typedef int (*GetItemIndexMethod)(const void* descriptor);
90
91 struct DescriptorContainerDef {
92 const char* mapping_name;
93 // Returns the number of items in the container.
94 CountMethod count_fn;
95 // Retrieve item by index (usually the order of declaration in the proto file)
96 // Used by sequences, but also iterators. 0 <= index < Count().
97 GetByIndexMethod get_by_index_fn;
98 // Retrieve item by name (usually a call to some 'FindByName' method).
99 // Used by "by_name" mappings.
100 GetByNameMethod get_by_name_fn;
101 // Retrieve item by camelcase name (usually a call to some
102 // 'FindByCamelcaseName' method). Used by "by_camelcase_name" mappings.
103 GetByCamelcaseNameMethod get_by_camelcase_name_fn;
104 // Retrieve item by declared number (field tag, or enum value).
105 // Used by "by_number" mappings.
106 GetByNumberMethod get_by_number_fn;
107 // Converts a item C++ descriptor to a Python object. Returns a new reference.
108 NewObjectFromItemMethod new_object_from_item_fn;
109 // Retrieve the name of an item. Used by iterators on "by_name" mappings.
110 GetItemNameMethod get_item_name_fn;
111 // Retrieve the camelcase name of an item. Used by iterators on
112 // "by_camelcase_name" mappings.
113 GetItemCamelcaseNameMethod get_item_camelcase_name_fn;
114 // Retrieve the number of an item. Used by iterators on "by_number" mappings.
115 GetItemNumberMethod get_item_number_fn;
116 // Retrieve the index of an item for the container type.
117 // Used by "__contains__".
118 // If not set, "x in sequence" will do a linear search.
119 GetItemIndexMethod get_item_index_fn;
120 };
121
122 struct PyContainer {
123 PyObject_HEAD
124
125 // The proto2 descriptor this container belongs to the global DescriptorPool.
126 const void* descriptor;
127
128 // A pointer to a static structure with function pointers that control the
129 // behavior of the container. Very similar to the table of virtual functions
130 // of a C++ class.
131 const DescriptorContainerDef* container_def;
132
133 // The kind of container: list, or dict by name or value.
134 enum ContainerKind {
135 KIND_SEQUENCE,
136 KIND_BYNAME,
137 KIND_BYCAMELCASENAME,
138 KIND_BYNUMBER,
139 } kind;
140 };
141
142 struct PyContainerIterator {
143 PyObject_HEAD
144
145 // The container we are iterating over. Own a reference.
146 PyContainer* container;
147
148 // The current index in the iterator.
149 int index;
150
151 // The kind of container: list, or dict by name or value.
152 enum IterKind {
153 KIND_ITERKEY,
154 KIND_ITERVALUE,
155 KIND_ITERITEM,
156 KIND_ITERVALUE_REVERSED, // For sequences
157 } kind;
158 };
159
160 namespace descriptor {
161
162 // Returns the C++ item descriptor for a given Python key.
163 // When the descriptor is found, return true and set *item.
164 // When the descriptor is not found, return true, but set *item to NULL.
165 // On error, returns false with an exception set.
_GetItemByKey(PyContainer * self,PyObject * key,const void ** item)166 static bool _GetItemByKey(PyContainer* self, PyObject* key, const void** item) {
167 switch (self->kind) {
168 case PyContainer::KIND_BYNAME:
169 {
170 char* name;
171 Py_ssize_t name_size;
172 if (PyString_AsStringAndSize(key, &name, &name_size) < 0) {
173 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
174 // Not a string, cannot be in the container.
175 PyErr_Clear();
176 *item = NULL;
177 return true;
178 }
179 return false;
180 }
181 *item = self->container_def->get_by_name_fn(
182 self, string(name, name_size));
183 return true;
184 }
185 case PyContainer::KIND_BYCAMELCASENAME:
186 {
187 char* camelcase_name;
188 Py_ssize_t name_size;
189 if (PyString_AsStringAndSize(key, &camelcase_name, &name_size) < 0) {
190 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
191 // Not a string, cannot be in the container.
192 PyErr_Clear();
193 *item = NULL;
194 return true;
195 }
196 return false;
197 }
198 *item = self->container_def->get_by_camelcase_name_fn(
199 self, string(camelcase_name, name_size));
200 return true;
201 }
202 case PyContainer::KIND_BYNUMBER:
203 {
204 Py_ssize_t number = PyNumber_AsSsize_t(key, NULL);
205 if (number == -1 && PyErr_Occurred()) {
206 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
207 // Not a number, cannot be in the container.
208 PyErr_Clear();
209 *item = NULL;
210 return true;
211 }
212 return false;
213 }
214 *item = self->container_def->get_by_number_fn(self, number);
215 return true;
216 }
217 default:
218 PyErr_SetNone(PyExc_NotImplementedError);
219 return false;
220 }
221 }
222
223 // Returns the key of the object at the given index.
224 // Used when iterating over mappings.
_NewKey_ByIndex(PyContainer * self,Py_ssize_t index)225 static PyObject* _NewKey_ByIndex(PyContainer* self, Py_ssize_t index) {
226 const void* item = self->container_def->get_by_index_fn(self, index);
227 switch (self->kind) {
228 case PyContainer::KIND_BYNAME:
229 {
230 const string& name(self->container_def->get_item_name_fn(item));
231 return PyString_FromStringAndSize(name.c_str(), name.size());
232 }
233 case PyContainer::KIND_BYCAMELCASENAME:
234 {
235 const string& name(
236 self->container_def->get_item_camelcase_name_fn(item));
237 return PyString_FromStringAndSize(name.c_str(), name.size());
238 }
239 case PyContainer::KIND_BYNUMBER:
240 {
241 int value = self->container_def->get_item_number_fn(item);
242 return PyInt_FromLong(value);
243 }
244 default:
245 PyErr_SetNone(PyExc_NotImplementedError);
246 return NULL;
247 }
248 }
249
250 // Returns the object at the given index.
251 // Also used when iterating over mappings.
_NewObj_ByIndex(PyContainer * self,Py_ssize_t index)252 static PyObject* _NewObj_ByIndex(PyContainer* self, Py_ssize_t index) {
253 return self->container_def->new_object_from_item_fn(
254 self->container_def->get_by_index_fn(self, index));
255 }
256
Length(PyContainer * self)257 static Py_ssize_t Length(PyContainer* self) {
258 return self->container_def->count_fn(self);
259 }
260
261 // The DescriptorMapping type.
262
Subscript(PyContainer * self,PyObject * key)263 static PyObject* Subscript(PyContainer* self, PyObject* key) {
264 const void* item = NULL;
265 if (!_GetItemByKey(self, key, &item)) {
266 return NULL;
267 }
268 if (!item) {
269 PyErr_SetObject(PyExc_KeyError, key);
270 return NULL;
271 }
272 return self->container_def->new_object_from_item_fn(item);
273 }
274
AssSubscript(PyContainer * self,PyObject * key,PyObject * value)275 static int AssSubscript(PyContainer* self, PyObject* key, PyObject* value) {
276 if (_CalledFromGeneratedFile(0)) {
277 return 0;
278 }
279 PyErr_Format(PyExc_TypeError,
280 "'%.200s' object does not support item assignment",
281 Py_TYPE(self)->tp_name);
282 return -1;
283 }
284
285 static PyMappingMethods MappingMappingMethods = {
286 (lenfunc)Length, // mp_length
287 (binaryfunc)Subscript, // mp_subscript
288 (objobjargproc)AssSubscript, // mp_ass_subscript
289 };
290
Contains(PyContainer * self,PyObject * key)291 static int Contains(PyContainer* self, PyObject* key) {
292 const void* item = NULL;
293 if (!_GetItemByKey(self, key, &item)) {
294 return -1;
295 }
296 if (item) {
297 return 1;
298 } else {
299 return 0;
300 }
301 }
302
ContainerRepr(PyContainer * self)303 static PyObject* ContainerRepr(PyContainer* self) {
304 const char* kind = "";
305 switch (self->kind) {
306 case PyContainer::KIND_SEQUENCE:
307 kind = "sequence";
308 break;
309 case PyContainer::KIND_BYNAME:
310 kind = "mapping by name";
311 break;
312 case PyContainer::KIND_BYCAMELCASENAME:
313 kind = "mapping by camelCase name";
314 break;
315 case PyContainer::KIND_BYNUMBER:
316 kind = "mapping by number";
317 break;
318 }
319 return PyString_FromFormat(
320 "<%s %s>", self->container_def->mapping_name, kind);
321 }
322
323 extern PyTypeObject DescriptorMapping_Type;
324 extern PyTypeObject DescriptorSequence_Type;
325
326 // A sequence container can only be equal to another sequence container, or (for
327 // backward compatibility) to a list containing the same items.
328 // Returns 1 if equal, 0 if unequal, -1 on error.
DescriptorSequence_Equal(PyContainer * self,PyObject * other)329 static int DescriptorSequence_Equal(PyContainer* self, PyObject* other) {
330 // Check the identity of C++ pointers.
331 if (PyObject_TypeCheck(other, &DescriptorSequence_Type)) {
332 PyContainer* other_container = reinterpret_cast<PyContainer*>(other);
333 if (self->descriptor == other_container->descriptor &&
334 self->container_def == other_container->container_def &&
335 self->kind == other_container->kind) {
336 return 1;
337 } else {
338 return 0;
339 }
340 }
341
342 // If other is a list
343 if (PyList_Check(other)) {
344 // return list(self) == other
345 int size = Length(self);
346 if (size != PyList_Size(other)) {
347 return false;
348 }
349 for (int index = 0; index < size; index++) {
350 ScopedPyObjectPtr value1(_NewObj_ByIndex(self, index));
351 if (value1 == NULL) {
352 return -1;
353 }
354 PyObject* value2 = PyList_GetItem(other, index);
355 if (value2 == NULL) {
356 return -1;
357 }
358 int cmp = PyObject_RichCompareBool(value1.get(), value2, Py_EQ);
359 if (cmp != 1) // error or not equal
360 return cmp;
361 }
362 // All items were found and equal
363 return 1;
364 }
365
366 // Any other object is different.
367 return 0;
368 }
369
370 // A mapping container can only be equal to another mapping container, or (for
371 // backward compatibility) to a dict containing the same items.
372 // Returns 1 if equal, 0 if unequal, -1 on error.
DescriptorMapping_Equal(PyContainer * self,PyObject * other)373 static int DescriptorMapping_Equal(PyContainer* self, PyObject* other) {
374 // Check the identity of C++ pointers.
375 if (PyObject_TypeCheck(other, &DescriptorMapping_Type)) {
376 PyContainer* other_container = reinterpret_cast<PyContainer*>(other);
377 if (self->descriptor == other_container->descriptor &&
378 self->container_def == other_container->container_def &&
379 self->kind == other_container->kind) {
380 return 1;
381 } else {
382 return 0;
383 }
384 }
385
386 // If other is a dict
387 if (PyDict_Check(other)) {
388 // equivalent to dict(self.items()) == other
389 int size = Length(self);
390 if (size != PyDict_Size(other)) {
391 return false;
392 }
393 for (int index = 0; index < size; index++) {
394 ScopedPyObjectPtr key(_NewKey_ByIndex(self, index));
395 if (key == NULL) {
396 return -1;
397 }
398 ScopedPyObjectPtr value1(_NewObj_ByIndex(self, index));
399 if (value1 == NULL) {
400 return -1;
401 }
402 PyObject* value2 = PyDict_GetItem(other, key.get());
403 if (value2 == NULL) {
404 // Not found in the other dictionary
405 return 0;
406 }
407 int cmp = PyObject_RichCompareBool(value1.get(), value2, Py_EQ);
408 if (cmp != 1) // error or not equal
409 return cmp;
410 }
411 // All items were found and equal
412 return 1;
413 }
414
415 // Any other object is different.
416 return 0;
417 }
418
RichCompare(PyContainer * self,PyObject * other,int opid)419 static PyObject* RichCompare(PyContainer* self, PyObject* other, int opid) {
420 if (opid != Py_EQ && opid != Py_NE) {
421 Py_INCREF(Py_NotImplemented);
422 return Py_NotImplemented;
423 }
424
425 int result;
426
427 if (self->kind == PyContainer::KIND_SEQUENCE) {
428 result = DescriptorSequence_Equal(self, other);
429 } else {
430 result = DescriptorMapping_Equal(self, other);
431 }
432 if (result < 0) {
433 return NULL;
434 }
435 if (result ^ (opid == Py_NE)) {
436 Py_RETURN_TRUE;
437 } else {
438 Py_RETURN_FALSE;
439 }
440 }
441
442 static PySequenceMethods MappingSequenceMethods = {
443 0, // sq_length
444 0, // sq_concat
445 0, // sq_repeat
446 0, // sq_item
447 0, // sq_slice
448 0, // sq_ass_item
449 0, // sq_ass_slice
450 (objobjproc)Contains, // sq_contains
451 };
452
Get(PyContainer * self,PyObject * args)453 static PyObject* Get(PyContainer* self, PyObject* args) {
454 PyObject* key;
455 PyObject* default_value = Py_None;
456 if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &default_value)) {
457 return NULL;
458 }
459
460 const void* item;
461 if (!_GetItemByKey(self, key, &item)) {
462 return NULL;
463 }
464 if (item == NULL) {
465 Py_INCREF(default_value);
466 return default_value;
467 }
468 return self->container_def->new_object_from_item_fn(item);
469 }
470
Keys(PyContainer * self,PyObject * args)471 static PyObject* Keys(PyContainer* self, PyObject* args) {
472 Py_ssize_t count = Length(self);
473 ScopedPyObjectPtr list(PyList_New(count));
474 if (list == NULL) {
475 return NULL;
476 }
477 for (Py_ssize_t index = 0; index < count; ++index) {
478 PyObject* key = _NewKey_ByIndex(self, index);
479 if (key == NULL) {
480 return NULL;
481 }
482 PyList_SET_ITEM(list.get(), index, key);
483 }
484 return list.release();
485 }
486
Values(PyContainer * self,PyObject * args)487 static PyObject* Values(PyContainer* self, PyObject* args) {
488 Py_ssize_t count = Length(self);
489 ScopedPyObjectPtr list(PyList_New(count));
490 if (list == NULL) {
491 return NULL;
492 }
493 for (Py_ssize_t index = 0; index < count; ++index) {
494 PyObject* value = _NewObj_ByIndex(self, index);
495 if (value == NULL) {
496 return NULL;
497 }
498 PyList_SET_ITEM(list.get(), index, value);
499 }
500 return list.release();
501 }
502
Items(PyContainer * self,PyObject * args)503 static PyObject* Items(PyContainer* self, PyObject* args) {
504 Py_ssize_t count = Length(self);
505 ScopedPyObjectPtr list(PyList_New(count));
506 if (list == NULL) {
507 return NULL;
508 }
509 for (Py_ssize_t index = 0; index < count; ++index) {
510 ScopedPyObjectPtr obj(PyTuple_New(2));
511 if (obj == NULL) {
512 return NULL;
513 }
514 PyObject* key = _NewKey_ByIndex(self, index);
515 if (key == NULL) {
516 return NULL;
517 }
518 PyTuple_SET_ITEM(obj.get(), 0, key);
519 PyObject* value = _NewObj_ByIndex(self, index);
520 if (value == NULL) {
521 return NULL;
522 }
523 PyTuple_SET_ITEM(obj.get(), 1, value);
524 PyList_SET_ITEM(list.get(), index, obj.release());
525 }
526 return list.release();
527 }
528
529 static PyObject* NewContainerIterator(PyContainer* mapping,
530 PyContainerIterator::IterKind kind);
531
Iter(PyContainer * self)532 static PyObject* Iter(PyContainer* self) {
533 return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY);
534 }
IterKeys(PyContainer * self,PyObject * args)535 static PyObject* IterKeys(PyContainer* self, PyObject* args) {
536 return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY);
537 }
IterValues(PyContainer * self,PyObject * args)538 static PyObject* IterValues(PyContainer* self, PyObject* args) {
539 return NewContainerIterator(self, PyContainerIterator::KIND_ITERVALUE);
540 }
IterItems(PyContainer * self,PyObject * args)541 static PyObject* IterItems(PyContainer* self, PyObject* args) {
542 return NewContainerIterator(self, PyContainerIterator::KIND_ITERITEM);
543 }
544
545 static PyMethodDef MappingMethods[] = {
546 { "get", (PyCFunction)Get, METH_VARARGS, },
547 { "keys", (PyCFunction)Keys, METH_NOARGS, },
548 { "values", (PyCFunction)Values, METH_NOARGS, },
549 { "items", (PyCFunction)Items, METH_NOARGS, },
550 { "iterkeys", (PyCFunction)IterKeys, METH_NOARGS, },
551 { "itervalues", (PyCFunction)IterValues, METH_NOARGS, },
552 { "iteritems", (PyCFunction)IterItems, METH_NOARGS, },
553 {NULL}
554 };
555
556 PyTypeObject DescriptorMapping_Type = {
557 PyVarObject_HEAD_INIT(&PyType_Type, 0)
558 "DescriptorMapping", // tp_name
559 sizeof(PyContainer), // tp_basicsize
560 0, // tp_itemsize
561 0, // tp_dealloc
562 0, // tp_print
563 0, // tp_getattr
564 0, // tp_setattr
565 0, // tp_compare
566 (reprfunc)ContainerRepr, // tp_repr
567 0, // tp_as_number
568 &MappingSequenceMethods, // tp_as_sequence
569 &MappingMappingMethods, // tp_as_mapping
570 0, // tp_hash
571 0, // tp_call
572 0, // tp_str
573 0, // tp_getattro
574 0, // tp_setattro
575 0, // tp_as_buffer
576 Py_TPFLAGS_DEFAULT, // tp_flags
577 0, // tp_doc
578 0, // tp_traverse
579 0, // tp_clear
580 (richcmpfunc)RichCompare, // tp_richcompare
581 0, // tp_weaklistoffset
582 (getiterfunc)Iter, // tp_iter
583 0, // tp_iternext
584 MappingMethods, // tp_methods
585 0, // tp_members
586 0, // tp_getset
587 0, // tp_base
588 0, // tp_dict
589 0, // tp_descr_get
590 0, // tp_descr_set
591 0, // tp_dictoffset
592 0, // tp_init
593 0, // tp_alloc
594 0, // tp_new
595 0, // tp_free
596 };
597
598 // The DescriptorSequence type.
599
GetItem(PyContainer * self,Py_ssize_t index)600 static PyObject* GetItem(PyContainer* self, Py_ssize_t index) {
601 if (index < 0) {
602 index += Length(self);
603 }
604 if (index < 0 || index >= Length(self)) {
605 PyErr_SetString(PyExc_IndexError, "index out of range");
606 return NULL;
607 }
608 return _NewObj_ByIndex(self, index);
609 }
610
611 static PyObject *
SeqSubscript(PyContainer * self,PyObject * item)612 SeqSubscript(PyContainer* self, PyObject* item) {
613 if (PyIndex_Check(item)) {
614 Py_ssize_t index;
615 index = PyNumber_AsSsize_t(item, PyExc_IndexError);
616 if (index == -1 && PyErr_Occurred())
617 return NULL;
618 return GetItem(self, index);
619 }
620 // Materialize the list and delegate the operation to it.
621 ScopedPyObjectPtr list(PyObject_CallFunctionObjArgs(
622 reinterpret_cast<PyObject*>(&PyList_Type), self, NULL));
623 if (list == NULL) {
624 return NULL;
625 }
626 return Py_TYPE(list.get())->tp_as_mapping->mp_subscript(list.get(), item);
627 }
628
629 // Returns the position of the item in the sequence, of -1 if not found.
630 // This function never fails.
Find(PyContainer * self,PyObject * item)631 int Find(PyContainer* self, PyObject* item) {
632 // The item can only be in one position: item.index.
633 // Check that self[item.index] == item, it's faster than a linear search.
634 //
635 // This assumes that sequences are only defined by syntax of the .proto file:
636 // a specific item belongs to only one sequence, depending on its position in
637 // the .proto file definition.
638 const void* descriptor_ptr = PyDescriptor_AsVoidPtr(item);
639 if (descriptor_ptr == NULL) {
640 // Not a descriptor, it cannot be in the list.
641 return -1;
642 }
643 if (self->container_def->get_item_index_fn) {
644 int index = self->container_def->get_item_index_fn(descriptor_ptr);
645 if (index < 0 || index >= Length(self)) {
646 // This index is not from this collection.
647 return -1;
648 }
649 if (self->container_def->get_by_index_fn(self, index) != descriptor_ptr) {
650 // The descriptor at this index is not the same.
651 return -1;
652 }
653 // self[item.index] == item, so return the index.
654 return index;
655 } else {
656 // Fall back to linear search.
657 int length = Length(self);
658 for (int index=0; index < length; index++) {
659 if (self->container_def->get_by_index_fn(self, index) == descriptor_ptr) {
660 return index;
661 }
662 }
663 // Not found
664 return -1;
665 }
666 }
667
668 // Implements list.index(): the position of the item is in the sequence.
Index(PyContainer * self,PyObject * item)669 static PyObject* Index(PyContainer* self, PyObject* item) {
670 int position = Find(self, item);
671 if (position < 0) {
672 // Not found
673 PyErr_SetNone(PyExc_ValueError);
674 return NULL;
675 } else {
676 return PyInt_FromLong(position);
677 }
678 }
679 // Implements "list.__contains__()": is the object in the sequence.
SeqContains(PyContainer * self,PyObject * item)680 static int SeqContains(PyContainer* self, PyObject* item) {
681 int position = Find(self, item);
682 if (position < 0) {
683 return 0;
684 } else {
685 return 1;
686 }
687 }
688
689 // Implements list.count(): number of occurrences of the item in the sequence.
690 // An item can only appear once in a sequence. If it exists, return 1.
Count(PyContainer * self,PyObject * item)691 static PyObject* Count(PyContainer* self, PyObject* item) {
692 int position = Find(self, item);
693 if (position < 0) {
694 return PyInt_FromLong(0);
695 } else {
696 return PyInt_FromLong(1);
697 }
698 }
699
Append(PyContainer * self,PyObject * args)700 static PyObject* Append(PyContainer* self, PyObject* args) {
701 if (_CalledFromGeneratedFile(0)) {
702 Py_RETURN_NONE;
703 }
704 PyErr_Format(PyExc_TypeError,
705 "'%.200s' object is not a mutable sequence",
706 Py_TYPE(self)->tp_name);
707 return NULL;
708 }
709
Reversed(PyContainer * self,PyObject * args)710 static PyObject* Reversed(PyContainer* self, PyObject* args) {
711 return NewContainerIterator(self,
712 PyContainerIterator::KIND_ITERVALUE_REVERSED);
713 }
714
715 static PyMethodDef SeqMethods[] = {
716 { "index", (PyCFunction)Index, METH_O, },
717 { "count", (PyCFunction)Count, METH_O, },
718 { "append", (PyCFunction)Append, METH_O, },
719 { "__reversed__", (PyCFunction)Reversed, METH_NOARGS, },
720 {NULL}
721 };
722
723 static PySequenceMethods SeqSequenceMethods = {
724 (lenfunc)Length, // sq_length
725 0, // sq_concat
726 0, // sq_repeat
727 (ssizeargfunc)GetItem, // sq_item
728 0, // sq_slice
729 0, // sq_ass_item
730 0, // sq_ass_slice
731 (objobjproc)SeqContains, // sq_contains
732 };
733
734 static PyMappingMethods SeqMappingMethods = {
735 (lenfunc)Length, // mp_length
736 (binaryfunc)SeqSubscript, // mp_subscript
737 0, // mp_ass_subscript
738 };
739
740 PyTypeObject DescriptorSequence_Type = {
741 PyVarObject_HEAD_INIT(&PyType_Type, 0)
742 "DescriptorSequence", // tp_name
743 sizeof(PyContainer), // tp_basicsize
744 0, // tp_itemsize
745 0, // tp_dealloc
746 0, // tp_print
747 0, // tp_getattr
748 0, // tp_setattr
749 0, // tp_compare
750 (reprfunc)ContainerRepr, // tp_repr
751 0, // tp_as_number
752 &SeqSequenceMethods, // tp_as_sequence
753 &SeqMappingMethods, // tp_as_mapping
754 0, // tp_hash
755 0, // tp_call
756 0, // tp_str
757 0, // tp_getattro
758 0, // tp_setattro
759 0, // tp_as_buffer
760 Py_TPFLAGS_DEFAULT, // tp_flags
761 0, // tp_doc
762 0, // tp_traverse
763 0, // tp_clear
764 (richcmpfunc)RichCompare, // tp_richcompare
765 0, // tp_weaklistoffset
766 0, // tp_iter
767 0, // tp_iternext
768 SeqMethods, // tp_methods
769 0, // tp_members
770 0, // tp_getset
771 0, // tp_base
772 0, // tp_dict
773 0, // tp_descr_get
774 0, // tp_descr_set
775 0, // tp_dictoffset
776 0, // tp_init
777 0, // tp_alloc
778 0, // tp_new
779 0, // tp_free
780 };
781
NewMappingByName(DescriptorContainerDef * container_def,const void * descriptor)782 static PyObject* NewMappingByName(
783 DescriptorContainerDef* container_def, const void* descriptor) {
784 PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
785 if (self == NULL) {
786 return NULL;
787 }
788 self->descriptor = descriptor;
789 self->container_def = container_def;
790 self->kind = PyContainer::KIND_BYNAME;
791 return reinterpret_cast<PyObject*>(self);
792 }
793
NewMappingByCamelcaseName(DescriptorContainerDef * container_def,const void * descriptor)794 static PyObject* NewMappingByCamelcaseName(
795 DescriptorContainerDef* container_def, const void* descriptor) {
796 PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
797 if (self == NULL) {
798 return NULL;
799 }
800 self->descriptor = descriptor;
801 self->container_def = container_def;
802 self->kind = PyContainer::KIND_BYCAMELCASENAME;
803 return reinterpret_cast<PyObject*>(self);
804 }
805
NewMappingByNumber(DescriptorContainerDef * container_def,const void * descriptor)806 static PyObject* NewMappingByNumber(
807 DescriptorContainerDef* container_def, const void* descriptor) {
808 if (container_def->get_by_number_fn == NULL ||
809 container_def->get_item_number_fn == NULL) {
810 PyErr_SetNone(PyExc_NotImplementedError);
811 return NULL;
812 }
813 PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
814 if (self == NULL) {
815 return NULL;
816 }
817 self->descriptor = descriptor;
818 self->container_def = container_def;
819 self->kind = PyContainer::KIND_BYNUMBER;
820 return reinterpret_cast<PyObject*>(self);
821 }
822
NewSequence(DescriptorContainerDef * container_def,const void * descriptor)823 static PyObject* NewSequence(
824 DescriptorContainerDef* container_def, const void* descriptor) {
825 PyContainer* self = PyObject_New(PyContainer, &DescriptorSequence_Type);
826 if (self == NULL) {
827 return NULL;
828 }
829 self->descriptor = descriptor;
830 self->container_def = container_def;
831 self->kind = PyContainer::KIND_SEQUENCE;
832 return reinterpret_cast<PyObject*>(self);
833 }
834
835 // Implement iterators over PyContainers.
836
Iterator_Dealloc(PyContainerIterator * self)837 static void Iterator_Dealloc(PyContainerIterator* self) {
838 Py_CLEAR(self->container);
839 Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
840 }
841
Iterator_Next(PyContainerIterator * self)842 static PyObject* Iterator_Next(PyContainerIterator* self) {
843 int count = self->container->container_def->count_fn(self->container);
844 if (self->index >= count) {
845 // Return NULL with no exception to indicate the end.
846 return NULL;
847 }
848 int index = self->index;
849 self->index += 1;
850 switch (self->kind) {
851 case PyContainerIterator::KIND_ITERKEY:
852 return _NewKey_ByIndex(self->container, index);
853 case PyContainerIterator::KIND_ITERVALUE:
854 return _NewObj_ByIndex(self->container, index);
855 case PyContainerIterator::KIND_ITERVALUE_REVERSED:
856 return _NewObj_ByIndex(self->container, count - index - 1);
857 case PyContainerIterator::KIND_ITERITEM:
858 {
859 PyObject* obj = PyTuple_New(2);
860 if (obj == NULL) {
861 return NULL;
862 }
863 PyObject* key = _NewKey_ByIndex(self->container, index);
864 if (key == NULL) {
865 Py_DECREF(obj);
866 return NULL;
867 }
868 PyTuple_SET_ITEM(obj, 0, key);
869 PyObject* value = _NewObj_ByIndex(self->container, index);
870 if (value == NULL) {
871 Py_DECREF(obj);
872 return NULL;
873 }
874 PyTuple_SET_ITEM(obj, 1, value);
875 return obj;
876 }
877 default:
878 PyErr_SetNone(PyExc_NotImplementedError);
879 return NULL;
880 }
881 }
882
883 static PyTypeObject ContainerIterator_Type = {
884 PyVarObject_HEAD_INIT(&PyType_Type, 0)
885 "DescriptorContainerIterator", // tp_name
886 sizeof(PyContainerIterator), // tp_basicsize
887 0, // tp_itemsize
888 (destructor)Iterator_Dealloc, // tp_dealloc
889 0, // tp_print
890 0, // tp_getattr
891 0, // tp_setattr
892 0, // tp_compare
893 0, // tp_repr
894 0, // tp_as_number
895 0, // tp_as_sequence
896 0, // tp_as_mapping
897 0, // tp_hash
898 0, // tp_call
899 0, // tp_str
900 0, // tp_getattro
901 0, // tp_setattro
902 0, // tp_as_buffer
903 Py_TPFLAGS_DEFAULT, // tp_flags
904 0, // tp_doc
905 0, // tp_traverse
906 0, // tp_clear
907 0, // tp_richcompare
908 0, // tp_weaklistoffset
909 PyObject_SelfIter, // tp_iter
910 (iternextfunc)Iterator_Next, // tp_iternext
911 0, // tp_methods
912 0, // tp_members
913 0, // tp_getset
914 0, // tp_base
915 0, // tp_dict
916 0, // tp_descr_get
917 0, // tp_descr_set
918 0, // tp_dictoffset
919 0, // tp_init
920 0, // tp_alloc
921 0, // tp_new
922 0, // tp_free
923 };
924
NewContainerIterator(PyContainer * container,PyContainerIterator::IterKind kind)925 static PyObject* NewContainerIterator(PyContainer* container,
926 PyContainerIterator::IterKind kind) {
927 PyContainerIterator* self = PyObject_New(PyContainerIterator,
928 &ContainerIterator_Type);
929 if (self == NULL) {
930 return NULL;
931 }
932 Py_INCREF(container);
933 self->container = container;
934 self->kind = kind;
935 self->index = 0;
936
937 return reinterpret_cast<PyObject*>(self);
938 }
939
940 } // namespace descriptor
941
942 // Now define the real collections!
943
944 namespace message_descriptor {
945
946 typedef const Descriptor* ParentDescriptor;
947
GetDescriptor(PyContainer * self)948 static ParentDescriptor GetDescriptor(PyContainer* self) {
949 return reinterpret_cast<ParentDescriptor>(self->descriptor);
950 }
951
952 namespace fields {
953
954 typedef const FieldDescriptor* ItemDescriptor;
955
Count(PyContainer * self)956 static int Count(PyContainer* self) {
957 return GetDescriptor(self)->field_count();
958 }
959
GetByName(PyContainer * self,const string & name)960 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
961 return GetDescriptor(self)->FindFieldByName(name);
962 }
963
GetByCamelcaseName(PyContainer * self,const string & name)964 static ItemDescriptor GetByCamelcaseName(PyContainer* self,
965 const string& name) {
966 return GetDescriptor(self)->FindFieldByCamelcaseName(name);
967 }
968
GetByNumber(PyContainer * self,int number)969 static ItemDescriptor GetByNumber(PyContainer* self, int number) {
970 return GetDescriptor(self)->FindFieldByNumber(number);
971 }
972
GetByIndex(PyContainer * self,int index)973 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
974 return GetDescriptor(self)->field(index);
975 }
976
NewObjectFromItem(ItemDescriptor item)977 static PyObject* NewObjectFromItem(ItemDescriptor item) {
978 return PyFieldDescriptor_FromDescriptor(item);
979 }
980
GetItemName(ItemDescriptor item)981 static const string& GetItemName(ItemDescriptor item) {
982 return item->name();
983 }
984
GetItemCamelcaseName(ItemDescriptor item)985 static const string& GetItemCamelcaseName(ItemDescriptor item) {
986 return item->camelcase_name();
987 }
988
GetItemNumber(ItemDescriptor item)989 static int GetItemNumber(ItemDescriptor item) {
990 return item->number();
991 }
992
GetItemIndex(ItemDescriptor item)993 static int GetItemIndex(ItemDescriptor item) {
994 return item->index();
995 }
996
997 static DescriptorContainerDef ContainerDef = {
998 "MessageFields",
999 (CountMethod)Count,
1000 (GetByIndexMethod)GetByIndex,
1001 (GetByNameMethod)GetByName,
1002 (GetByCamelcaseNameMethod)GetByCamelcaseName,
1003 (GetByNumberMethod)GetByNumber,
1004 (NewObjectFromItemMethod)NewObjectFromItem,
1005 (GetItemNameMethod)GetItemName,
1006 (GetItemCamelcaseNameMethod)GetItemCamelcaseName,
1007 (GetItemNumberMethod)GetItemNumber,
1008 (GetItemIndexMethod)GetItemIndex,
1009 };
1010
1011 } // namespace fields
1012
NewMessageFieldsByName(ParentDescriptor descriptor)1013 PyObject* NewMessageFieldsByName(ParentDescriptor descriptor) {
1014 return descriptor::NewMappingByName(&fields::ContainerDef, descriptor);
1015 }
1016
NewMessageFieldsByCamelcaseName(ParentDescriptor descriptor)1017 PyObject* NewMessageFieldsByCamelcaseName(ParentDescriptor descriptor) {
1018 return descriptor::NewMappingByCamelcaseName(&fields::ContainerDef,
1019 descriptor);
1020 }
1021
NewMessageFieldsByNumber(ParentDescriptor descriptor)1022 PyObject* NewMessageFieldsByNumber(ParentDescriptor descriptor) {
1023 return descriptor::NewMappingByNumber(&fields::ContainerDef, descriptor);
1024 }
1025
NewMessageFieldsSeq(ParentDescriptor descriptor)1026 PyObject* NewMessageFieldsSeq(ParentDescriptor descriptor) {
1027 return descriptor::NewSequence(&fields::ContainerDef, descriptor);
1028 }
1029
1030 namespace nested_types {
1031
1032 typedef const Descriptor* ItemDescriptor;
1033
Count(PyContainer * self)1034 static int Count(PyContainer* self) {
1035 return GetDescriptor(self)->nested_type_count();
1036 }
1037
GetByName(PyContainer * self,const string & name)1038 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1039 return GetDescriptor(self)->FindNestedTypeByName(name);
1040 }
1041
GetByIndex(PyContainer * self,int index)1042 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1043 return GetDescriptor(self)->nested_type(index);
1044 }
1045
NewObjectFromItem(ItemDescriptor item)1046 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1047 return PyMessageDescriptor_FromDescriptor(item);
1048 }
1049
GetItemName(ItemDescriptor item)1050 static const string& GetItemName(ItemDescriptor item) {
1051 return item->name();
1052 }
1053
GetItemIndex(ItemDescriptor item)1054 static int GetItemIndex(ItemDescriptor item) {
1055 return item->index();
1056 }
1057
1058 static DescriptorContainerDef ContainerDef = {
1059 "MessageNestedTypes",
1060 (CountMethod)Count,
1061 (GetByIndexMethod)GetByIndex,
1062 (GetByNameMethod)GetByName,
1063 (GetByCamelcaseNameMethod)NULL,
1064 (GetByNumberMethod)NULL,
1065 (NewObjectFromItemMethod)NewObjectFromItem,
1066 (GetItemNameMethod)GetItemName,
1067 (GetItemCamelcaseNameMethod)NULL,
1068 (GetItemNumberMethod)NULL,
1069 (GetItemIndexMethod)GetItemIndex,
1070 };
1071
1072 } // namespace nested_types
1073
NewMessageNestedTypesSeq(ParentDescriptor descriptor)1074 PyObject* NewMessageNestedTypesSeq(ParentDescriptor descriptor) {
1075 return descriptor::NewSequence(&nested_types::ContainerDef, descriptor);
1076 }
1077
NewMessageNestedTypesByName(ParentDescriptor descriptor)1078 PyObject* NewMessageNestedTypesByName(ParentDescriptor descriptor) {
1079 return descriptor::NewMappingByName(&nested_types::ContainerDef, descriptor);
1080 }
1081
1082 namespace enums {
1083
1084 typedef const EnumDescriptor* ItemDescriptor;
1085
Count(PyContainer * self)1086 static int Count(PyContainer* self) {
1087 return GetDescriptor(self)->enum_type_count();
1088 }
1089
GetByName(PyContainer * self,const string & name)1090 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1091 return GetDescriptor(self)->FindEnumTypeByName(name);
1092 }
1093
GetByIndex(PyContainer * self,int index)1094 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1095 return GetDescriptor(self)->enum_type(index);
1096 }
1097
NewObjectFromItem(ItemDescriptor item)1098 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1099 return PyEnumDescriptor_FromDescriptor(item);
1100 }
1101
GetItemName(ItemDescriptor item)1102 static const string& GetItemName(ItemDescriptor item) {
1103 return item->name();
1104 }
1105
GetItemIndex(ItemDescriptor item)1106 static int GetItemIndex(ItemDescriptor item) {
1107 return item->index();
1108 }
1109
1110 static DescriptorContainerDef ContainerDef = {
1111 "MessageNestedEnums",
1112 (CountMethod)Count,
1113 (GetByIndexMethod)GetByIndex,
1114 (GetByNameMethod)GetByName,
1115 (GetByCamelcaseNameMethod)NULL,
1116 (GetByNumberMethod)NULL,
1117 (NewObjectFromItemMethod)NewObjectFromItem,
1118 (GetItemNameMethod)GetItemName,
1119 (GetItemCamelcaseNameMethod)NULL,
1120 (GetItemNumberMethod)NULL,
1121 (GetItemIndexMethod)GetItemIndex,
1122 };
1123
1124 } // namespace enums
1125
NewMessageEnumsByName(ParentDescriptor descriptor)1126 PyObject* NewMessageEnumsByName(ParentDescriptor descriptor) {
1127 return descriptor::NewMappingByName(&enums::ContainerDef, descriptor);
1128 }
1129
NewMessageEnumsSeq(ParentDescriptor descriptor)1130 PyObject* NewMessageEnumsSeq(ParentDescriptor descriptor) {
1131 return descriptor::NewSequence(&enums::ContainerDef, descriptor);
1132 }
1133
1134 namespace enumvalues {
1135
1136 // This is the "enum_values_by_name" mapping, which collects values from all
1137 // enum types in a message.
1138 //
1139 // Note that the behavior of the C++ descriptor is different: it will search and
1140 // return the first value that matches the name, whereas the Python
1141 // implementation retrieves the last one.
1142
1143 typedef const EnumValueDescriptor* ItemDescriptor;
1144
Count(PyContainer * self)1145 static int Count(PyContainer* self) {
1146 int count = 0;
1147 for (int i = 0; i < GetDescriptor(self)->enum_type_count(); ++i) {
1148 count += GetDescriptor(self)->enum_type(i)->value_count();
1149 }
1150 return count;
1151 }
1152
GetByName(PyContainer * self,const string & name)1153 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1154 return GetDescriptor(self)->FindEnumValueByName(name);
1155 }
1156
GetByIndex(PyContainer * self,int index)1157 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1158 // This is not optimal, but the number of enums *types* in a given message
1159 // is small. This function is only used when iterating over the mapping.
1160 const EnumDescriptor* enum_type = NULL;
1161 int enum_type_count = GetDescriptor(self)->enum_type_count();
1162 for (int i = 0; i < enum_type_count; ++i) {
1163 enum_type = GetDescriptor(self)->enum_type(i);
1164 int enum_value_count = enum_type->value_count();
1165 if (index < enum_value_count) {
1166 // Found it!
1167 break;
1168 }
1169 index -= enum_value_count;
1170 }
1171 // The next statement cannot overflow, because this function is only called by
1172 // internal iterators which ensure that 0 <= index < Count().
1173 return enum_type->value(index);
1174 }
1175
NewObjectFromItem(ItemDescriptor item)1176 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1177 return PyEnumValueDescriptor_FromDescriptor(item);
1178 }
1179
GetItemName(ItemDescriptor item)1180 static const string& GetItemName(ItemDescriptor item) {
1181 return item->name();
1182 }
1183
1184 static DescriptorContainerDef ContainerDef = {
1185 "MessageEnumValues",
1186 (CountMethod)Count,
1187 (GetByIndexMethod)GetByIndex,
1188 (GetByNameMethod)GetByName,
1189 (GetByCamelcaseNameMethod)NULL,
1190 (GetByNumberMethod)NULL,
1191 (NewObjectFromItemMethod)NewObjectFromItem,
1192 (GetItemNameMethod)GetItemName,
1193 (GetItemCamelcaseNameMethod)NULL,
1194 (GetItemNumberMethod)NULL,
1195 (GetItemIndexMethod)NULL,
1196 };
1197
1198 } // namespace enumvalues
1199
NewMessageEnumValuesByName(ParentDescriptor descriptor)1200 PyObject* NewMessageEnumValuesByName(ParentDescriptor descriptor) {
1201 return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor);
1202 }
1203
1204 namespace extensions {
1205
1206 typedef const FieldDescriptor* ItemDescriptor;
1207
Count(PyContainer * self)1208 static int Count(PyContainer* self) {
1209 return GetDescriptor(self)->extension_count();
1210 }
1211
GetByName(PyContainer * self,const string & name)1212 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1213 return GetDescriptor(self)->FindExtensionByName(name);
1214 }
1215
GetByIndex(PyContainer * self,int index)1216 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1217 return GetDescriptor(self)->extension(index);
1218 }
1219
NewObjectFromItem(ItemDescriptor item)1220 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1221 return PyFieldDescriptor_FromDescriptor(item);
1222 }
1223
GetItemName(ItemDescriptor item)1224 static const string& GetItemName(ItemDescriptor item) {
1225 return item->name();
1226 }
1227
GetItemIndex(ItemDescriptor item)1228 static int GetItemIndex(ItemDescriptor item) {
1229 return item->index();
1230 }
1231
1232 static DescriptorContainerDef ContainerDef = {
1233 "MessageExtensions",
1234 (CountMethod)Count,
1235 (GetByIndexMethod)GetByIndex,
1236 (GetByNameMethod)GetByName,
1237 (GetByCamelcaseNameMethod)NULL,
1238 (GetByNumberMethod)NULL,
1239 (NewObjectFromItemMethod)NewObjectFromItem,
1240 (GetItemNameMethod)GetItemName,
1241 (GetItemCamelcaseNameMethod)NULL,
1242 (GetItemNumberMethod)NULL,
1243 (GetItemIndexMethod)GetItemIndex,
1244 };
1245
1246 } // namespace extensions
1247
NewMessageExtensionsByName(ParentDescriptor descriptor)1248 PyObject* NewMessageExtensionsByName(ParentDescriptor descriptor) {
1249 return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor);
1250 }
1251
NewMessageExtensionsSeq(ParentDescriptor descriptor)1252 PyObject* NewMessageExtensionsSeq(ParentDescriptor descriptor) {
1253 return descriptor::NewSequence(&extensions::ContainerDef, descriptor);
1254 }
1255
1256 namespace oneofs {
1257
1258 typedef const OneofDescriptor* ItemDescriptor;
1259
Count(PyContainer * self)1260 static int Count(PyContainer* self) {
1261 return GetDescriptor(self)->oneof_decl_count();
1262 }
1263
GetByName(PyContainer * self,const string & name)1264 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1265 return GetDescriptor(self)->FindOneofByName(name);
1266 }
1267
GetByIndex(PyContainer * self,int index)1268 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1269 return GetDescriptor(self)->oneof_decl(index);
1270 }
1271
NewObjectFromItem(ItemDescriptor item)1272 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1273 return PyOneofDescriptor_FromDescriptor(item);
1274 }
1275
GetItemName(ItemDescriptor item)1276 static const string& GetItemName(ItemDescriptor item) {
1277 return item->name();
1278 }
1279
GetItemIndex(ItemDescriptor item)1280 static int GetItemIndex(ItemDescriptor item) {
1281 return item->index();
1282 }
1283
1284 static DescriptorContainerDef ContainerDef = {
1285 "MessageOneofs",
1286 (CountMethod)Count,
1287 (GetByIndexMethod)GetByIndex,
1288 (GetByNameMethod)GetByName,
1289 (GetByCamelcaseNameMethod)NULL,
1290 (GetByNumberMethod)NULL,
1291 (NewObjectFromItemMethod)NewObjectFromItem,
1292 (GetItemNameMethod)GetItemName,
1293 (GetItemCamelcaseNameMethod)NULL,
1294 (GetItemNumberMethod)NULL,
1295 (GetItemIndexMethod)GetItemIndex,
1296 };
1297
1298 } // namespace oneofs
1299
NewMessageOneofsByName(ParentDescriptor descriptor)1300 PyObject* NewMessageOneofsByName(ParentDescriptor descriptor) {
1301 return descriptor::NewMappingByName(&oneofs::ContainerDef, descriptor);
1302 }
1303
NewMessageOneofsSeq(ParentDescriptor descriptor)1304 PyObject* NewMessageOneofsSeq(ParentDescriptor descriptor) {
1305 return descriptor::NewSequence(&oneofs::ContainerDef, descriptor);
1306 }
1307
1308 } // namespace message_descriptor
1309
1310 namespace enum_descriptor {
1311
1312 typedef const EnumDescriptor* ParentDescriptor;
1313
GetDescriptor(PyContainer * self)1314 static ParentDescriptor GetDescriptor(PyContainer* self) {
1315 return reinterpret_cast<ParentDescriptor>(self->descriptor);
1316 }
1317
1318 namespace enumvalues {
1319
1320 typedef const EnumValueDescriptor* ItemDescriptor;
1321
Count(PyContainer * self)1322 static int Count(PyContainer* self) {
1323 return GetDescriptor(self)->value_count();
1324 }
1325
GetByIndex(PyContainer * self,int index)1326 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1327 return GetDescriptor(self)->value(index);
1328 }
1329
GetByName(PyContainer * self,const string & name)1330 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1331 return GetDescriptor(self)->FindValueByName(name);
1332 }
1333
GetByNumber(PyContainer * self,int number)1334 static ItemDescriptor GetByNumber(PyContainer* self, int number) {
1335 return GetDescriptor(self)->FindValueByNumber(number);
1336 }
1337
NewObjectFromItem(ItemDescriptor item)1338 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1339 return PyEnumValueDescriptor_FromDescriptor(item);
1340 }
1341
GetItemName(ItemDescriptor item)1342 static const string& GetItemName(ItemDescriptor item) {
1343 return item->name();
1344 }
1345
GetItemNumber(ItemDescriptor item)1346 static int GetItemNumber(ItemDescriptor item) {
1347 return item->number();
1348 }
1349
GetItemIndex(ItemDescriptor item)1350 static int GetItemIndex(ItemDescriptor item) {
1351 return item->index();
1352 }
1353
1354 static DescriptorContainerDef ContainerDef = {
1355 "EnumValues",
1356 (CountMethod)Count,
1357 (GetByIndexMethod)GetByIndex,
1358 (GetByNameMethod)GetByName,
1359 (GetByCamelcaseNameMethod)NULL,
1360 (GetByNumberMethod)GetByNumber,
1361 (NewObjectFromItemMethod)NewObjectFromItem,
1362 (GetItemNameMethod)GetItemName,
1363 (GetItemCamelcaseNameMethod)NULL,
1364 (GetItemNumberMethod)GetItemNumber,
1365 (GetItemIndexMethod)GetItemIndex,
1366 };
1367
1368 } // namespace enumvalues
1369
NewEnumValuesByName(ParentDescriptor descriptor)1370 PyObject* NewEnumValuesByName(ParentDescriptor descriptor) {
1371 return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor);
1372 }
1373
NewEnumValuesByNumber(ParentDescriptor descriptor)1374 PyObject* NewEnumValuesByNumber(ParentDescriptor descriptor) {
1375 return descriptor::NewMappingByNumber(&enumvalues::ContainerDef, descriptor);
1376 }
1377
NewEnumValuesSeq(ParentDescriptor descriptor)1378 PyObject* NewEnumValuesSeq(ParentDescriptor descriptor) {
1379 return descriptor::NewSequence(&enumvalues::ContainerDef, descriptor);
1380 }
1381
1382 } // namespace enum_descriptor
1383
1384 namespace oneof_descriptor {
1385
1386 typedef const OneofDescriptor* ParentDescriptor;
1387
GetDescriptor(PyContainer * self)1388 static ParentDescriptor GetDescriptor(PyContainer* self) {
1389 return reinterpret_cast<ParentDescriptor>(self->descriptor);
1390 }
1391
1392 namespace fields {
1393
1394 typedef const FieldDescriptor* ItemDescriptor;
1395
Count(PyContainer * self)1396 static int Count(PyContainer* self) {
1397 return GetDescriptor(self)->field_count();
1398 }
1399
GetByIndex(PyContainer * self,int index)1400 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1401 return GetDescriptor(self)->field(index);
1402 }
1403
NewObjectFromItem(ItemDescriptor item)1404 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1405 return PyFieldDescriptor_FromDescriptor(item);
1406 }
1407
GetItemIndex(ItemDescriptor item)1408 static int GetItemIndex(ItemDescriptor item) {
1409 return item->index_in_oneof();
1410 }
1411
1412 static DescriptorContainerDef ContainerDef = {
1413 "OneofFields",
1414 (CountMethod)Count,
1415 (GetByIndexMethod)GetByIndex,
1416 (GetByNameMethod)NULL,
1417 (GetByCamelcaseNameMethod)NULL,
1418 (GetByNumberMethod)NULL,
1419 (NewObjectFromItemMethod)NewObjectFromItem,
1420 (GetItemNameMethod)NULL,
1421 (GetItemCamelcaseNameMethod)NULL,
1422 (GetItemNumberMethod)NULL,
1423 (GetItemIndexMethod)GetItemIndex,
1424 };
1425
1426 } // namespace fields
1427
NewOneofFieldsSeq(ParentDescriptor descriptor)1428 PyObject* NewOneofFieldsSeq(ParentDescriptor descriptor) {
1429 return descriptor::NewSequence(&fields::ContainerDef, descriptor);
1430 }
1431
1432 } // namespace oneof_descriptor
1433
1434 namespace service_descriptor {
1435
1436 typedef const ServiceDescriptor* ParentDescriptor;
1437
GetDescriptor(PyContainer * self)1438 static ParentDescriptor GetDescriptor(PyContainer* self) {
1439 return reinterpret_cast<ParentDescriptor>(self->descriptor);
1440 }
1441
1442 namespace methods {
1443
1444 typedef const MethodDescriptor* ItemDescriptor;
1445
Count(PyContainer * self)1446 static int Count(PyContainer* self) {
1447 return GetDescriptor(self)->method_count();
1448 }
1449
GetByName(PyContainer * self,const string & name)1450 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1451 return GetDescriptor(self)->FindMethodByName(name);
1452 }
1453
GetByIndex(PyContainer * self,int index)1454 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1455 return GetDescriptor(self)->method(index);
1456 }
1457
NewObjectFromItem(ItemDescriptor item)1458 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1459 return PyMethodDescriptor_FromDescriptor(item);
1460 }
1461
GetItemName(ItemDescriptor item)1462 static const string& GetItemName(ItemDescriptor item) {
1463 return item->name();
1464 }
1465
GetItemIndex(ItemDescriptor item)1466 static int GetItemIndex(ItemDescriptor item) {
1467 return item->index();
1468 }
1469
1470 static DescriptorContainerDef ContainerDef = {
1471 "ServiceMethods",
1472 (CountMethod)Count,
1473 (GetByIndexMethod)GetByIndex,
1474 (GetByNameMethod)GetByName,
1475 (GetByCamelcaseNameMethod)NULL,
1476 (GetByNumberMethod)NULL,
1477 (NewObjectFromItemMethod)NewObjectFromItem,
1478 (GetItemNameMethod)GetItemName,
1479 (GetItemCamelcaseNameMethod)NULL,
1480 (GetItemNumberMethod)NULL,
1481 (GetItemIndexMethod)GetItemIndex,
1482 };
1483
1484 } // namespace methods
1485
NewServiceMethodsSeq(ParentDescriptor descriptor)1486 PyObject* NewServiceMethodsSeq(ParentDescriptor descriptor) {
1487 return descriptor::NewSequence(&methods::ContainerDef, descriptor);
1488 }
1489
NewServiceMethodsByName(ParentDescriptor descriptor)1490 PyObject* NewServiceMethodsByName(ParentDescriptor descriptor) {
1491 return descriptor::NewMappingByName(&methods::ContainerDef, descriptor);
1492 }
1493
1494 } // namespace service_descriptor
1495
1496 namespace file_descriptor {
1497
1498 typedef const FileDescriptor* ParentDescriptor;
1499
GetDescriptor(PyContainer * self)1500 static ParentDescriptor GetDescriptor(PyContainer* self) {
1501 return reinterpret_cast<ParentDescriptor>(self->descriptor);
1502 }
1503
1504 namespace messages {
1505
1506 typedef const Descriptor* ItemDescriptor;
1507
Count(PyContainer * self)1508 static int Count(PyContainer* self) {
1509 return GetDescriptor(self)->message_type_count();
1510 }
1511
GetByName(PyContainer * self,const string & name)1512 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1513 return GetDescriptor(self)->FindMessageTypeByName(name);
1514 }
1515
GetByIndex(PyContainer * self,int index)1516 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1517 return GetDescriptor(self)->message_type(index);
1518 }
1519
NewObjectFromItem(ItemDescriptor item)1520 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1521 return PyMessageDescriptor_FromDescriptor(item);
1522 }
1523
GetItemName(ItemDescriptor item)1524 static const string& GetItemName(ItemDescriptor item) {
1525 return item->name();
1526 }
1527
GetItemIndex(ItemDescriptor item)1528 static int GetItemIndex(ItemDescriptor item) {
1529 return item->index();
1530 }
1531
1532 static DescriptorContainerDef ContainerDef = {
1533 "FileMessages",
1534 (CountMethod)Count,
1535 (GetByIndexMethod)GetByIndex,
1536 (GetByNameMethod)GetByName,
1537 (GetByCamelcaseNameMethod)NULL,
1538 (GetByNumberMethod)NULL,
1539 (NewObjectFromItemMethod)NewObjectFromItem,
1540 (GetItemNameMethod)GetItemName,
1541 (GetItemCamelcaseNameMethod)NULL,
1542 (GetItemNumberMethod)NULL,
1543 (GetItemIndexMethod)GetItemIndex,
1544 };
1545
1546 } // namespace messages
1547
NewFileMessageTypesByName(ParentDescriptor descriptor)1548 PyObject* NewFileMessageTypesByName(ParentDescriptor descriptor) {
1549 return descriptor::NewMappingByName(&messages::ContainerDef, descriptor);
1550 }
1551
1552 namespace enums {
1553
1554 typedef const EnumDescriptor* ItemDescriptor;
1555
Count(PyContainer * self)1556 static int Count(PyContainer* self) {
1557 return GetDescriptor(self)->enum_type_count();
1558 }
1559
GetByName(PyContainer * self,const string & name)1560 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1561 return GetDescriptor(self)->FindEnumTypeByName(name);
1562 }
1563
GetByIndex(PyContainer * self,int index)1564 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1565 return GetDescriptor(self)->enum_type(index);
1566 }
1567
NewObjectFromItem(ItemDescriptor item)1568 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1569 return PyEnumDescriptor_FromDescriptor(item);
1570 }
1571
GetItemName(ItemDescriptor item)1572 static const string& GetItemName(ItemDescriptor item) {
1573 return item->name();
1574 }
1575
GetItemIndex(ItemDescriptor item)1576 static int GetItemIndex(ItemDescriptor item) {
1577 return item->index();
1578 }
1579
1580 static DescriptorContainerDef ContainerDef = {
1581 "FileEnums",
1582 (CountMethod)Count,
1583 (GetByIndexMethod)GetByIndex,
1584 (GetByNameMethod)GetByName,
1585 (GetByCamelcaseNameMethod)NULL,
1586 (GetByNumberMethod)NULL,
1587 (NewObjectFromItemMethod)NewObjectFromItem,
1588 (GetItemNameMethod)GetItemName,
1589 (GetItemCamelcaseNameMethod)NULL,
1590 (GetItemNumberMethod)NULL,
1591 (GetItemIndexMethod)GetItemIndex,
1592 };
1593
1594 } // namespace enums
1595
NewFileEnumTypesByName(ParentDescriptor descriptor)1596 PyObject* NewFileEnumTypesByName(ParentDescriptor descriptor) {
1597 return descriptor::NewMappingByName(&enums::ContainerDef, descriptor);
1598 }
1599
1600 namespace extensions {
1601
1602 typedef const FieldDescriptor* ItemDescriptor;
1603
Count(PyContainer * self)1604 static int Count(PyContainer* self) {
1605 return GetDescriptor(self)->extension_count();
1606 }
1607
GetByName(PyContainer * self,const string & name)1608 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1609 return GetDescriptor(self)->FindExtensionByName(name);
1610 }
1611
GetByIndex(PyContainer * self,int index)1612 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1613 return GetDescriptor(self)->extension(index);
1614 }
1615
NewObjectFromItem(ItemDescriptor item)1616 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1617 return PyFieldDescriptor_FromDescriptor(item);
1618 }
1619
GetItemName(ItemDescriptor item)1620 static const string& GetItemName(ItemDescriptor item) {
1621 return item->name();
1622 }
1623
GetItemIndex(ItemDescriptor item)1624 static int GetItemIndex(ItemDescriptor item) {
1625 return item->index();
1626 }
1627
1628 static DescriptorContainerDef ContainerDef = {
1629 "FileExtensions",
1630 (CountMethod)Count,
1631 (GetByIndexMethod)GetByIndex,
1632 (GetByNameMethod)GetByName,
1633 (GetByCamelcaseNameMethod)NULL,
1634 (GetByNumberMethod)NULL,
1635 (NewObjectFromItemMethod)NewObjectFromItem,
1636 (GetItemNameMethod)GetItemName,
1637 (GetItemCamelcaseNameMethod)NULL,
1638 (GetItemNumberMethod)NULL,
1639 (GetItemIndexMethod)GetItemIndex,
1640 };
1641
1642 } // namespace extensions
1643
NewFileExtensionsByName(ParentDescriptor descriptor)1644 PyObject* NewFileExtensionsByName(ParentDescriptor descriptor) {
1645 return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor);
1646 }
1647
1648 namespace services {
1649
1650 typedef const ServiceDescriptor* ItemDescriptor;
1651
Count(PyContainer * self)1652 static int Count(PyContainer* self) {
1653 return GetDescriptor(self)->service_count();
1654 }
1655
GetByName(PyContainer * self,const string & name)1656 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
1657 return GetDescriptor(self)->FindServiceByName(name);
1658 }
1659
GetByIndex(PyContainer * self,int index)1660 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1661 return GetDescriptor(self)->service(index);
1662 }
1663
NewObjectFromItem(ItemDescriptor item)1664 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1665 return PyServiceDescriptor_FromDescriptor(item);
1666 }
1667
GetItemName(ItemDescriptor item)1668 static const string& GetItemName(ItemDescriptor item) {
1669 return item->name();
1670 }
1671
GetItemIndex(ItemDescriptor item)1672 static int GetItemIndex(ItemDescriptor item) {
1673 return item->index();
1674 }
1675
1676 static DescriptorContainerDef ContainerDef = {
1677 "FileServices",
1678 (CountMethod)Count,
1679 (GetByIndexMethod)GetByIndex,
1680 (GetByNameMethod)GetByName,
1681 (GetByCamelcaseNameMethod)NULL,
1682 (GetByNumberMethod)NULL,
1683 (NewObjectFromItemMethod)NewObjectFromItem,
1684 (GetItemNameMethod)GetItemName,
1685 (GetItemCamelcaseNameMethod)NULL,
1686 (GetItemNumberMethod)NULL,
1687 (GetItemIndexMethod)GetItemIndex,
1688 };
1689
1690 } // namespace services
1691
NewFileServicesByName(const FileDescriptor * descriptor)1692 PyObject* NewFileServicesByName(const FileDescriptor* descriptor) {
1693 return descriptor::NewMappingByName(&services::ContainerDef, descriptor);
1694 }
1695
1696 namespace dependencies {
1697
1698 typedef const FileDescriptor* ItemDescriptor;
1699
Count(PyContainer * self)1700 static int Count(PyContainer* self) {
1701 return GetDescriptor(self)->dependency_count();
1702 }
1703
GetByIndex(PyContainer * self,int index)1704 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1705 return GetDescriptor(self)->dependency(index);
1706 }
1707
NewObjectFromItem(ItemDescriptor item)1708 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1709 return PyFileDescriptor_FromDescriptor(item);
1710 }
1711
1712 static DescriptorContainerDef ContainerDef = {
1713 "FileDependencies",
1714 (CountMethod)Count,
1715 (GetByIndexMethod)GetByIndex,
1716 (GetByNameMethod)NULL,
1717 (GetByCamelcaseNameMethod)NULL,
1718 (GetByNumberMethod)NULL,
1719 (NewObjectFromItemMethod)NewObjectFromItem,
1720 (GetItemNameMethod)NULL,
1721 (GetItemCamelcaseNameMethod)NULL,
1722 (GetItemNumberMethod)NULL,
1723 (GetItemIndexMethod)NULL,
1724 };
1725
1726 } // namespace dependencies
1727
NewFileDependencies(const FileDescriptor * descriptor)1728 PyObject* NewFileDependencies(const FileDescriptor* descriptor) {
1729 return descriptor::NewSequence(&dependencies::ContainerDef, descriptor);
1730 }
1731
1732 namespace public_dependencies {
1733
1734 typedef const FileDescriptor* ItemDescriptor;
1735
Count(PyContainer * self)1736 static int Count(PyContainer* self) {
1737 return GetDescriptor(self)->public_dependency_count();
1738 }
1739
GetByIndex(PyContainer * self,int index)1740 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
1741 return GetDescriptor(self)->public_dependency(index);
1742 }
1743
NewObjectFromItem(ItemDescriptor item)1744 static PyObject* NewObjectFromItem(ItemDescriptor item) {
1745 return PyFileDescriptor_FromDescriptor(item);
1746 }
1747
1748 static DescriptorContainerDef ContainerDef = {
1749 "FilePublicDependencies",
1750 (CountMethod)Count,
1751 (GetByIndexMethod)GetByIndex,
1752 (GetByNameMethod)NULL,
1753 (GetByCamelcaseNameMethod)NULL,
1754 (GetByNumberMethod)NULL,
1755 (NewObjectFromItemMethod)NewObjectFromItem,
1756 (GetItemNameMethod)NULL,
1757 (GetItemCamelcaseNameMethod)NULL,
1758 (GetItemNumberMethod)NULL,
1759 (GetItemIndexMethod)NULL,
1760 };
1761
1762 } // namespace public_dependencies
1763
NewFilePublicDependencies(const FileDescriptor * descriptor)1764 PyObject* NewFilePublicDependencies(const FileDescriptor* descriptor) {
1765 return descriptor::NewSequence(&public_dependencies::ContainerDef,
1766 descriptor);
1767 }
1768
1769 } // namespace file_descriptor
1770
1771
1772 // Register all implementations
1773
InitDescriptorMappingTypes()1774 bool InitDescriptorMappingTypes() {
1775 if (PyType_Ready(&descriptor::DescriptorMapping_Type) < 0)
1776 return false;
1777 if (PyType_Ready(&descriptor::DescriptorSequence_Type) < 0)
1778 return false;
1779 if (PyType_Ready(&descriptor::ContainerIterator_Type) < 0)
1780 return false;
1781 return true;
1782 }
1783
1784 } // namespace python
1785 } // namespace protobuf
1786 } // namespace google
1787