| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085 | // Protocol Buffers - Google's data interchange format// Copyright 2008 Google Inc.  All rights reserved.// https://developers.google.com/protocol-buffers///// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met:////     * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.//     * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following disclaimer// in the documentation and/or other materials provided with the// distribution.//     * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived from// this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include "def.h"#include <php.h>// This is not self-contained: it must be after other Zend includes.#include <Zend/zend_exceptions.h>#include "names.h"#include "php-upb.h"#include "protobuf.h"static void CheckUpbStatus(const upb_status* status, const char* msg) {  if (!upb_ok(status)) {    zend_error(E_ERROR, "%s: %s\n", msg, upb_status_errmsg(status));  }}static void FieldDescriptor_FromFieldDef(zval *val, const upb_fielddef *f);// We use this for objects that should not be created directly from PHP.static zend_object *CreateHandler_ReturnNull(zend_class_entry *class_type) {  return NULL;  // Nobody should call this.}// -----------------------------------------------------------------------------// EnumValueDescriptor// -----------------------------------------------------------------------------typedef struct {  zend_object std;  const char *name;  int32_t number;} EnumValueDescriptor;zend_class_entry *EnumValueDescriptor_class_entry;static zend_object_handlers EnumValueDescriptor_object_handlers;/* * EnumValueDescriptor_Make() * * Function to create an EnumValueDescriptor object from C. */static void EnumValueDescriptor_Make(zval *val, const char *name,                                     int32_t number) {  EnumValueDescriptor *intern = emalloc(sizeof(EnumValueDescriptor));  zend_object_std_init(&intern->std, EnumValueDescriptor_class_entry);  intern->std.handlers = &EnumValueDescriptor_object_handlers;  intern->name = name;  intern->number = number;  // Skip object_properties_init(), we don't allow derived classes.  ZVAL_OBJ(val, &intern->std);}/* * EnumValueDescriptor::getName() * * Returns the name for this enum value. */PHP_METHOD(EnumValueDescriptor, getName) {  EnumValueDescriptor *intern = (EnumValueDescriptor*)Z_OBJ_P(getThis());  RETURN_STRING(intern->name);}/* * EnumValueDescriptor::getNumber() * * Returns the number for this enum value. */PHP_METHOD(EnumValueDescriptor, getNumber) {  EnumValueDescriptor *intern = (EnumValueDescriptor*)Z_OBJ_P(getThis());  RETURN_LONG(intern->number);}static zend_function_entry EnumValueDescriptor_methods[] = {  PHP_ME(EnumValueDescriptor, getName, NULL, ZEND_ACC_PUBLIC)  PHP_ME(EnumValueDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC)  ZEND_FE_END};// -----------------------------------------------------------------------------// EnumDescriptor// -----------------------------------------------------------------------------typedef struct {  zend_object std;  const upb_enumdef *enumdef;} EnumDescriptor;zend_class_entry *EnumDescriptor_class_entry;static zend_object_handlers EnumDescriptor_object_handlers;void EnumDescriptor_FromClassEntry(zval *val, zend_class_entry *ce) {  // To differentiate enums from classes, we pointer-tag the class entry.  void* key = (void*)((uintptr_t)ce | 1);  PBPHP_ASSERT(key != ce);  if (ce == NULL) {    ZVAL_NULL(val);    return;  }  if (!ObjCache_Get(key, val)) {    const upb_enumdef *e = NameMap_GetEnum(ce);    if (!e) {      ZVAL_NULL(val);      return;    }    EnumDescriptor* ret = emalloc(sizeof(EnumDescriptor));    zend_object_std_init(&ret->std, EnumDescriptor_class_entry);    ret->std.handlers = &EnumDescriptor_object_handlers;    ret->enumdef = e;    ObjCache_Add(key, &ret->std);    // Prevent this from ever being collected (within a request).    GC_ADDREF(&ret->std);    ZVAL_OBJ(val, &ret->std);  }}void EnumDescriptor_FromEnumDef(zval *val, const upb_enumdef *m) {  if (!m) {    ZVAL_NULL(val);  } else {    char *classname =        GetPhpClassname(upb_enumdef_file(m), upb_enumdef_fullname(m));    zend_string *str = zend_string_init(classname, strlen(classname), 0);    zend_class_entry *ce = zend_lookup_class(str);  // May autoload the class.    zend_string_release (str);    if (!ce) {      zend_error(E_ERROR, "Couldn't load generated class %s", classname);    }    free(classname);    EnumDescriptor_FromClassEntry(val, ce);  }}/* * EnumDescriptor::getValue() * * Returns an EnumValueDescriptor for this index. Note: we are not looking * up by numeric enum value, but by the index in the list of enum values. */PHP_METHOD(EnumDescriptor, getValue) {  EnumDescriptor *intern = (EnumDescriptor*)Z_OBJ_P(getThis());  zend_long index;  zval ret;  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==      FAILURE) {    zend_error(E_USER_ERROR, "Expect integer for index.\n");    return;  }  int field_num = upb_enumdef_numvals(intern->enumdef);  if (index < 0 || index >= field_num) {    zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);    return;  }  upb_enum_iter iter;  int i;  for(upb_enum_begin(&iter, intern->enumdef), i = 0;      !upb_enum_done(&iter) && i < index;      upb_enum_next(&iter), i++);  EnumValueDescriptor_Make(&ret, upb_enum_iter_name(&iter),                           upb_enum_iter_number(&iter));  RETURN_ZVAL(&ret, 0, 1);}/* * EnumDescriptor::getValueCount() * * Returns the number of values in this enum. */PHP_METHOD(EnumDescriptor, getValueCount) {  EnumDescriptor *intern = (EnumDescriptor*)Z_OBJ_P(getThis());  RETURN_LONG(upb_enumdef_numvals(intern->enumdef));}/* * EnumDescriptor::getPublicDescriptor() * * Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not * have two separate EnumDescriptor classes. We use a single class for both * the public and private descriptor. */PHP_METHOD(EnumDescriptor, getPublicDescriptor) {  RETURN_ZVAL(getThis(), 1, 0);}static zend_function_entry EnumDescriptor_methods[] = {  PHP_ME(EnumDescriptor, getPublicDescriptor, NULL, ZEND_ACC_PUBLIC)  PHP_ME(EnumDescriptor, getValueCount, NULL, ZEND_ACC_PUBLIC)  PHP_ME(EnumDescriptor, getValue, NULL, ZEND_ACC_PUBLIC)  ZEND_FE_END};// -----------------------------------------------------------------------------// Oneof// -----------------------------------------------------------------------------typedef struct {  zend_object std;  const upb_oneofdef *oneofdef;} OneofDescriptor;zend_class_entry *OneofDescriptor_class_entry;static zend_object_handlers OneofDescriptor_object_handlers;static void OneofDescriptor_FromOneofDef(zval *val, const upb_oneofdef *o) {  if (o == NULL) {    ZVAL_NULL(val);    return;  }  if (!ObjCache_Get(o, val)) {    OneofDescriptor* ret = emalloc(sizeof(OneofDescriptor));    zend_object_std_init(&ret->std, OneofDescriptor_class_entry);    ret->std.handlers = &OneofDescriptor_object_handlers;    ret->oneofdef = o;    ObjCache_Add(o, &ret->std);    // Prevent this from ever being collected (within a request).    GC_ADDREF(&ret->std);    ZVAL_OBJ(val, &ret->std);  }}/* * OneofDescriptor::getName() * * Returns the name of this oneof. */PHP_METHOD(OneofDescriptor, getName) {  OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis());  RETURN_STRING(upb_oneofdef_name(intern->oneofdef));}/* * OneofDescriptor::getField() * * Returns a field from this oneof. The given index must be in the range *   [0, getFieldCount() - 1]. */PHP_METHOD(OneofDescriptor, getField) {  OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis());  zend_long index;  zval ret;  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==      FAILURE) {    zend_error(E_USER_ERROR, "Expect integer for index.\n");    return;  }  int field_num = upb_oneofdef_numfields(intern->oneofdef);  if (index < 0 || index >= field_num) {    zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);    return;  }  upb_oneof_iter iter;  int i;  for(upb_oneof_begin(&iter, intern->oneofdef), i = 0;      !upb_oneof_done(&iter) && i < index;      upb_oneof_next(&iter), i++);  const upb_fielddef *field = upb_oneof_iter_field(&iter);  FieldDescriptor_FromFieldDef(&ret, field);  RETURN_ZVAL(&ret, 1, 0);}/* * OneofDescriptor::getFieldCount() * * Returns the number of fields in this oneof. */PHP_METHOD(OneofDescriptor, getFieldCount) {  OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis());  RETURN_LONG(upb_oneofdef_numfields(intern->oneofdef));}static zend_function_entry OneofDescriptor_methods[] = {  PHP_ME(OneofDescriptor, getName,  NULL, ZEND_ACC_PUBLIC)  PHP_ME(OneofDescriptor, getField, NULL, ZEND_ACC_PUBLIC)  PHP_ME(OneofDescriptor, getFieldCount, NULL, ZEND_ACC_PUBLIC)  ZEND_FE_END};// -----------------------------------------------------------------------------// FieldDescriptor// -----------------------------------------------------------------------------typedef struct {  zend_object std;  const upb_fielddef *fielddef;} FieldDescriptor;zend_class_entry *FieldDescriptor_class_entry;static zend_object_handlers FieldDescriptor_object_handlers;static void FieldDescriptor_FromFieldDef(zval *val, const upb_fielddef *f) {  if (f == NULL) {    ZVAL_NULL(val);    return;  }  if (!ObjCache_Get(f, val)) {    FieldDescriptor* ret = emalloc(sizeof(FieldDescriptor));    zend_object_std_init(&ret->std, FieldDescriptor_class_entry);    ret->std.handlers = &FieldDescriptor_object_handlers;    ret->fielddef = f;    ObjCache_Add(f, &ret->std);    // Prevent this from ever being collected (within a request).    GC_ADDREF(&ret->std);    ZVAL_OBJ(val, &ret->std);  }}upb_fieldtype_t to_fieldtype(upb_descriptortype_t type) {  switch (type) {#define CASE(descriptor_type, type)           \  case UPB_DESCRIPTOR_TYPE_##descriptor_type: \    return UPB_TYPE_##type;  CASE(FLOAT,    FLOAT);  CASE(DOUBLE,   DOUBLE);  CASE(BOOL,     BOOL);  CASE(STRING,   STRING);  CASE(BYTES,    BYTES);  CASE(MESSAGE,  MESSAGE);  CASE(GROUP,    MESSAGE);  CASE(ENUM,     ENUM);  CASE(INT32,    INT32);  CASE(INT64,    INT64);  CASE(UINT32,   UINT32);  CASE(UINT64,   UINT64);  CASE(SINT32,   INT32);  CASE(SINT64,   INT64);  CASE(FIXED32,  UINT32);  CASE(FIXED64,  UINT64);  CASE(SFIXED32, INT32);  CASE(SFIXED64, INT64);#undef CONVERT  }  zend_error(E_ERROR, "Unknown field type.");  return 0;}/* * FieldDescriptor::getName() * * Returns the name of this field. */PHP_METHOD(FieldDescriptor, getName) {  FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());  RETURN_STRING(upb_fielddef_name(intern->fielddef));}/* * FieldDescriptor::getNumber() * * Returns the number of this field. */PHP_METHOD(FieldDescriptor, getNumber) {  FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());  RETURN_LONG(upb_fielddef_number(intern->fielddef));}/* * FieldDescriptor::getLabel() * * Returns the label of this field as an integer. */PHP_METHOD(FieldDescriptor, getLabel) {  FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());  RETURN_LONG(upb_fielddef_label(intern->fielddef));}/* * FieldDescriptor::getType() * * Returns the type of this field as an integer. */PHP_METHOD(FieldDescriptor, getType) {  FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());  RETURN_LONG(upb_fielddef_descriptortype(intern->fielddef));}/* * FieldDescriptor::isMap() * * Returns true if this field is a map. */PHP_METHOD(FieldDescriptor, isMap) {  FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());  RETURN_BOOL(upb_fielddef_ismap(intern->fielddef));}/* * FieldDescriptor::getEnumType() * * Returns the EnumDescriptor for this field, which must be an enum. */PHP_METHOD(FieldDescriptor, getEnumType) {  FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());  const upb_enumdef *e = upb_fielddef_enumsubdef(intern->fielddef);  zval ret;  if (!e) {    zend_throw_exception_ex(NULL, 0,                            "Cannot get enum type for non-enum field '%s'",                            upb_fielddef_name(intern->fielddef));    return;  }  EnumDescriptor_FromEnumDef(&ret, e);  RETURN_ZVAL(&ret, 1, 0);}/* * FieldDescriptor::getMessageType() * * Returns the Descriptor for this field, which must be a message. */PHP_METHOD(FieldDescriptor, getMessageType) {  FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());  Descriptor* desc = Descriptor_GetFromFieldDef(intern->fielddef);  zval ret;  if (!desc) {    zend_throw_exception_ex(        NULL, 0, "Cannot get message type for non-message field '%s'",        upb_fielddef_name(intern->fielddef));    return;  }  ZVAL_OBJ(&ret, &desc->std);  RETURN_ZVAL(&ret, 1, 0);}static zend_function_entry FieldDescriptor_methods[] = {  PHP_ME(FieldDescriptor, getName,   NULL, ZEND_ACC_PUBLIC)  PHP_ME(FieldDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC)  PHP_ME(FieldDescriptor, getLabel,  NULL, ZEND_ACC_PUBLIC)  PHP_ME(FieldDescriptor, getType,   NULL, ZEND_ACC_PUBLIC)  PHP_ME(FieldDescriptor, isMap,     NULL, ZEND_ACC_PUBLIC)  PHP_ME(FieldDescriptor, getEnumType, NULL, ZEND_ACC_PUBLIC)  PHP_ME(FieldDescriptor, getMessageType, NULL, ZEND_ACC_PUBLIC)  ZEND_FE_END};// -----------------------------------------------------------------------------// Descriptor// -----------------------------------------------------------------------------zend_class_entry *Descriptor_class_entry;static zend_object_handlers Descriptor_object_handlers;static void Descriptor_destructor(zend_object* obj) {  // We don't really need to do anything here, we don't allow this to be  // collected before the end of the request.}// C Functions from def.h //////////////////////////////////////////////////////// These are documented in the header file.void Descriptor_FromClassEntry(zval *val, zend_class_entry *ce) {  if (ce == NULL) {    ZVAL_NULL(val);    return;  }  if (!ObjCache_Get(ce, val)) {    const upb_msgdef *msgdef = NameMap_GetMessage(ce);    if (!msgdef) {      ZVAL_NULL(val);      return;    }    Descriptor* ret = emalloc(sizeof(Descriptor));    zend_object_std_init(&ret->std, Descriptor_class_entry);    ret->std.handlers = &Descriptor_object_handlers;    ret->class_entry = ce;    ret->msgdef = msgdef;    ObjCache_Add(ce, &ret->std);    // Prevent this from ever being collected (within a request).    GC_ADDREF(&ret->std);    ZVAL_OBJ(val, &ret->std);  }}Descriptor* Descriptor_GetFromClassEntry(zend_class_entry *ce) {  zval desc;  Descriptor_FromClassEntry(&desc, ce);  if (Z_TYPE_P(&desc) == IS_NULL) {    return NULL;  } else {    return (Descriptor*)Z_OBJ_P(&desc);  }}Descriptor* Descriptor_GetFromMessageDef(const upb_msgdef *m) {  if (m) {    if (upb_msgdef_mapentry(m)) {      // A bit of a hack, since map entries don't have classes.      Descriptor* ret = emalloc(sizeof(Descriptor));      zend_object_std_init(&ret->std, Descriptor_class_entry);      ret->std.handlers = &Descriptor_object_handlers;      ret->class_entry = NULL;      ret->msgdef = m;      // Prevent this from ever being collected (within a request).      GC_ADDREF(&ret->std);      return ret;    }    char *classname =        GetPhpClassname(upb_msgdef_file(m), upb_msgdef_fullname(m));    zend_string *str = zend_string_init(classname, strlen(classname), 0);    zend_class_entry *ce = zend_lookup_class(str);  // May autoload the class.    zend_string_release (str);    if (!ce) {      zend_error(E_ERROR, "Couldn't load generated class %s", classname);    }    free(classname);    return Descriptor_GetFromClassEntry(ce);  } else {    return NULL;  }}Descriptor* Descriptor_GetFromFieldDef(const upb_fielddef *f) {  return Descriptor_GetFromMessageDef(upb_fielddef_msgsubdef(f));}/* * Descriptor::getPublicDescriptor() * * Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not * have two separate EnumDescriptor classes. We use a single class for both * the public and private descriptor. */PHP_METHOD(Descriptor, getPublicDescriptor) {  RETURN_ZVAL(getThis(), 1, 0);}/* * Descriptor::getFullName() * * Returns the full name for this message type. */PHP_METHOD(Descriptor, getFullName) {  Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());  RETURN_STRING(upb_msgdef_fullname(intern->msgdef));}/* * Descriptor::getField() * * Returns a FieldDescriptor for the given index, which must be in the range * [0, getFieldCount()-1]. */PHP_METHOD(Descriptor, getField) {  Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());  int count = upb_msgdef_numfields(intern->msgdef);  zval ret;  zend_long index;  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==      FAILURE) {    zend_error(E_USER_ERROR, "Expect integer for index.\n");    return;  }  if (index < 0 || index >= count) {    zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);    return;  }  upb_msg_field_iter iter;  int i;  for(upb_msg_field_begin(&iter, intern->msgdef), i = 0;      !upb_msg_field_done(&iter) && i < index;      upb_msg_field_next(&iter), i++);  const upb_fielddef *field = upb_msg_iter_field(&iter);  FieldDescriptor_FromFieldDef(&ret, field);  RETURN_ZVAL(&ret, 1, 0);}/* * Descriptor::getFieldCount() * * Returns the number of fields in this message. */PHP_METHOD(Descriptor, getFieldCount) {  Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());  RETURN_LONG(upb_msgdef_numfields(intern->msgdef));}/* * Descriptor::getOneofDecl() * * Returns a OneofDescriptor for the given index, which must be in the range * [0, getOneofDeclCount()]. */PHP_METHOD(Descriptor, getOneofDecl) {  Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());  zend_long index;  zval ret;  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==      FAILURE) {    zend_error(E_USER_ERROR, "Expect integer for index.\n");    return;  }  int field_num = upb_msgdef_numoneofs(intern->msgdef);  if (index < 0 || index >= field_num) {    zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);    return;  }  upb_msg_oneof_iter iter;  int i;  for(upb_msg_oneof_begin(&iter, intern->msgdef), i = 0;      !upb_msg_oneof_done(&iter) && i < index;      upb_msg_oneof_next(&iter), i++);  const upb_oneofdef *oneof = upb_msg_iter_oneof(&iter);  OneofDescriptor_FromOneofDef(&ret, oneof);  RETURN_ZVAL(&ret, 1, 0);}/* * Descriptor::getOneofDeclCount() * * Returns the number of oneofs in this message. */PHP_METHOD(Descriptor, getOneofDeclCount) {  Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());  RETURN_LONG(upb_msgdef_numoneofs(intern->msgdef));}/* * Descriptor::getClass() * * Returns the name of the PHP class for this message. */PHP_METHOD(Descriptor, getClass) {  Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());  const char* classname = ZSTR_VAL(intern->class_entry->name);  RETURN_STRING(classname);}static zend_function_entry Descriptor_methods[] = {  PHP_ME(Descriptor, getClass, NULL, ZEND_ACC_PUBLIC)  PHP_ME(Descriptor, getFullName, NULL, ZEND_ACC_PUBLIC)  PHP_ME(Descriptor, getField, NULL, ZEND_ACC_PUBLIC)  PHP_ME(Descriptor, getFieldCount, NULL, ZEND_ACC_PUBLIC)  PHP_ME(Descriptor, getOneofDecl, NULL, ZEND_ACC_PUBLIC)  PHP_ME(Descriptor, getOneofDeclCount, NULL, ZEND_ACC_PUBLIC)  PHP_ME(Descriptor, getPublicDescriptor, NULL, ZEND_ACC_PUBLIC)  ZEND_FE_END};// -----------------------------------------------------------------------------// DescriptorPool// -----------------------------------------------------------------------------typedef struct DescriptorPool {  zend_object std;  upb_symtab *symtab;} DescriptorPool;zend_class_entry *DescriptorPool_class_entry;static zend_object_handlers DescriptorPool_object_handlers;static DescriptorPool *GetPool(const zval* this_ptr) {  return (DescriptorPool*)Z_OBJ_P(this_ptr);}/** * Object handler to create an DescriptorPool. */static zend_object* DescriptorPool_create(zend_class_entry *class_type) {  DescriptorPool *intern = emalloc(sizeof(DescriptorPool));  zend_object_std_init(&intern->std, class_type);  intern->std.handlers = &DescriptorPool_object_handlers;  intern->symtab = upb_symtab_new();  // Skip object_properties_init(), we don't allow derived classes.  return &intern->std;}/** * Object handler to free an DescriptorPool. */static void DescriptorPool_destructor(zend_object* obj) {  DescriptorPool* intern = (DescriptorPool*)obj;  if (intern->symtab) {    upb_symtab_free(intern->symtab);  }  intern->symtab = NULL;  zend_object_std_dtor(&intern->std);}void DescriptorPool_CreateWithSymbolTable(zval *zv, upb_symtab *symtab) {  ZVAL_OBJ(zv, DescriptorPool_create(DescriptorPool_class_entry));  if (symtab) {    DescriptorPool *intern = GetPool(zv);    upb_symtab_free(intern->symtab);    intern->symtab = symtab;  }}upb_symtab *DescriptorPool_Steal(zval *zv) {  DescriptorPool *intern = GetPool(zv);  upb_symtab *ret = intern->symtab;  intern->symtab = NULL;  return ret;}upb_symtab *DescriptorPool_GetSymbolTable() {  DescriptorPool *intern = GetPool(get_generated_pool());  return intern->symtab;}/* * DescriptorPool::getGeneratedPool() * * Returns the generated DescriptorPool. */PHP_METHOD(DescriptorPool, getGeneratedPool) {  zval ret;  ZVAL_COPY(&ret, get_generated_pool());  RETURN_ZVAL(&ret, 0, 1);}/* * DescriptorPool::getDescriptorByClassName() * * Returns a Descriptor object for the given PHP class name. */PHP_METHOD(DescriptorPool, getDescriptorByClassName) {  char *classname = NULL;  zend_long classname_len;  zend_class_entry *ce;  zend_string *str;  zval ret;  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname,                            &classname_len) == FAILURE) {    return;  }  str = zend_string_init(classname, strlen(classname), 0);  ce = zend_lookup_class(str);  // May autoload the class.  zend_string_release (str);  if (!ce) {    RETURN_NULL();  }  Descriptor_FromClassEntry(&ret, ce);  RETURN_ZVAL(&ret, 1, 0);}/* * DescriptorPool::getEnumDescriptorByClassName() * * Returns a EnumDescriptor object for the given PHP class name. */PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) {  char *classname = NULL;  zend_long classname_len;  zend_class_entry *ce;  zend_string *str;  zval ret;  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname,                            &classname_len) == FAILURE) {    return;  }  str = zend_string_init(classname, strlen(classname), 0);  ce = zend_lookup_class(str);  // May autoload the class.  zend_string_release (str);  if (!ce) {    RETURN_NULL();  }  EnumDescriptor_FromClassEntry(&ret, ce);  RETURN_ZVAL(&ret, 1, 0);}/* * DescriptorPool::getEnumDescriptorByProtoName() * * Returns a Descriptor object for the given protobuf message name. */PHP_METHOD(DescriptorPool, getDescriptorByProtoName) {  DescriptorPool *intern = GetPool(getThis());  char *protoname = NULL;  zend_long protoname_len;  const upb_msgdef *m;  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &protoname,                            &protoname_len) == FAILURE) {    return;  }  if (*protoname == '.') protoname++;  m = upb_symtab_lookupmsg(intern->symtab, protoname);  if (m) {    zval ret;    ZVAL_OBJ(&ret, &Descriptor_GetFromMessageDef(m)->std);    RETURN_ZVAL(&ret, 1, 0);  } else {    RETURN_NULL();  }}/* * depends_on_descriptor() * * Returns true if this FileDescriptorProto depends on descriptor.proto. */bool depends_on_descriptor(const google_protobuf_FileDescriptorProto* file) {  const upb_strview *deps;  upb_strview name = upb_strview_makez("google/protobuf/descriptor.proto");  size_t i, n;  deps = google_protobuf_FileDescriptorProto_dependency(file, &n);  for (i = 0; i < n; i++) {    if (upb_strview_eql(deps[i], name)) {      return true;    }  }  return false;}/* * add_name_mappings() * * Adds the messages and enums in this file to the NameMap. */static void add_name_mappings(const upb_filedef *file) {  size_t i;  for (i = 0; i < upb_filedef_msgcount(file); i++) {    NameMap_AddMessage(upb_filedef_msg(file, i));  }  for (i = 0; i < upb_filedef_enumcount(file); i++) {    NameMap_AddEnum(upb_filedef_enum(file, i));  }}/* * add_name_mappings() * * Adds the given descriptor data to this DescriptorPool. */static void add_descriptor(DescriptorPool *pool, const char *data,                           int data_len, upb_arena *arena) {  size_t i, n;  google_protobuf_FileDescriptorSet *set;  const google_protobuf_FileDescriptorProto* const* files;  set = google_protobuf_FileDescriptorSet_parse(data, data_len, arena);  if (!set) {    zend_error(E_ERROR, "Failed to parse binary descriptor\n");    return;  }  files = google_protobuf_FileDescriptorSet_file(set, &n);  for (i = 0; i < n; i++) {    const google_protobuf_FileDescriptorProto* file = files[i];    upb_strview name = google_protobuf_FileDescriptorProto_name(file);    upb_status status;    const upb_filedef *file_def;    upb_status_clear(&status);    if (upb_symtab_lookupfile2(pool->symtab, name.data, name.size)) {      // Already added.      continue;    }    // The PHP code generator currently special-cases descriptor.proto.  It    // doesn't add it as a dependency even if the proto file actually does    // depend on it.    if (depends_on_descriptor(file)) {      google_protobuf_FileDescriptorProto_getmsgdef(pool->symtab);    }    file_def = upb_symtab_addfile(pool->symtab, file, &status);    CheckUpbStatus(&status, "Unable to load descriptor");    add_name_mappings(file_def);  }}/* * DescriptorPool::internalAddGeneratedFile() * * Adds the given descriptor data to this DescriptorPool. */PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {  DescriptorPool *intern = GetPool(getThis());  char *data = NULL;  zend_long data_len;  zend_bool use_nested_submsg = false;  upb_arena *arena;  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &data, &data_len,                            &use_nested_submsg) != SUCCESS) {    return;  }  arena = upb_arena_new();  add_descriptor(intern, data, data_len, arena);  upb_arena_free(arena);}static zend_function_entry DescriptorPool_methods[] = {  PHP_ME(DescriptorPool, getGeneratedPool, NULL,         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)  PHP_ME(DescriptorPool, getDescriptorByClassName, NULL, ZEND_ACC_PUBLIC)  PHP_ME(DescriptorPool, getDescriptorByProtoName, NULL, ZEND_ACC_PUBLIC)  PHP_ME(DescriptorPool, getEnumDescriptorByClassName, NULL, ZEND_ACC_PUBLIC)  PHP_ME(DescriptorPool, internalAddGeneratedFile, NULL, ZEND_ACC_PUBLIC)  ZEND_FE_END};// -----------------------------------------------------------------------------// GPBType// -----------------------------------------------------------------------------zend_class_entry* gpb_type_type;static zend_function_entry gpb_type_methods[] = {  ZEND_FE_END};// -----------------------------------------------------------------------------// Module Init// -----------------------------------------------------------------------------void Def_ModuleInit() {  zend_class_entry tmp_ce;  zend_object_handlers *h;  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\OneofDescriptor",                   OneofDescriptor_methods);  OneofDescriptor_class_entry = zend_register_internal_class(&tmp_ce);  OneofDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;  OneofDescriptor_class_entry->create_object = CreateHandler_ReturnNull;  h = &OneofDescriptor_object_handlers;  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumValueDescriptor",                   EnumValueDescriptor_methods);  EnumValueDescriptor_class_entry = zend_register_internal_class(&tmp_ce);  EnumValueDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;  EnumValueDescriptor_class_entry->create_object = CreateHandler_ReturnNull;  h = &EnumValueDescriptor_object_handlers;  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumDescriptor",                   EnumDescriptor_methods);  EnumDescriptor_class_entry = zend_register_internal_class(&tmp_ce);  EnumDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;  EnumDescriptor_class_entry->create_object = CreateHandler_ReturnNull;  h = &EnumDescriptor_object_handlers;  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Descriptor",                   Descriptor_methods);  Descriptor_class_entry = zend_register_internal_class(&tmp_ce);  Descriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;  Descriptor_class_entry->create_object = CreateHandler_ReturnNull;  h = &Descriptor_object_handlers;  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));  h->dtor_obj = Descriptor_destructor;  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\FieldDescriptor",                   FieldDescriptor_methods);  FieldDescriptor_class_entry = zend_register_internal_class(&tmp_ce);  FieldDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;  FieldDescriptor_class_entry->create_object = CreateHandler_ReturnNull;  h = &FieldDescriptor_object_handlers;  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));  INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\DescriptorPool",                   DescriptorPool_methods);  DescriptorPool_class_entry = zend_register_internal_class(&tmp_ce);  DescriptorPool_class_entry->ce_flags |= ZEND_ACC_FINAL;  DescriptorPool_class_entry->create_object = DescriptorPool_create;  h = &DescriptorPool_object_handlers;  memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));  h->dtor_obj = DescriptorPool_destructor;  // GPBType.#define STR(str) (str), strlen(str)  zend_class_entry class_type;  INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBType",                   gpb_type_methods);  gpb_type_type = zend_register_internal_class(&class_type);  zend_declare_class_constant_long(gpb_type_type, STR("DOUBLE"), 1);  zend_declare_class_constant_long(gpb_type_type, STR("FLOAT"), 2);  zend_declare_class_constant_long(gpb_type_type, STR("INT64"), 3);  zend_declare_class_constant_long(gpb_type_type, STR("UINT64"), 4);  zend_declare_class_constant_long(gpb_type_type, STR("INT32"), 5);  zend_declare_class_constant_long(gpb_type_type, STR("FIXED64"), 6);  zend_declare_class_constant_long(gpb_type_type, STR("FIXED32"), 7);  zend_declare_class_constant_long(gpb_type_type, STR("BOOL"), 8);  zend_declare_class_constant_long(gpb_type_type, STR("STRING"), 9);  zend_declare_class_constant_long(gpb_type_type, STR("GROUP"), 10);  zend_declare_class_constant_long(gpb_type_type, STR("MESSAGE"), 11);  zend_declare_class_constant_long(gpb_type_type, STR("BYTES"), 12);  zend_declare_class_constant_long(gpb_type_type, STR("UINT32"), 13);  zend_declare_class_constant_long(gpb_type_type, STR("ENUM"), 14);  zend_declare_class_constant_long(gpb_type_type, STR("SFIXED32"), 15);  zend_declare_class_constant_long(gpb_type_type, STR("SFIXED64"), 16);  zend_declare_class_constant_long(gpb_type_type, STR("SINT32"), 17);  zend_declare_class_constant_long(gpb_type_type, STR("SINT64"), 18);#undef STR}
 |