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
- }
|