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. 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. 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. 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 257 static Py_ssize_t Length(PyContainer* self) { 258 return self->container_def->count_fn(self); 259 } 260 261 // The DescriptorMapping type. 262 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 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 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 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. 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. 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 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 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 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 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 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 532 static PyObject* Iter(PyContainer* self) { 533 return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY); 534 } 535 static PyObject* IterKeys(PyContainer* self, PyObject* args) { 536 return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY); 537 } 538 static PyObject* IterValues(PyContainer* self, PyObject* args) { 539 return NewContainerIterator(self, PyContainerIterator::KIND_ITERVALUE); 540 } 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 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 // Returns the position of the item in the sequence, of -1 if not found. 612 // This function never fails. 613 int Find(PyContainer* self, PyObject* item) { 614 // The item can only be in one position: item.index. 615 // Check that self[item.index] == item, it's faster than a linear search. 616 // 617 // This assumes that sequences are only defined by syntax of the .proto file: 618 // a specific item belongs to only one sequence, depending on its position in 619 // the .proto file definition. 620 const void* descriptor_ptr = PyDescriptor_AsVoidPtr(item); 621 if (descriptor_ptr == NULL) { 622 // Not a descriptor, it cannot be in the list. 623 return -1; 624 } 625 if (self->container_def->get_item_index_fn) { 626 int index = self->container_def->get_item_index_fn(descriptor_ptr); 627 if (index < 0 || index >= Length(self)) { 628 // This index is not from this collection. 629 return -1; 630 } 631 if (self->container_def->get_by_index_fn(self, index) != descriptor_ptr) { 632 // The descriptor at this index is not the same. 633 return -1; 634 } 635 // self[item.index] == item, so return the index. 636 return index; 637 } else { 638 // Fall back to linear search. 639 int length = Length(self); 640 for (int index=0; index < length; index++) { 641 if (self->container_def->get_by_index_fn(self, index) == descriptor_ptr) { 642 return index; 643 } 644 } 645 // Not found 646 return -1; 647 } 648 } 649 650 // Implements list.index(): the position of the item is in the sequence. 651 static PyObject* Index(PyContainer* self, PyObject* item) { 652 int position = Find(self, item); 653 if (position < 0) { 654 // Not found 655 PyErr_SetNone(PyExc_ValueError); 656 return NULL; 657 } else { 658 return PyInt_FromLong(position); 659 } 660 } 661 // Implements "list.__contains__()": is the object in the sequence. 662 static int SeqContains(PyContainer* self, PyObject* item) { 663 int position = Find(self, item); 664 if (position < 0) { 665 return 0; 666 } else { 667 return 1; 668 } 669 } 670 671 // Implements list.count(): number of occurrences of the item in the sequence. 672 // An item can only appear once in a sequence. If it exists, return 1. 673 static PyObject* Count(PyContainer* self, PyObject* item) { 674 int position = Find(self, item); 675 if (position < 0) { 676 return PyInt_FromLong(0); 677 } else { 678 return PyInt_FromLong(1); 679 } 680 } 681 682 static PyObject* Append(PyContainer* self, PyObject* args) { 683 if (_CalledFromGeneratedFile(0)) { 684 Py_RETURN_NONE; 685 } 686 PyErr_Format(PyExc_TypeError, 687 "'%.200s' object is not a mutable sequence", 688 Py_TYPE(self)->tp_name); 689 return NULL; 690 } 691 692 static PyObject* Reversed(PyContainer* self, PyObject* args) { 693 return NewContainerIterator(self, 694 PyContainerIterator::KIND_ITERVALUE_REVERSED); 695 } 696 697 static PyMethodDef SeqMethods[] = { 698 { "index", (PyCFunction)Index, METH_O, }, 699 { "count", (PyCFunction)Count, METH_O, }, 700 { "append", (PyCFunction)Append, METH_O, }, 701 { "__reversed__", (PyCFunction)Reversed, METH_NOARGS, }, 702 {NULL} 703 }; 704 705 static PySequenceMethods SeqSequenceMethods = { 706 (lenfunc)Length, // sq_length 707 0, // sq_concat 708 0, // sq_repeat 709 (ssizeargfunc)GetItem, // sq_item 710 0, // sq_slice 711 0, // sq_ass_item 712 0, // sq_ass_slice 713 (objobjproc)SeqContains, // sq_contains 714 }; 715 716 PyTypeObject DescriptorSequence_Type = { 717 PyVarObject_HEAD_INIT(&PyType_Type, 0) 718 "DescriptorSequence", // tp_name 719 sizeof(PyContainer), // tp_basicsize 720 0, // tp_itemsize 721 0, // tp_dealloc 722 0, // tp_print 723 0, // tp_getattr 724 0, // tp_setattr 725 0, // tp_compare 726 (reprfunc)ContainerRepr, // tp_repr 727 0, // tp_as_number 728 &SeqSequenceMethods, // tp_as_sequence 729 0, // tp_as_mapping 730 0, // tp_hash 731 0, // tp_call 732 0, // tp_str 733 0, // tp_getattro 734 0, // tp_setattro 735 0, // tp_as_buffer 736 Py_TPFLAGS_DEFAULT, // tp_flags 737 0, // tp_doc 738 0, // tp_traverse 739 0, // tp_clear 740 (richcmpfunc)RichCompare, // tp_richcompare 741 0, // tp_weaklistoffset 742 0, // tp_iter 743 0, // tp_iternext 744 SeqMethods, // tp_methods 745 0, // tp_members 746 0, // tp_getset 747 0, // tp_base 748 0, // tp_dict 749 0, // tp_descr_get 750 0, // tp_descr_set 751 0, // tp_dictoffset 752 0, // tp_init 753 0, // tp_alloc 754 0, // tp_new 755 0, // tp_free 756 }; 757 758 static PyObject* NewMappingByName( 759 DescriptorContainerDef* container_def, const void* descriptor) { 760 PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type); 761 if (self == NULL) { 762 return NULL; 763 } 764 self->descriptor = descriptor; 765 self->container_def = container_def; 766 self->kind = PyContainer::KIND_BYNAME; 767 return reinterpret_cast<PyObject*>(self); 768 } 769 770 static PyObject* NewMappingByCamelcaseName( 771 DescriptorContainerDef* container_def, const void* descriptor) { 772 PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type); 773 if (self == NULL) { 774 return NULL; 775 } 776 self->descriptor = descriptor; 777 self->container_def = container_def; 778 self->kind = PyContainer::KIND_BYCAMELCASENAME; 779 return reinterpret_cast<PyObject*>(self); 780 } 781 782 static PyObject* NewMappingByNumber( 783 DescriptorContainerDef* container_def, const void* descriptor) { 784 if (container_def->get_by_number_fn == NULL || 785 container_def->get_item_number_fn == NULL) { 786 PyErr_SetNone(PyExc_NotImplementedError); 787 return NULL; 788 } 789 PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type); 790 if (self == NULL) { 791 return NULL; 792 } 793 self->descriptor = descriptor; 794 self->container_def = container_def; 795 self->kind = PyContainer::KIND_BYNUMBER; 796 return reinterpret_cast<PyObject*>(self); 797 } 798 799 static PyObject* NewSequence( 800 DescriptorContainerDef* container_def, const void* descriptor) { 801 PyContainer* self = PyObject_New(PyContainer, &DescriptorSequence_Type); 802 if (self == NULL) { 803 return NULL; 804 } 805 self->descriptor = descriptor; 806 self->container_def = container_def; 807 self->kind = PyContainer::KIND_SEQUENCE; 808 return reinterpret_cast<PyObject*>(self); 809 } 810 811 // Implement iterators over PyContainers. 812 813 static void Iterator_Dealloc(PyContainerIterator* self) { 814 Py_CLEAR(self->container); 815 Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); 816 } 817 818 static PyObject* Iterator_Next(PyContainerIterator* self) { 819 int count = self->container->container_def->count_fn(self->container); 820 if (self->index >= count) { 821 // Return NULL with no exception to indicate the end. 822 return NULL; 823 } 824 int index = self->index; 825 self->index += 1; 826 switch (self->kind) { 827 case PyContainerIterator::KIND_ITERKEY: 828 return _NewKey_ByIndex(self->container, index); 829 case PyContainerIterator::KIND_ITERVALUE: 830 return _NewObj_ByIndex(self->container, index); 831 case PyContainerIterator::KIND_ITERVALUE_REVERSED: 832 return _NewObj_ByIndex(self->container, count - index - 1); 833 case PyContainerIterator::KIND_ITERITEM: 834 { 835 PyObject* obj = PyTuple_New(2); 836 if (obj == NULL) { 837 return NULL; 838 } 839 PyObject* key = _NewKey_ByIndex(self->container, index); 840 if (key == NULL) { 841 Py_DECREF(obj); 842 return NULL; 843 } 844 PyTuple_SET_ITEM(obj, 0, key); 845 PyObject* value = _NewObj_ByIndex(self->container, index); 846 if (value == NULL) { 847 Py_DECREF(obj); 848 return NULL; 849 } 850 PyTuple_SET_ITEM(obj, 1, value); 851 return obj; 852 } 853 default: 854 PyErr_SetNone(PyExc_NotImplementedError); 855 return NULL; 856 } 857 } 858 859 static PyTypeObject ContainerIterator_Type = { 860 PyVarObject_HEAD_INIT(&PyType_Type, 0) 861 "DescriptorContainerIterator", // tp_name 862 sizeof(PyContainerIterator), // tp_basicsize 863 0, // tp_itemsize 864 (destructor)Iterator_Dealloc, // tp_dealloc 865 0, // tp_print 866 0, // tp_getattr 867 0, // tp_setattr 868 0, // tp_compare 869 0, // tp_repr 870 0, // tp_as_number 871 0, // tp_as_sequence 872 0, // tp_as_mapping 873 0, // tp_hash 874 0, // tp_call 875 0, // tp_str 876 0, // tp_getattro 877 0, // tp_setattro 878 0, // tp_as_buffer 879 Py_TPFLAGS_DEFAULT, // tp_flags 880 0, // tp_doc 881 0, // tp_traverse 882 0, // tp_clear 883 0, // tp_richcompare 884 0, // tp_weaklistoffset 885 PyObject_SelfIter, // tp_iter 886 (iternextfunc)Iterator_Next, // tp_iternext 887 0, // tp_methods 888 0, // tp_members 889 0, // tp_getset 890 0, // tp_base 891 0, // tp_dict 892 0, // tp_descr_get 893 0, // tp_descr_set 894 0, // tp_dictoffset 895 0, // tp_init 896 0, // tp_alloc 897 0, // tp_new 898 0, // tp_free 899 }; 900 901 static PyObject* NewContainerIterator(PyContainer* container, 902 PyContainerIterator::IterKind kind) { 903 PyContainerIterator* self = PyObject_New(PyContainerIterator, 904 &ContainerIterator_Type); 905 if (self == NULL) { 906 return NULL; 907 } 908 Py_INCREF(container); 909 self->container = container; 910 self->kind = kind; 911 self->index = 0; 912 913 return reinterpret_cast<PyObject*>(self); 914 } 915 916 } // namespace descriptor 917 918 // Now define the real collections! 919 920 namespace message_descriptor { 921 922 typedef const Descriptor* ParentDescriptor; 923 924 static ParentDescriptor GetDescriptor(PyContainer* self) { 925 return reinterpret_cast<ParentDescriptor>(self->descriptor); 926 } 927 928 namespace fields { 929 930 typedef const FieldDescriptor* ItemDescriptor; 931 932 static int Count(PyContainer* self) { 933 return GetDescriptor(self)->field_count(); 934 } 935 936 static ItemDescriptor GetByName(PyContainer* self, const string& name) { 937 return GetDescriptor(self)->FindFieldByName(name); 938 } 939 940 static ItemDescriptor GetByCamelcaseName(PyContainer* self, 941 const string& name) { 942 return GetDescriptor(self)->FindFieldByCamelcaseName(name); 943 } 944 945 static ItemDescriptor GetByNumber(PyContainer* self, int number) { 946 return GetDescriptor(self)->FindFieldByNumber(number); 947 } 948 949 static ItemDescriptor GetByIndex(PyContainer* self, int index) { 950 return GetDescriptor(self)->field(index); 951 } 952 953 static PyObject* NewObjectFromItem(ItemDescriptor item) { 954 return PyFieldDescriptor_FromDescriptor(item); 955 } 956 957 static const string& GetItemName(ItemDescriptor item) { 958 return item->name(); 959 } 960 961 static const string& GetItemCamelcaseName(ItemDescriptor item) { 962 return item->camelcase_name(); 963 } 964 965 static int GetItemNumber(ItemDescriptor item) { 966 return item->number(); 967 } 968 969 static int GetItemIndex(ItemDescriptor item) { 970 return item->index(); 971 } 972 973 static DescriptorContainerDef ContainerDef = { 974 "MessageFields", 975 (CountMethod)Count, 976 (GetByIndexMethod)GetByIndex, 977 (GetByNameMethod)GetByName, 978 (GetByCamelcaseNameMethod)GetByCamelcaseName, 979 (GetByNumberMethod)GetByNumber, 980 (NewObjectFromItemMethod)NewObjectFromItem, 981 (GetItemNameMethod)GetItemName, 982 (GetItemCamelcaseNameMethod)GetItemCamelcaseName, 983 (GetItemNumberMethod)GetItemNumber, 984 (GetItemIndexMethod)GetItemIndex, 985 }; 986 987 } // namespace fields 988 989 PyObject* NewMessageFieldsByName(ParentDescriptor descriptor) { 990 return descriptor::NewMappingByName(&fields::ContainerDef, descriptor); 991 } 992 993 PyObject* NewMessageFieldsByCamelcaseName(ParentDescriptor descriptor) { 994 return descriptor::NewMappingByCamelcaseName(&fields::ContainerDef, 995 descriptor); 996 } 997 998 PyObject* NewMessageFieldsByNumber(ParentDescriptor descriptor) { 999 return descriptor::NewMappingByNumber(&fields::ContainerDef, descriptor); 1000 } 1001 1002 PyObject* NewMessageFieldsSeq(ParentDescriptor descriptor) { 1003 return descriptor::NewSequence(&fields::ContainerDef, descriptor); 1004 } 1005 1006 namespace nested_types { 1007 1008 typedef const Descriptor* ItemDescriptor; 1009 1010 static int Count(PyContainer* self) { 1011 return GetDescriptor(self)->nested_type_count(); 1012 } 1013 1014 static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1015 return GetDescriptor(self)->FindNestedTypeByName(name); 1016 } 1017 1018 static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1019 return GetDescriptor(self)->nested_type(index); 1020 } 1021 1022 static PyObject* NewObjectFromItem(ItemDescriptor item) { 1023 return PyMessageDescriptor_FromDescriptor(item); 1024 } 1025 1026 static const string& GetItemName(ItemDescriptor item) { 1027 return item->name(); 1028 } 1029 1030 static int GetItemIndex(ItemDescriptor item) { 1031 return item->index(); 1032 } 1033 1034 static DescriptorContainerDef ContainerDef = { 1035 "MessageNestedTypes", 1036 (CountMethod)Count, 1037 (GetByIndexMethod)GetByIndex, 1038 (GetByNameMethod)GetByName, 1039 (GetByCamelcaseNameMethod)NULL, 1040 (GetByNumberMethod)NULL, 1041 (NewObjectFromItemMethod)NewObjectFromItem, 1042 (GetItemNameMethod)GetItemName, 1043 (GetItemCamelcaseNameMethod)NULL, 1044 (GetItemNumberMethod)NULL, 1045 (GetItemIndexMethod)GetItemIndex, 1046 }; 1047 1048 } // namespace nested_types 1049 1050 PyObject* NewMessageNestedTypesSeq(ParentDescriptor descriptor) { 1051 return descriptor::NewSequence(&nested_types::ContainerDef, descriptor); 1052 } 1053 1054 PyObject* NewMessageNestedTypesByName(ParentDescriptor descriptor) { 1055 return descriptor::NewMappingByName(&nested_types::ContainerDef, descriptor); 1056 } 1057 1058 namespace enums { 1059 1060 typedef const EnumDescriptor* ItemDescriptor; 1061 1062 static int Count(PyContainer* self) { 1063 return GetDescriptor(self)->enum_type_count(); 1064 } 1065 1066 static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1067 return GetDescriptor(self)->FindEnumTypeByName(name); 1068 } 1069 1070 static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1071 return GetDescriptor(self)->enum_type(index); 1072 } 1073 1074 static PyObject* NewObjectFromItem(ItemDescriptor item) { 1075 return PyEnumDescriptor_FromDescriptor(item); 1076 } 1077 1078 static const string& GetItemName(ItemDescriptor item) { 1079 return item->name(); 1080 } 1081 1082 static int GetItemIndex(ItemDescriptor item) { 1083 return item->index(); 1084 } 1085 1086 static DescriptorContainerDef ContainerDef = { 1087 "MessageNestedEnums", 1088 (CountMethod)Count, 1089 (GetByIndexMethod)GetByIndex, 1090 (GetByNameMethod)GetByName, 1091 (GetByCamelcaseNameMethod)NULL, 1092 (GetByNumberMethod)NULL, 1093 (NewObjectFromItemMethod)NewObjectFromItem, 1094 (GetItemNameMethod)GetItemName, 1095 (GetItemCamelcaseNameMethod)NULL, 1096 (GetItemNumberMethod)NULL, 1097 (GetItemIndexMethod)GetItemIndex, 1098 }; 1099 1100 } // namespace enums 1101 1102 PyObject* NewMessageEnumsByName(ParentDescriptor descriptor) { 1103 return descriptor::NewMappingByName(&enums::ContainerDef, descriptor); 1104 } 1105 1106 PyObject* NewMessageEnumsSeq(ParentDescriptor descriptor) { 1107 return descriptor::NewSequence(&enums::ContainerDef, descriptor); 1108 } 1109 1110 namespace enumvalues { 1111 1112 // This is the "enum_values_by_name" mapping, which collects values from all 1113 // enum types in a message. 1114 // 1115 // Note that the behavior of the C++ descriptor is different: it will search and 1116 // return the first value that matches the name, whereas the Python 1117 // implementation retrieves the last one. 1118 1119 typedef const EnumValueDescriptor* ItemDescriptor; 1120 1121 static int Count(PyContainer* self) { 1122 int count = 0; 1123 for (int i = 0; i < GetDescriptor(self)->enum_type_count(); ++i) { 1124 count += GetDescriptor(self)->enum_type(i)->value_count(); 1125 } 1126 return count; 1127 } 1128 1129 static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1130 return GetDescriptor(self)->FindEnumValueByName(name); 1131 } 1132 1133 static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1134 // This is not optimal, but the number of enums *types* in a given message 1135 // is small. This function is only used when iterating over the mapping. 1136 const EnumDescriptor* enum_type = NULL; 1137 int enum_type_count = GetDescriptor(self)->enum_type_count(); 1138 for (int i = 0; i < enum_type_count; ++i) { 1139 enum_type = GetDescriptor(self)->enum_type(i); 1140 int enum_value_count = enum_type->value_count(); 1141 if (index < enum_value_count) { 1142 // Found it! 1143 break; 1144 } 1145 index -= enum_value_count; 1146 } 1147 // The next statement cannot overflow, because this function is only called by 1148 // internal iterators which ensure that 0 <= index < Count(). 1149 return enum_type->value(index); 1150 } 1151 1152 static PyObject* NewObjectFromItem(ItemDescriptor item) { 1153 return PyEnumValueDescriptor_FromDescriptor(item); 1154 } 1155 1156 static const string& GetItemName(ItemDescriptor item) { 1157 return item->name(); 1158 } 1159 1160 static DescriptorContainerDef ContainerDef = { 1161 "MessageEnumValues", 1162 (CountMethod)Count, 1163 (GetByIndexMethod)GetByIndex, 1164 (GetByNameMethod)GetByName, 1165 (GetByCamelcaseNameMethod)NULL, 1166 (GetByNumberMethod)NULL, 1167 (NewObjectFromItemMethod)NewObjectFromItem, 1168 (GetItemNameMethod)GetItemName, 1169 (GetItemCamelcaseNameMethod)NULL, 1170 (GetItemNumberMethod)NULL, 1171 (GetItemIndexMethod)NULL, 1172 }; 1173 1174 } // namespace enumvalues 1175 1176 PyObject* NewMessageEnumValuesByName(ParentDescriptor descriptor) { 1177 return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor); 1178 } 1179 1180 namespace extensions { 1181 1182 typedef const FieldDescriptor* ItemDescriptor; 1183 1184 static int Count(PyContainer* self) { 1185 return GetDescriptor(self)->extension_count(); 1186 } 1187 1188 static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1189 return GetDescriptor(self)->FindExtensionByName(name); 1190 } 1191 1192 static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1193 return GetDescriptor(self)->extension(index); 1194 } 1195 1196 static PyObject* NewObjectFromItem(ItemDescriptor item) { 1197 return PyFieldDescriptor_FromDescriptor(item); 1198 } 1199 1200 static const string& GetItemName(ItemDescriptor item) { 1201 return item->name(); 1202 } 1203 1204 static int GetItemIndex(ItemDescriptor item) { 1205 return item->index(); 1206 } 1207 1208 static DescriptorContainerDef ContainerDef = { 1209 "MessageExtensions", 1210 (CountMethod)Count, 1211 (GetByIndexMethod)GetByIndex, 1212 (GetByNameMethod)GetByName, 1213 (GetByCamelcaseNameMethod)NULL, 1214 (GetByNumberMethod)NULL, 1215 (NewObjectFromItemMethod)NewObjectFromItem, 1216 (GetItemNameMethod)GetItemName, 1217 (GetItemCamelcaseNameMethod)NULL, 1218 (GetItemNumberMethod)NULL, 1219 (GetItemIndexMethod)GetItemIndex, 1220 }; 1221 1222 } // namespace extensions 1223 1224 PyObject* NewMessageExtensionsByName(ParentDescriptor descriptor) { 1225 return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor); 1226 } 1227 1228 PyObject* NewMessageExtensionsSeq(ParentDescriptor descriptor) { 1229 return descriptor::NewSequence(&extensions::ContainerDef, descriptor); 1230 } 1231 1232 namespace oneofs { 1233 1234 typedef const OneofDescriptor* ItemDescriptor; 1235 1236 static int Count(PyContainer* self) { 1237 return GetDescriptor(self)->oneof_decl_count(); 1238 } 1239 1240 static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1241 return GetDescriptor(self)->FindOneofByName(name); 1242 } 1243 1244 static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1245 return GetDescriptor(self)->oneof_decl(index); 1246 } 1247 1248 static PyObject* NewObjectFromItem(ItemDescriptor item) { 1249 return PyOneofDescriptor_FromDescriptor(item); 1250 } 1251 1252 static const string& GetItemName(ItemDescriptor item) { 1253 return item->name(); 1254 } 1255 1256 static int GetItemIndex(ItemDescriptor item) { 1257 return item->index(); 1258 } 1259 1260 static DescriptorContainerDef ContainerDef = { 1261 "MessageOneofs", 1262 (CountMethod)Count, 1263 (GetByIndexMethod)GetByIndex, 1264 (GetByNameMethod)GetByName, 1265 (GetByCamelcaseNameMethod)NULL, 1266 (GetByNumberMethod)NULL, 1267 (NewObjectFromItemMethod)NewObjectFromItem, 1268 (GetItemNameMethod)GetItemName, 1269 (GetItemCamelcaseNameMethod)NULL, 1270 (GetItemNumberMethod)NULL, 1271 (GetItemIndexMethod)GetItemIndex, 1272 }; 1273 1274 } // namespace oneofs 1275 1276 PyObject* NewMessageOneofsByName(ParentDescriptor descriptor) { 1277 return descriptor::NewMappingByName(&oneofs::ContainerDef, descriptor); 1278 } 1279 1280 PyObject* NewMessageOneofsSeq(ParentDescriptor descriptor) { 1281 return descriptor::NewSequence(&oneofs::ContainerDef, descriptor); 1282 } 1283 1284 } // namespace message_descriptor 1285 1286 namespace enum_descriptor { 1287 1288 typedef const EnumDescriptor* ParentDescriptor; 1289 1290 static ParentDescriptor GetDescriptor(PyContainer* self) { 1291 return reinterpret_cast<ParentDescriptor>(self->descriptor); 1292 } 1293 1294 namespace enumvalues { 1295 1296 typedef const EnumValueDescriptor* ItemDescriptor; 1297 1298 static int Count(PyContainer* self) { 1299 return GetDescriptor(self)->value_count(); 1300 } 1301 1302 static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1303 return GetDescriptor(self)->value(index); 1304 } 1305 1306 static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1307 return GetDescriptor(self)->FindValueByName(name); 1308 } 1309 1310 static ItemDescriptor GetByNumber(PyContainer* self, int number) { 1311 return GetDescriptor(self)->FindValueByNumber(number); 1312 } 1313 1314 static PyObject* NewObjectFromItem(ItemDescriptor item) { 1315 return PyEnumValueDescriptor_FromDescriptor(item); 1316 } 1317 1318 static const string& GetItemName(ItemDescriptor item) { 1319 return item->name(); 1320 } 1321 1322 static int GetItemNumber(ItemDescriptor item) { 1323 return item->number(); 1324 } 1325 1326 static int GetItemIndex(ItemDescriptor item) { 1327 return item->index(); 1328 } 1329 1330 static DescriptorContainerDef ContainerDef = { 1331 "EnumValues", 1332 (CountMethod)Count, 1333 (GetByIndexMethod)GetByIndex, 1334 (GetByNameMethod)GetByName, 1335 (GetByCamelcaseNameMethod)NULL, 1336 (GetByNumberMethod)GetByNumber, 1337 (NewObjectFromItemMethod)NewObjectFromItem, 1338 (GetItemNameMethod)GetItemName, 1339 (GetItemCamelcaseNameMethod)NULL, 1340 (GetItemNumberMethod)GetItemNumber, 1341 (GetItemIndexMethod)GetItemIndex, 1342 }; 1343 1344 } // namespace enumvalues 1345 1346 PyObject* NewEnumValuesByName(ParentDescriptor descriptor) { 1347 return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor); 1348 } 1349 1350 PyObject* NewEnumValuesByNumber(ParentDescriptor descriptor) { 1351 return descriptor::NewMappingByNumber(&enumvalues::ContainerDef, descriptor); 1352 } 1353 1354 PyObject* NewEnumValuesSeq(ParentDescriptor descriptor) { 1355 return descriptor::NewSequence(&enumvalues::ContainerDef, descriptor); 1356 } 1357 1358 } // namespace enum_descriptor 1359 1360 namespace oneof_descriptor { 1361 1362 typedef const OneofDescriptor* ParentDescriptor; 1363 1364 static ParentDescriptor GetDescriptor(PyContainer* self) { 1365 return reinterpret_cast<ParentDescriptor>(self->descriptor); 1366 } 1367 1368 namespace fields { 1369 1370 typedef const FieldDescriptor* ItemDescriptor; 1371 1372 static int Count(PyContainer* self) { 1373 return GetDescriptor(self)->field_count(); 1374 } 1375 1376 static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1377 return GetDescriptor(self)->field(index); 1378 } 1379 1380 static PyObject* NewObjectFromItem(ItemDescriptor item) { 1381 return PyFieldDescriptor_FromDescriptor(item); 1382 } 1383 1384 static int GetItemIndex(ItemDescriptor item) { 1385 return item->index_in_oneof(); 1386 } 1387 1388 static DescriptorContainerDef ContainerDef = { 1389 "OneofFields", 1390 (CountMethod)Count, 1391 (GetByIndexMethod)GetByIndex, 1392 (GetByNameMethod)NULL, 1393 (GetByCamelcaseNameMethod)NULL, 1394 (GetByNumberMethod)NULL, 1395 (NewObjectFromItemMethod)NewObjectFromItem, 1396 (GetItemNameMethod)NULL, 1397 (GetItemCamelcaseNameMethod)NULL, 1398 (GetItemNumberMethod)NULL, 1399 (GetItemIndexMethod)GetItemIndex, 1400 }; 1401 1402 } // namespace fields 1403 1404 PyObject* NewOneofFieldsSeq(ParentDescriptor descriptor) { 1405 return descriptor::NewSequence(&fields::ContainerDef, descriptor); 1406 } 1407 1408 } // namespace oneof_descriptor 1409 1410 namespace file_descriptor { 1411 1412 typedef const FileDescriptor* ParentDescriptor; 1413 1414 static ParentDescriptor GetDescriptor(PyContainer* self) { 1415 return reinterpret_cast<ParentDescriptor>(self->descriptor); 1416 } 1417 1418 namespace messages { 1419 1420 typedef const Descriptor* ItemDescriptor; 1421 1422 static int Count(PyContainer* self) { 1423 return GetDescriptor(self)->message_type_count(); 1424 } 1425 1426 static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1427 return GetDescriptor(self)->FindMessageTypeByName(name); 1428 } 1429 1430 static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1431 return GetDescriptor(self)->message_type(index); 1432 } 1433 1434 static PyObject* NewObjectFromItem(ItemDescriptor item) { 1435 return PyMessageDescriptor_FromDescriptor(item); 1436 } 1437 1438 static const string& GetItemName(ItemDescriptor item) { 1439 return item->name(); 1440 } 1441 1442 static int GetItemIndex(ItemDescriptor item) { 1443 return item->index(); 1444 } 1445 1446 static DescriptorContainerDef ContainerDef = { 1447 "FileMessages", 1448 (CountMethod)Count, 1449 (GetByIndexMethod)GetByIndex, 1450 (GetByNameMethod)GetByName, 1451 (GetByCamelcaseNameMethod)NULL, 1452 (GetByNumberMethod)NULL, 1453 (NewObjectFromItemMethod)NewObjectFromItem, 1454 (GetItemNameMethod)GetItemName, 1455 (GetItemCamelcaseNameMethod)NULL, 1456 (GetItemNumberMethod)NULL, 1457 (GetItemIndexMethod)GetItemIndex, 1458 }; 1459 1460 } // namespace messages 1461 1462 PyObject* NewFileMessageTypesByName(const FileDescriptor* descriptor) { 1463 return descriptor::NewMappingByName(&messages::ContainerDef, descriptor); 1464 } 1465 1466 namespace enums { 1467 1468 typedef const EnumDescriptor* ItemDescriptor; 1469 1470 static int Count(PyContainer* self) { 1471 return GetDescriptor(self)->enum_type_count(); 1472 } 1473 1474 static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1475 return GetDescriptor(self)->FindEnumTypeByName(name); 1476 } 1477 1478 static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1479 return GetDescriptor(self)->enum_type(index); 1480 } 1481 1482 static PyObject* NewObjectFromItem(ItemDescriptor item) { 1483 return PyEnumDescriptor_FromDescriptor(item); 1484 } 1485 1486 static const string& GetItemName(ItemDescriptor item) { 1487 return item->name(); 1488 } 1489 1490 static int GetItemIndex(ItemDescriptor item) { 1491 return item->index(); 1492 } 1493 1494 static DescriptorContainerDef ContainerDef = { 1495 "FileEnums", 1496 (CountMethod)Count, 1497 (GetByIndexMethod)GetByIndex, 1498 (GetByNameMethod)GetByName, 1499 (GetByCamelcaseNameMethod)NULL, 1500 (GetByNumberMethod)NULL, 1501 (NewObjectFromItemMethod)NewObjectFromItem, 1502 (GetItemNameMethod)GetItemName, 1503 (GetItemCamelcaseNameMethod)NULL, 1504 (GetItemNumberMethod)NULL, 1505 (GetItemIndexMethod)GetItemIndex, 1506 }; 1507 1508 } // namespace enums 1509 1510 PyObject* NewFileEnumTypesByName(const FileDescriptor* descriptor) { 1511 return descriptor::NewMappingByName(&enums::ContainerDef, descriptor); 1512 } 1513 1514 namespace extensions { 1515 1516 typedef const FieldDescriptor* ItemDescriptor; 1517 1518 static int Count(PyContainer* self) { 1519 return GetDescriptor(self)->extension_count(); 1520 } 1521 1522 static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1523 return GetDescriptor(self)->FindExtensionByName(name); 1524 } 1525 1526 static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1527 return GetDescriptor(self)->extension(index); 1528 } 1529 1530 static PyObject* NewObjectFromItem(ItemDescriptor item) { 1531 return PyFieldDescriptor_FromDescriptor(item); 1532 } 1533 1534 static const string& GetItemName(ItemDescriptor item) { 1535 return item->name(); 1536 } 1537 1538 static int GetItemIndex(ItemDescriptor item) { 1539 return item->index(); 1540 } 1541 1542 static DescriptorContainerDef ContainerDef = { 1543 "FileExtensions", 1544 (CountMethod)Count, 1545 (GetByIndexMethod)GetByIndex, 1546 (GetByNameMethod)GetByName, 1547 (GetByCamelcaseNameMethod)NULL, 1548 (GetByNumberMethod)NULL, 1549 (NewObjectFromItemMethod)NewObjectFromItem, 1550 (GetItemNameMethod)GetItemName, 1551 (GetItemCamelcaseNameMethod)NULL, 1552 (GetItemNumberMethod)NULL, 1553 (GetItemIndexMethod)GetItemIndex, 1554 }; 1555 1556 } // namespace extensions 1557 1558 PyObject* NewFileExtensionsByName(const FileDescriptor* descriptor) { 1559 return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor); 1560 } 1561 1562 namespace dependencies { 1563 1564 typedef const FileDescriptor* ItemDescriptor; 1565 1566 static int Count(PyContainer* self) { 1567 return GetDescriptor(self)->dependency_count(); 1568 } 1569 1570 static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1571 return GetDescriptor(self)->dependency(index); 1572 } 1573 1574 static PyObject* NewObjectFromItem(ItemDescriptor item) { 1575 return PyFileDescriptor_FromDescriptor(item); 1576 } 1577 1578 static DescriptorContainerDef ContainerDef = { 1579 "FileDependencies", 1580 (CountMethod)Count, 1581 (GetByIndexMethod)GetByIndex, 1582 (GetByNameMethod)NULL, 1583 (GetByCamelcaseNameMethod)NULL, 1584 (GetByNumberMethod)NULL, 1585 (NewObjectFromItemMethod)NewObjectFromItem, 1586 (GetItemNameMethod)NULL, 1587 (GetItemCamelcaseNameMethod)NULL, 1588 (GetItemNumberMethod)NULL, 1589 (GetItemIndexMethod)NULL, 1590 }; 1591 1592 } // namespace dependencies 1593 1594 PyObject* NewFileDependencies(const FileDescriptor* descriptor) { 1595 return descriptor::NewSequence(&dependencies::ContainerDef, descriptor); 1596 } 1597 1598 namespace public_dependencies { 1599 1600 typedef const FileDescriptor* ItemDescriptor; 1601 1602 static int Count(PyContainer* self) { 1603 return GetDescriptor(self)->public_dependency_count(); 1604 } 1605 1606 static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1607 return GetDescriptor(self)->public_dependency(index); 1608 } 1609 1610 static PyObject* NewObjectFromItem(ItemDescriptor item) { 1611 return PyFileDescriptor_FromDescriptor(item); 1612 } 1613 1614 static DescriptorContainerDef ContainerDef = { 1615 "FilePublicDependencies", 1616 (CountMethod)Count, 1617 (GetByIndexMethod)GetByIndex, 1618 (GetByNameMethod)NULL, 1619 (GetByCamelcaseNameMethod)NULL, 1620 (GetByNumberMethod)NULL, 1621 (NewObjectFromItemMethod)NewObjectFromItem, 1622 (GetItemNameMethod)NULL, 1623 (GetItemCamelcaseNameMethod)NULL, 1624 (GetItemNumberMethod)NULL, 1625 (GetItemIndexMethod)NULL, 1626 }; 1627 1628 } // namespace public_dependencies 1629 1630 PyObject* NewFilePublicDependencies(const FileDescriptor* descriptor) { 1631 return descriptor::NewSequence(&public_dependencies::ContainerDef, 1632 descriptor); 1633 } 1634 1635 } // namespace file_descriptor 1636 1637 1638 // Register all implementations 1639 1640 bool InitDescriptorMappingTypes() { 1641 if (PyType_Ready(&descriptor::DescriptorMapping_Type) < 0) 1642 return false; 1643 if (PyType_Ready(&descriptor::DescriptorSequence_Type) < 0) 1644 return false; 1645 if (PyType_Ready(&descriptor::ContainerIterator_Type) < 0) 1646 return false; 1647 return true; 1648 } 1649 1650 } // namespace python 1651 } // namespace protobuf 1652 } // namespace google 1653