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 73namespace google { 74namespace protobuf { 75namespace python { 76 77struct PyContainer; 78 79typedef int (*CountMethod)(PyContainer* self); 80typedef const void* (*GetByIndexMethod)(PyContainer* self, int index); 81typedef const void* (*GetByNameMethod)(PyContainer* self, const string& name); 82typedef const void* (*GetByCamelcaseNameMethod)(PyContainer* self, 83 const string& name); 84typedef const void* (*GetByNumberMethod)(PyContainer* self, int index); 85typedef PyObject* (*NewObjectFromItemMethod)(const void* descriptor); 86typedef const string& (*GetItemNameMethod)(const void* descriptor); 87typedef const string& (*GetItemCamelcaseNameMethod)(const void* descriptor); 88typedef int (*GetItemNumberMethod)(const void* descriptor); 89typedef int (*GetItemIndexMethod)(const void* descriptor); 90 91struct 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 122struct 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 142struct 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 160namespace 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. 166static 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. 225static 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. 252static 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 257static Py_ssize_t Length(PyContainer* self) { 258 return self->container_def->count_fn(self); 259} 260 261// The DescriptorMapping type. 262 263static 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 275static 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 285static PyMappingMethods MappingMappingMethods = { 286 (lenfunc)Length, // mp_length 287 (binaryfunc)Subscript, // mp_subscript 288 (objobjargproc)AssSubscript, // mp_ass_subscript 289}; 290 291static 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 303static 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 323extern PyTypeObject DescriptorMapping_Type; 324extern 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. 329static 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. 373static 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 419static 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 442static 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 453static 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 471static 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 487static 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 503static 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 529static PyObject* NewContainerIterator(PyContainer* mapping, 530 PyContainerIterator::IterKind kind); 531 532static PyObject* Iter(PyContainer* self) { 533 return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY); 534} 535static PyObject* IterKeys(PyContainer* self, PyObject* args) { 536 return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY); 537} 538static PyObject* IterValues(PyContainer* self, PyObject* args) { 539 return NewContainerIterator(self, PyContainerIterator::KIND_ITERVALUE); 540} 541static PyObject* IterItems(PyContainer* self, PyObject* args) { 542 return NewContainerIterator(self, PyContainerIterator::KIND_ITERITEM); 543} 544 545static 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 556PyTypeObject 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 600static 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. 613int 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. 651static 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. 662static 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. 673static 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 682static 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 692static PyObject* Reversed(PyContainer* self, PyObject* args) { 693 return NewContainerIterator(self, 694 PyContainerIterator::KIND_ITERVALUE_REVERSED); 695} 696 697static 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 705static 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 716PyTypeObject 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 758static 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 770static 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 782static 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 799static 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 813static void Iterator_Dealloc(PyContainerIterator* self) { 814 Py_CLEAR(self->container); 815 Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); 816} 817 818static 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 859static 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 901static 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 920namespace message_descriptor { 921 922typedef const Descriptor* ParentDescriptor; 923 924static ParentDescriptor GetDescriptor(PyContainer* self) { 925 return reinterpret_cast<ParentDescriptor>(self->descriptor); 926} 927 928namespace fields { 929 930typedef const FieldDescriptor* ItemDescriptor; 931 932static int Count(PyContainer* self) { 933 return GetDescriptor(self)->field_count(); 934} 935 936static ItemDescriptor GetByName(PyContainer* self, const string& name) { 937 return GetDescriptor(self)->FindFieldByName(name); 938} 939 940static ItemDescriptor GetByCamelcaseName(PyContainer* self, 941 const string& name) { 942 return GetDescriptor(self)->FindFieldByCamelcaseName(name); 943} 944 945static ItemDescriptor GetByNumber(PyContainer* self, int number) { 946 return GetDescriptor(self)->FindFieldByNumber(number); 947} 948 949static ItemDescriptor GetByIndex(PyContainer* self, int index) { 950 return GetDescriptor(self)->field(index); 951} 952 953static PyObject* NewObjectFromItem(ItemDescriptor item) { 954 return PyFieldDescriptor_FromDescriptor(item); 955} 956 957static const string& GetItemName(ItemDescriptor item) { 958 return item->name(); 959} 960 961static const string& GetItemCamelcaseName(ItemDescriptor item) { 962 return item->camelcase_name(); 963} 964 965static int GetItemNumber(ItemDescriptor item) { 966 return item->number(); 967} 968 969static int GetItemIndex(ItemDescriptor item) { 970 return item->index(); 971} 972 973static 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 989PyObject* NewMessageFieldsByName(ParentDescriptor descriptor) { 990 return descriptor::NewMappingByName(&fields::ContainerDef, descriptor); 991} 992 993PyObject* NewMessageFieldsByCamelcaseName(ParentDescriptor descriptor) { 994 return descriptor::NewMappingByCamelcaseName(&fields::ContainerDef, 995 descriptor); 996} 997 998PyObject* NewMessageFieldsByNumber(ParentDescriptor descriptor) { 999 return descriptor::NewMappingByNumber(&fields::ContainerDef, descriptor); 1000} 1001 1002PyObject* NewMessageFieldsSeq(ParentDescriptor descriptor) { 1003 return descriptor::NewSequence(&fields::ContainerDef, descriptor); 1004} 1005 1006namespace nested_types { 1007 1008typedef const Descriptor* ItemDescriptor; 1009 1010static int Count(PyContainer* self) { 1011 return GetDescriptor(self)->nested_type_count(); 1012} 1013 1014static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1015 return GetDescriptor(self)->FindNestedTypeByName(name); 1016} 1017 1018static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1019 return GetDescriptor(self)->nested_type(index); 1020} 1021 1022static PyObject* NewObjectFromItem(ItemDescriptor item) { 1023 return PyMessageDescriptor_FromDescriptor(item); 1024} 1025 1026static const string& GetItemName(ItemDescriptor item) { 1027 return item->name(); 1028} 1029 1030static int GetItemIndex(ItemDescriptor item) { 1031 return item->index(); 1032} 1033 1034static 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 1050PyObject* NewMessageNestedTypesSeq(ParentDescriptor descriptor) { 1051 return descriptor::NewSequence(&nested_types::ContainerDef, descriptor); 1052} 1053 1054PyObject* NewMessageNestedTypesByName(ParentDescriptor descriptor) { 1055 return descriptor::NewMappingByName(&nested_types::ContainerDef, descriptor); 1056} 1057 1058namespace enums { 1059 1060typedef const EnumDescriptor* ItemDescriptor; 1061 1062static int Count(PyContainer* self) { 1063 return GetDescriptor(self)->enum_type_count(); 1064} 1065 1066static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1067 return GetDescriptor(self)->FindEnumTypeByName(name); 1068} 1069 1070static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1071 return GetDescriptor(self)->enum_type(index); 1072} 1073 1074static PyObject* NewObjectFromItem(ItemDescriptor item) { 1075 return PyEnumDescriptor_FromDescriptor(item); 1076} 1077 1078static const string& GetItemName(ItemDescriptor item) { 1079 return item->name(); 1080} 1081 1082static int GetItemIndex(ItemDescriptor item) { 1083 return item->index(); 1084} 1085 1086static 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 1102PyObject* NewMessageEnumsByName(ParentDescriptor descriptor) { 1103 return descriptor::NewMappingByName(&enums::ContainerDef, descriptor); 1104} 1105 1106PyObject* NewMessageEnumsSeq(ParentDescriptor descriptor) { 1107 return descriptor::NewSequence(&enums::ContainerDef, descriptor); 1108} 1109 1110namespace 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 1119typedef const EnumValueDescriptor* ItemDescriptor; 1120 1121static 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 1129static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1130 return GetDescriptor(self)->FindEnumValueByName(name); 1131} 1132 1133static 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 1152static PyObject* NewObjectFromItem(ItemDescriptor item) { 1153 return PyEnumValueDescriptor_FromDescriptor(item); 1154} 1155 1156static const string& GetItemName(ItemDescriptor item) { 1157 return item->name(); 1158} 1159 1160static 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 1176PyObject* NewMessageEnumValuesByName(ParentDescriptor descriptor) { 1177 return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor); 1178} 1179 1180namespace extensions { 1181 1182typedef const FieldDescriptor* ItemDescriptor; 1183 1184static int Count(PyContainer* self) { 1185 return GetDescriptor(self)->extension_count(); 1186} 1187 1188static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1189 return GetDescriptor(self)->FindExtensionByName(name); 1190} 1191 1192static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1193 return GetDescriptor(self)->extension(index); 1194} 1195 1196static PyObject* NewObjectFromItem(ItemDescriptor item) { 1197 return PyFieldDescriptor_FromDescriptor(item); 1198} 1199 1200static const string& GetItemName(ItemDescriptor item) { 1201 return item->name(); 1202} 1203 1204static int GetItemIndex(ItemDescriptor item) { 1205 return item->index(); 1206} 1207 1208static 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 1224PyObject* NewMessageExtensionsByName(ParentDescriptor descriptor) { 1225 return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor); 1226} 1227 1228PyObject* NewMessageExtensionsSeq(ParentDescriptor descriptor) { 1229 return descriptor::NewSequence(&extensions::ContainerDef, descriptor); 1230} 1231 1232namespace oneofs { 1233 1234typedef const OneofDescriptor* ItemDescriptor; 1235 1236static int Count(PyContainer* self) { 1237 return GetDescriptor(self)->oneof_decl_count(); 1238} 1239 1240static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1241 return GetDescriptor(self)->FindOneofByName(name); 1242} 1243 1244static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1245 return GetDescriptor(self)->oneof_decl(index); 1246} 1247 1248static PyObject* NewObjectFromItem(ItemDescriptor item) { 1249 return PyOneofDescriptor_FromDescriptor(item); 1250} 1251 1252static const string& GetItemName(ItemDescriptor item) { 1253 return item->name(); 1254} 1255 1256static int GetItemIndex(ItemDescriptor item) { 1257 return item->index(); 1258} 1259 1260static 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 1276PyObject* NewMessageOneofsByName(ParentDescriptor descriptor) { 1277 return descriptor::NewMappingByName(&oneofs::ContainerDef, descriptor); 1278} 1279 1280PyObject* NewMessageOneofsSeq(ParentDescriptor descriptor) { 1281 return descriptor::NewSequence(&oneofs::ContainerDef, descriptor); 1282} 1283 1284} // namespace message_descriptor 1285 1286namespace enum_descriptor { 1287 1288typedef const EnumDescriptor* ParentDescriptor; 1289 1290static ParentDescriptor GetDescriptor(PyContainer* self) { 1291 return reinterpret_cast<ParentDescriptor>(self->descriptor); 1292} 1293 1294namespace enumvalues { 1295 1296typedef const EnumValueDescriptor* ItemDescriptor; 1297 1298static int Count(PyContainer* self) { 1299 return GetDescriptor(self)->value_count(); 1300} 1301 1302static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1303 return GetDescriptor(self)->value(index); 1304} 1305 1306static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1307 return GetDescriptor(self)->FindValueByName(name); 1308} 1309 1310static ItemDescriptor GetByNumber(PyContainer* self, int number) { 1311 return GetDescriptor(self)->FindValueByNumber(number); 1312} 1313 1314static PyObject* NewObjectFromItem(ItemDescriptor item) { 1315 return PyEnumValueDescriptor_FromDescriptor(item); 1316} 1317 1318static const string& GetItemName(ItemDescriptor item) { 1319 return item->name(); 1320} 1321 1322static int GetItemNumber(ItemDescriptor item) { 1323 return item->number(); 1324} 1325 1326static int GetItemIndex(ItemDescriptor item) { 1327 return item->index(); 1328} 1329 1330static 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 1346PyObject* NewEnumValuesByName(ParentDescriptor descriptor) { 1347 return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor); 1348} 1349 1350PyObject* NewEnumValuesByNumber(ParentDescriptor descriptor) { 1351 return descriptor::NewMappingByNumber(&enumvalues::ContainerDef, descriptor); 1352} 1353 1354PyObject* NewEnumValuesSeq(ParentDescriptor descriptor) { 1355 return descriptor::NewSequence(&enumvalues::ContainerDef, descriptor); 1356} 1357 1358} // namespace enum_descriptor 1359 1360namespace oneof_descriptor { 1361 1362typedef const OneofDescriptor* ParentDescriptor; 1363 1364static ParentDescriptor GetDescriptor(PyContainer* self) { 1365 return reinterpret_cast<ParentDescriptor>(self->descriptor); 1366} 1367 1368namespace fields { 1369 1370typedef const FieldDescriptor* ItemDescriptor; 1371 1372static int Count(PyContainer* self) { 1373 return GetDescriptor(self)->field_count(); 1374} 1375 1376static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1377 return GetDescriptor(self)->field(index); 1378} 1379 1380static PyObject* NewObjectFromItem(ItemDescriptor item) { 1381 return PyFieldDescriptor_FromDescriptor(item); 1382} 1383 1384static int GetItemIndex(ItemDescriptor item) { 1385 return item->index_in_oneof(); 1386} 1387 1388static 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 1404PyObject* NewOneofFieldsSeq(ParentDescriptor descriptor) { 1405 return descriptor::NewSequence(&fields::ContainerDef, descriptor); 1406} 1407 1408} // namespace oneof_descriptor 1409 1410namespace file_descriptor { 1411 1412typedef const FileDescriptor* ParentDescriptor; 1413 1414static ParentDescriptor GetDescriptor(PyContainer* self) { 1415 return reinterpret_cast<ParentDescriptor>(self->descriptor); 1416} 1417 1418namespace messages { 1419 1420typedef const Descriptor* ItemDescriptor; 1421 1422static int Count(PyContainer* self) { 1423 return GetDescriptor(self)->message_type_count(); 1424} 1425 1426static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1427 return GetDescriptor(self)->FindMessageTypeByName(name); 1428} 1429 1430static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1431 return GetDescriptor(self)->message_type(index); 1432} 1433 1434static PyObject* NewObjectFromItem(ItemDescriptor item) { 1435 return PyMessageDescriptor_FromDescriptor(item); 1436} 1437 1438static const string& GetItemName(ItemDescriptor item) { 1439 return item->name(); 1440} 1441 1442static int GetItemIndex(ItemDescriptor item) { 1443 return item->index(); 1444} 1445 1446static 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 1462PyObject* NewFileMessageTypesByName(const FileDescriptor* descriptor) { 1463 return descriptor::NewMappingByName(&messages::ContainerDef, descriptor); 1464} 1465 1466namespace enums { 1467 1468typedef const EnumDescriptor* ItemDescriptor; 1469 1470static int Count(PyContainer* self) { 1471 return GetDescriptor(self)->enum_type_count(); 1472} 1473 1474static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1475 return GetDescriptor(self)->FindEnumTypeByName(name); 1476} 1477 1478static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1479 return GetDescriptor(self)->enum_type(index); 1480} 1481 1482static PyObject* NewObjectFromItem(ItemDescriptor item) { 1483 return PyEnumDescriptor_FromDescriptor(item); 1484} 1485 1486static const string& GetItemName(ItemDescriptor item) { 1487 return item->name(); 1488} 1489 1490static int GetItemIndex(ItemDescriptor item) { 1491 return item->index(); 1492} 1493 1494static 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 1510PyObject* NewFileEnumTypesByName(const FileDescriptor* descriptor) { 1511 return descriptor::NewMappingByName(&enums::ContainerDef, descriptor); 1512} 1513 1514namespace extensions { 1515 1516typedef const FieldDescriptor* ItemDescriptor; 1517 1518static int Count(PyContainer* self) { 1519 return GetDescriptor(self)->extension_count(); 1520} 1521 1522static ItemDescriptor GetByName(PyContainer* self, const string& name) { 1523 return GetDescriptor(self)->FindExtensionByName(name); 1524} 1525 1526static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1527 return GetDescriptor(self)->extension(index); 1528} 1529 1530static PyObject* NewObjectFromItem(ItemDescriptor item) { 1531 return PyFieldDescriptor_FromDescriptor(item); 1532} 1533 1534static const string& GetItemName(ItemDescriptor item) { 1535 return item->name(); 1536} 1537 1538static int GetItemIndex(ItemDescriptor item) { 1539 return item->index(); 1540} 1541 1542static 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 1558PyObject* NewFileExtensionsByName(const FileDescriptor* descriptor) { 1559 return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor); 1560} 1561 1562namespace dependencies { 1563 1564typedef const FileDescriptor* ItemDescriptor; 1565 1566static int Count(PyContainer* self) { 1567 return GetDescriptor(self)->dependency_count(); 1568} 1569 1570static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1571 return GetDescriptor(self)->dependency(index); 1572} 1573 1574static PyObject* NewObjectFromItem(ItemDescriptor item) { 1575 return PyFileDescriptor_FromDescriptor(item); 1576} 1577 1578static 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 1594PyObject* NewFileDependencies(const FileDescriptor* descriptor) { 1595 return descriptor::NewSequence(&dependencies::ContainerDef, descriptor); 1596} 1597 1598namespace public_dependencies { 1599 1600typedef const FileDescriptor* ItemDescriptor; 1601 1602static int Count(PyContainer* self) { 1603 return GetDescriptor(self)->public_dependency_count(); 1604} 1605 1606static ItemDescriptor GetByIndex(PyContainer* self, int index) { 1607 return GetDescriptor(self)->public_dependency(index); 1608} 1609 1610static PyObject* NewObjectFromItem(ItemDescriptor item) { 1611 return PyFileDescriptor_FromDescriptor(item); 1612} 1613 1614static 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 1630PyObject* 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 1640bool 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