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