diff options
Diffstat (limited to 'php/ext')
-rw-r--r-- | php/ext/google/protobuf/def.c | 57 | ||||
-rw-r--r-- | php/ext/google/protobuf/encode_decode.c | 85 | ||||
-rw-r--r-- | php/ext/google/protobuf/message.c | 1747 | ||||
-rw-r--r-- | php/ext/google/protobuf/protobuf.c | 70 | ||||
-rw-r--r-- | php/ext/google/protobuf/protobuf.h | 527 | ||||
-rw-r--r-- | php/ext/google/protobuf/storage.c | 54 | ||||
-rw-r--r-- | php/ext/google/protobuf/type_check.c | 37 | ||||
-rw-r--r-- | php/ext/google/protobuf/upb.c | 2004 | ||||
-rw-r--r-- | php/ext/google/protobuf/upb.h | 815 |
9 files changed, 4446 insertions, 950 deletions
diff --git a/php/ext/google/protobuf/def.c b/php/ext/google/protobuf/def.c index d07c664c..13f7cdd6 100644 --- a/php/ext/google/protobuf/def.c +++ b/php/ext/google/protobuf/def.c @@ -112,33 +112,6 @@ static void append_map_entry_name(char *result, const char *field_name, check_upb_status(&status, msg); \ } while (0) -// Define PHP class -#define DEFINE_PROTOBUF_INIT_CLASS(CLASSNAME, CAMELNAME, LOWERNAME) \ - PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWERNAME) \ - PHP_PROTO_INIT_CLASS_END - -#define DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME) \ - PHP_PROTO_OBJECT_CREATE_START(NAME, LOWERNAME) \ - LOWERNAME##_init_c_instance(intern TSRMLS_CC); \ - PHP_PROTO_OBJECT_CREATE_END(NAME, LOWERNAME) - -#define DEFINE_PROTOBUF_FREE(CAMELNAME, LOWERNAME) \ - PHP_PROTO_OBJECT_FREE_START(CAMELNAME, LOWERNAME) \ - LOWERNAME##_free_c(intern TSRMLS_CC); \ - PHP_PROTO_OBJECT_FREE_END - -#define DEFINE_PROTOBUF_DTOR(CAMELNAME, LOWERNAME) \ - PHP_PROTO_OBJECT_DTOR_START(CAMELNAME, LOWERNAME) \ - PHP_PROTO_OBJECT_DTOR_END - -#define DEFINE_CLASS(NAME, LOWERNAME, string_name) \ - zend_class_entry *LOWERNAME##_type; \ - zend_object_handlers *LOWERNAME##_handlers; \ - DEFINE_PROTOBUF_FREE(NAME, LOWERNAME) \ - DEFINE_PROTOBUF_DTOR(NAME, LOWERNAME) \ - DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME) \ - DEFINE_PROTOBUF_INIT_CLASS(string_name, NAME, LOWERNAME) - // ----------------------------------------------------------------------------- // GPBType // ----------------------------------------------------------------------------- @@ -654,7 +627,7 @@ zend_object *internal_generated_pool_php; #endif InternalDescriptorPool *generated_pool; // The actual generated pool -static void init_generated_pool_once(TSRMLS_D) { +void init_generated_pool_once(TSRMLS_D) { if (generated_pool == NULL) { #if PHP_MAJOR_VERSION < 7 MAKE_STD_ZVAL(generated_pool_php); @@ -844,18 +817,11 @@ static void convert_to_class_name_inplace(const char *package, memcpy(classname + i, prefix, prefix_len); } -PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) { - char *data = NULL; - PHP_PROTO_SIZE data_len; +void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len, + InternalDescriptorPool *pool TSRMLS_DC) { upb_filedef **files; size_t i; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) == - FAILURE) { - return; - } - - InternalDescriptorPool *pool = UNBOX(InternalDescriptorPool, getThis()); CHECK_UPB(files = upb_loaddescriptor(data, data_len, &pool, &status), "Parse binary descriptors to internal descriptors failed"); @@ -914,6 +880,8 @@ PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) { desc->klass = PHP_PROTO_CE_UNREF(pce); \ } \ add_ce_obj(desc->klass, desc_php); \ + add_proto_obj(upb_##def_type_lower##_fullname(desc->def_type_lower), \ + desc_php); \ efree(classname); \ break; \ } @@ -940,6 +908,21 @@ PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) { upb_gfree(files); } +PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) { + char *data = NULL; + PHP_PROTO_SIZE data_len; + upb_filedef **files; + size_t i; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) == + FAILURE) { + return; + } + + InternalDescriptorPool *pool = UNBOX(InternalDescriptorPool, getThis()); + internal_add_generated_file(data, data_len, pool TSRMLS_CC); +} + PHP_METHOD(DescriptorPool, getDescriptorByClassName) { DescriptorPool *public_pool = UNBOX(DescriptorPool, getThis()); InternalDescriptorPool *pool = public_pool->intern; diff --git a/php/ext/google/protobuf/encode_decode.c b/php/ext/google/protobuf/encode_decode.c index 89e75d6a..7e2b3ae6 100644 --- a/php/ext/google/protobuf/encode_decode.c +++ b/php/ext/google/protobuf/encode_decode.c @@ -142,6 +142,23 @@ static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) { return hd_ofs; } +typedef size_t (*encodeunknown_handlerfunc)(void* _sink, const void* hd, + const char* ptr, size_t len, + const upb_bufhandle* handle); + +typedef struct { + encodeunknown_handlerfunc handler; +} unknownfields_handlerdata_t; + +// Creates a handlerdata for unknown fields. +static const void *newunknownfieldshandlerdata(upb_handlers* h) { + unknownfields_handlerdata_t* hd = + (unknownfields_handlerdata_t*)malloc(sizeof(unknownfields_handlerdata_t)); + hd->handler = stringsink_string; + upb_handlers_addcleanup(h, hd, free); + return hd; +} + typedef struct { size_t ofs; const upb_msgdef *md; @@ -944,6 +961,24 @@ static void add_handlers_for_oneof_field(upb_handlers *h, upb_handlerattr_uninit(&attr); } +static bool add_unknown_handler(void* closure, const void* hd, const char* buf, + size_t size) { + encodeunknown_handlerfunc handler = + ((unknownfields_handlerdata_t*)hd)->handler; + + MessageHeader* msg = (MessageHeader*)closure; + stringsink* unknown = DEREF(message_data(msg), 0, stringsink*); + if (unknown == NULL) { + DEREF(message_data(msg), 0, stringsink*) = ALLOC(stringsink); + unknown = DEREF(message_data(msg), 0, stringsink*); + stringsink_init(unknown); + } + + handler(unknown, NULL, buf, size, NULL); + + return true; +} + static void add_handlers_for_message(const void* closure, upb_handlers* h) { const upb_msgdef* msgdef = upb_handlers_msgdef(h); @@ -967,6 +1002,10 @@ static void add_handlers_for_message(const void* closure, desc->layout = create_layout(desc->msgdef); } + upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr_sethandlerdata(&attr, newunknownfieldshandlerdata(h)); + upb_handlers_setunknown(h, add_unknown_handler, &attr); + for (upb_msg_field_begin(&i, desc->msgdef); !upb_msg_field_done(&i); upb_msg_field_next(&i)) { @@ -1278,6 +1317,11 @@ static void putrawmsg(MessageHeader* msg, const Descriptor* desc, } } + stringsink* unknown = DEREF(message_data(msg), 0, stringsink*); + if (unknown != NULL) { + upb_sink_putunknown(sink, unknown->ptr, unknown->len); + } + upb_sink_endmsg(sink, &status); } @@ -1445,9 +1489,9 @@ static const upb_handlers* msgdef_json_serialize_handlers( // PHP encode/decode methods // ----------------------------------------------------------------------------- -PHP_METHOD(Message, serializeToString) { +void serialize_to_string(zval* val, zval* return_value TSRMLS_DC) { Descriptor* desc = - UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis()))); + UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(val))); stringsink sink; stringsink_init(&sink); @@ -1461,7 +1505,7 @@ PHP_METHOD(Message, serializeToString) { stackenv_init(&se, "Error occurred during encoding: %s"); encoder = upb_pb_encoder_create(&se.env, serialize_handlers, &sink.sink); - putmsg(getThis(), desc, upb_pb_encoder_input(encoder), 0 TSRMLS_CC); + putmsg(val, desc, upb_pb_encoder_input(encoder), 0 TSRMLS_CC); PHP_PROTO_RETVAL_STRINGL(sink.ptr, sink.len, 1); @@ -1470,6 +1514,26 @@ PHP_METHOD(Message, serializeToString) { } } +PHP_METHOD(Message, serializeToString) { + serialize_to_string(getThis(), return_value TSRMLS_CC); +} + +void merge_from_string(const char* data, int data_len, const Descriptor* desc, + MessageHeader* msg) { + const upb_pbdecodermethod* method = msgdef_decodermethod(desc); + const upb_handlers* h = upb_pbdecodermethod_desthandlers(method); + stackenv se; + upb_sink sink; + upb_pbdecoder* decoder; + stackenv_init(&se, "Error occurred during parsing: %s"); + + upb_sink_reset(&sink, h, msg); + decoder = upb_pbdecoder_create(&se.env, method, &sink); + upb_bufsrc_putbuf(data, data_len, upb_pbdecoder_input(decoder)); + + stackenv_uninit(&se); +} + PHP_METHOD(Message, mergeFromString) { Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis()))); @@ -1483,20 +1547,7 @@ PHP_METHOD(Message, mergeFromString) { return; } - { - const upb_pbdecodermethod* method = msgdef_decodermethod(desc); - const upb_handlers* h = upb_pbdecodermethod_desthandlers(method); - stackenv se; - upb_sink sink; - upb_pbdecoder* decoder; - stackenv_init(&se, "Error occurred during parsing: %s"); - - upb_sink_reset(&sink, h, msg); - decoder = upb_pbdecoder_create(&se.env, method, &sink); - upb_bufsrc_putbuf(data, data_len, upb_pbdecoder_input(decoder)); - - stackenv_uninit(&se); - } + merge_from_string(data, data_len, desc, msg); } PHP_METHOD(Message, serializeToJsonString) { diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c index 519786dd..291f5c24 100644 --- a/php/ext/google/protobuf/message.c +++ b/php/ext/google/protobuf/message.c @@ -29,12 +29,16 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <php.h> +#include <ext/date/php_date.h> #include <stdlib.h> #include "protobuf.h" +#include "utf8.h" -static zend_class_entry* message_type; +zend_class_entry* message_type; zend_object_handlers* message_handlers; +static const char TYPE_URL_PREFIX[] = "type.googleapis.com/"; +static void hex_to_binary(const char* hex, char** binary, int* binary_len); static zend_function_entry message_methods[] = { PHP_ME(Message, clear, NULL, ZEND_ACC_PUBLIC) @@ -77,6 +81,10 @@ static HashTable* message_get_properties(zval* object TSRMLS_DC); // Define object free method. PHP_PROTO_OBJECT_FREE_START(MessageHeader, message) + if (*(void**)intern->data != NULL) { + stringsink_uninit(*(void**)intern->data); + FREE(*(void**)intern->data); + } FREE(intern->data); PHP_PROTO_OBJECT_FREE_END @@ -103,6 +111,20 @@ PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\Message", message_handlers->get_gc = message_get_gc; PHP_PROTO_INIT_CLASS_END +static void message_set_property_internal(zval* object, zval* member, + zval* value TSRMLS_DC) { + const upb_fielddef* field; + + MessageHeader* self = UNBOX(MessageHeader, object); + + field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member)); + if (field == NULL) { + zend_error(E_USER_ERROR, "Unknown field: %s", Z_STRVAL_P(member)); + } + + layout_set(self->descriptor->layout, self, field, value TSRMLS_CC); +} + #if PHP_MAJOR_VERSION < 7 static void message_set_property(zval* object, zval* member, zval* value, php_proto_zend_literal key TSRMLS_DC) { @@ -125,16 +147,42 @@ static void message_set_property(zval* object, zval* member, zval* value, return; } - const upb_fielddef* field; + message_set_property_internal(object, member, value TSRMLS_CC); +} +static zval* message_get_property_internal(zval* object, + zval* member TSRMLS_DC) { MessageHeader* self = UNBOX(MessageHeader, object); + const upb_fielddef* field; + field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member)); + if (field == NULL) { + return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL; + } + + zend_property_info* property_info; +#if PHP_MAJOR_VERSION < 7 + property_info = + zend_get_property_info(Z_OBJCE_P(object), member, true TSRMLS_CC); +#else + property_info = + zend_get_property_info(Z_OBJCE_P(object), Z_STR_P(member), true); +#endif + return layout_get( + self->descriptor->layout, message_data(self), field, + OBJ_PROP(Z_OBJ_P(object), property_info->offset) TSRMLS_CC); +} +static void message_get_oneof_property_internal(zval* object, zval* member, + zval* return_value TSRMLS_DC) { + MessageHeader* self = UNBOX(MessageHeader, object); + const upb_fielddef* field; field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member)); if (field == NULL) { - zend_error(E_USER_ERROR, "Unknown field: %s", Z_STRVAL_P(member)); + return; } - layout_set(self->descriptor->layout, self, field, value TSRMLS_CC); + layout_get(self->descriptor->layout, message_data(self), field, + ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC); } #if PHP_MAJOR_VERSION < 7 @@ -159,27 +207,7 @@ static zval* message_get_property(zval* object, zval* member, int type, return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL; } - MessageHeader* self = UNBOX(MessageHeader, object); - const upb_fielddef* field; - field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member)); - if (field == NULL) { - return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL; - } - - zend_property_info* property_info; -#if PHP_MAJOR_VERSION < 7 - property_info = - zend_get_property_info(Z_OBJCE_P(object), member, true TSRMLS_CC); - return layout_get( - self->descriptor->layout, message_data(self), field, - OBJ_PROP(Z_OBJ_P(object), property_info->offset) TSRMLS_CC); -#else - property_info = - zend_get_property_info(Z_OBJCE_P(object), Z_STR_P(member), true); - return layout_get( - self->descriptor->layout, message_data(self), field, - OBJ_PROP(Z_OBJ_P(object), property_info->offset) TSRMLS_CC); -#endif + return message_get_property_internal(object, member TSRMLS_CC); } #if PHP_MAJOR_VERSION < 7 @@ -298,11 +326,6 @@ PHP_METHOD(Message, readOneof) { const upb_fielddef* field = upb_msgdef_itof(msg->descriptor->msgdef, index); - int property_cache_index = - msg->descriptor->layout->fields[upb_fielddef_index(field)].cache_index; - zval* property_ptr = CACHED_PTR_TO_ZVAL_PTR( - OBJ_PROP(Z_OBJ_P(getThis()), property_cache_index)); - // Unlike singular fields, oneof fields share cached property. So we cannot // let lay_get modify the cached property. Instead, we pass in the return // value directly. @@ -342,3 +365,1667 @@ PHP_METHOD(Message, whichOneof) { msg->descriptor->layout, message_data(msg), oneof TSRMLS_CC); PHP_PROTO_RETURN_STRING(oneof_case_name, 1); } + +// ----------------------------------------------------------------------------- +// Well Known Types Support +// ----------------------------------------------------------------------------- + +#define PHP_PROTO_FIELD_ACCESSORS(UPPER_CLASS, LOWER_CLASS, UPPER_FIELD, \ + LOWER_FIELD) \ + PHP_METHOD(UPPER_CLASS, get##UPPER_FIELD) { \ + zval member; \ + PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1); \ + PHP_PROTO_FAKE_SCOPE_BEGIN(LOWER_CLASS##_type); \ + zval* value = message_get_property_internal(getThis(), &member TSRMLS_CC); \ + PHP_PROTO_FAKE_SCOPE_END; \ + PHP_PROTO_RETVAL_ZVAL(value); \ + } \ + PHP_METHOD(UPPER_CLASS, set##UPPER_FIELD) { \ + zval* value = NULL; \ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == \ + FAILURE) { \ + return; \ + } \ + zval member; \ + PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1); \ + message_set_property_internal(getThis(), &member, value TSRMLS_CC); \ + PHP_PROTO_RETVAL_ZVAL(getThis()); \ + } + +#define PHP_PROTO_ONEOF_FIELD_ACCESSORS(UPPER_CLASS, LOWER_CLASS, UPPER_FIELD, \ + LOWER_FIELD) \ + PHP_METHOD(UPPER_CLASS, get##UPPER_FIELD) { \ + zval member; \ + PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1); \ + PHP_PROTO_FAKE_SCOPE_BEGIN(LOWER_CLASS##_type); \ + message_get_oneof_property_internal(getThis(), &member, \ + return_value TSRMLS_CC); \ + PHP_PROTO_FAKE_SCOPE_END; \ + } \ + PHP_METHOD(UPPER_CLASS, set##UPPER_FIELD) { \ + zval* value = NULL; \ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == \ + FAILURE) { \ + return; \ + } \ + zval member; \ + PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1); \ + message_set_property_internal(getThis(), &member, value TSRMLS_CC); \ + PHP_PROTO_RETVAL_ZVAL(getThis()); \ + } + +#define PHP_PROTO_ONEOF_ACCESSORS(UPPER_CLASS, LOWER_CLASS, UPPER_FIELD, \ + LOWER_FIELD) \ + PHP_METHOD(UPPER_CLASS, get##UPPER_FIELD) { \ + MessageHeader* msg = UNBOX(MessageHeader, getThis()); \ + PHP_PROTO_FAKE_SCOPE_BEGIN(LOWER_CLASS##_type); \ + const upb_oneofdef* oneof = upb_msgdef_ntoo( \ + msg->descriptor->msgdef, LOWER_FIELD, strlen(LOWER_FIELD)); \ + const char* oneof_case_name = layout_get_oneof_case( \ + msg->descriptor->layout, message_data(msg), oneof TSRMLS_CC); \ + PHP_PROTO_FAKE_SCOPE_END; \ + PHP_PROTO_RETURN_STRING(oneof_case_name, 1); \ + } + +// Forward declare file init functions +static void init_file_any(TSRMLS_D); +static void init_file_api(TSRMLS_D); +static void init_file_duration(TSRMLS_D); +static void init_file_field_mask(TSRMLS_D); +static void init_file_empty(TSRMLS_D); +static void init_file_source_context(TSRMLS_D); +static void init_file_struct(TSRMLS_D); +static void init_file_timestamp(TSRMLS_D); +static void init_file_type(TSRMLS_D); +static void init_file_wrappers(TSRMLS_D); + +// Define file init functions +static void init_file_any(TSRMLS_D) { + static bool is_initialized = false; + if (is_initialized) return; + init_generated_pool_once(TSRMLS_C); + const char* generated_file = + "0acd010a19676f6f676c652f70726f746f6275662f616e792e70726f746f" + "120f676f6f676c652e70726f746f62756622260a03416e7912100a087479" + "70655f75726c180120012809120d0a0576616c756518022001280c426f0a" + "13636f6d2e676f6f676c652e70726f746f6275664208416e7950726f746f" + "50015a256769746875622e636f6d2f676f6c616e672f70726f746f627566" + "2f7074797065732f616e79a20203475042aa021e476f6f676c652e50726f" + "746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33"; + char* binary; + int binary_len; + hex_to_binary(generated_file, &binary, &binary_len); + internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC); + FREE(binary); + is_initialized = true; +} + +static void init_file_api(TSRMLS_D) { + static bool is_initialized = false; + if (is_initialized) return; + init_file_source_context(TSRMLS_C); + init_file_type(TSRMLS_C); + init_generated_pool_once(TSRMLS_C); + const char* generated_file = + "0aee050a19676f6f676c652f70726f746f6275662f6170692e70726f746f" + "120f676f6f676c652e70726f746f6275661a24676f6f676c652f70726f74" + "6f6275662f736f757263655f636f6e746578742e70726f746f1a1a676f6f" + "676c652f70726f746f6275662f747970652e70726f746f2281020a034170" + "69120c0a046e616d6518012001280912280a076d6574686f647318022003" + "280b32172e676f6f676c652e70726f746f6275662e4d6574686f6412280a" + "076f7074696f6e7318032003280b32172e676f6f676c652e70726f746f62" + "75662e4f7074696f6e120f0a0776657273696f6e18042001280912360a0e" + "736f757263655f636f6e7465787418052001280b321e2e676f6f676c652e" + "70726f746f6275662e536f75726365436f6e7465787412260a066d697869" + "6e7318062003280b32162e676f6f676c652e70726f746f6275662e4d6978" + "696e12270a0673796e74617818072001280e32172e676f6f676c652e7072" + "6f746f6275662e53796e74617822d5010a064d6574686f64120c0a046e61" + "6d6518012001280912180a10726571756573745f747970655f75726c1802" + "2001280912190a11726571756573745f73747265616d696e671803200128" + "0812190a11726573706f6e73655f747970655f75726c180420012809121a" + "0a12726573706f6e73655f73747265616d696e6718052001280812280a07" + "6f7074696f6e7318062003280b32172e676f6f676c652e70726f746f6275" + "662e4f7074696f6e12270a0673796e74617818072001280e32172e676f6f" + "676c652e70726f746f6275662e53796e74617822230a054d6978696e120c" + "0a046e616d65180120012809120c0a04726f6f7418022001280942750a13" + "636f6d2e676f6f676c652e70726f746f627566420841706950726f746f50" + "015a2b676f6f676c652e676f6c616e672e6f72672f67656e70726f746f2f" + "70726f746f6275662f6170693b617069a20203475042aa021e476f6f676c" + "652e50726f746f6275662e57656c6c4b6e6f776e5479706573620670726f" + "746f33"; + char* binary; + int binary_len; + hex_to_binary(generated_file, &binary, &binary_len); + internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC); + FREE(binary); + is_initialized = true; +} + +static void init_file_duration(TSRMLS_D) { + static bool is_initialized = false; + if (is_initialized) return; + init_generated_pool_once(TSRMLS_C); + const char* generated_file = + "0ae3010a1e676f6f676c652f70726f746f6275662f6475726174696f6e2e" + "70726f746f120f676f6f676c652e70726f746f627566222a0a0844757261" + "74696f6e120f0a077365636f6e6473180120012803120d0a056e616e6f73" + "180220012805427c0a13636f6d2e676f6f676c652e70726f746f62756642" + "0d4475726174696f6e50726f746f50015a2a6769746875622e636f6d2f67" + "6f6c616e672f70726f746f6275662f7074797065732f6475726174696f6e" + "f80101a20203475042aa021e476f6f676c652e50726f746f6275662e5765" + "6c6c4b6e6f776e5479706573620670726f746f33"; + char* binary; + int binary_len; + hex_to_binary(generated_file, &binary, &binary_len); + internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC); + FREE(binary); + is_initialized = true; +} + +static void init_file_field_mask(TSRMLS_D) { + static bool is_initialized = false; + if (is_initialized) return; + init_generated_pool_once(TSRMLS_C); + const char* generated_file = + "0ae3010a20676f6f676c652f70726f746f6275662f6669656c645f6d6173" + "6b2e70726f746f120f676f6f676c652e70726f746f627566221a0a094669" + "656c644d61736b120d0a0570617468731801200328094289010a13636f6d" + "2e676f6f676c652e70726f746f627566420e4669656c644d61736b50726f" + "746f50015a39676f6f676c652e676f6c616e672e6f72672f67656e70726f" + "746f2f70726f746f6275662f6669656c645f6d61736b3b6669656c645f6d" + "61736ba20203475042aa021e476f6f676c652e50726f746f6275662e5765" + "6c6c4b6e6f776e5479706573620670726f746f33"; + char* binary; + int binary_len; + hex_to_binary(generated_file, &binary, &binary_len); + internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC); + FREE(binary); + is_initialized = true; +} + +static void init_file_empty(TSRMLS_D) { + static bool is_initialized = false; + if (is_initialized) return; + init_generated_pool_once(TSRMLS_C); + const char* generated_file = + "0ab7010a1b676f6f676c652f70726f746f6275662f656d7074792e70726f" + "746f120f676f6f676c652e70726f746f62756622070a05456d7074794276" + "0a13636f6d2e676f6f676c652e70726f746f627566420a456d7074795072" + "6f746f50015a276769746875622e636f6d2f676f6c616e672f70726f746f" + "6275662f7074797065732f656d707479f80101a20203475042aa021e476f" + "6f676c652e50726f746f6275662e57656c6c4b6e6f776e54797065736206" + "70726f746f33"; + char* binary; + int binary_len; + hex_to_binary(generated_file, &binary, &binary_len); + internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC); + FREE(binary); + is_initialized = true; +} + +static void init_file_source_context(TSRMLS_D) { + static bool is_initialized = false; + if (is_initialized) return; + init_generated_pool_once(TSRMLS_C); + const char* generated_file = + "0afb010a24676f6f676c652f70726f746f6275662f736f757263655f636f" + "6e746578742e70726f746f120f676f6f676c652e70726f746f6275662222" + "0a0d536f75726365436f6e7465787412110a0966696c655f6e616d651801" + "200128094295010a13636f6d2e676f6f676c652e70726f746f6275664212" + "536f75726365436f6e7465787450726f746f50015a41676f6f676c652e67" + "6f6c616e672e6f72672f67656e70726f746f2f70726f746f6275662f736f" + "757263655f636f6e746578743b736f757263655f636f6e74657874a20203" + "475042aa021e476f6f676c652e50726f746f6275662e57656c6c4b6e6f77" + "6e5479706573620670726f746f33"; + char* binary; + int binary_len; + hex_to_binary(generated_file, &binary, &binary_len); + internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC); + FREE(binary); + is_initialized = true; +} + +static void init_file_struct(TSRMLS_D) { + static bool is_initialized = false; + if (is_initialized) return; + init_generated_pool_once(TSRMLS_C); + const char* generated_file = + "0a81050a1c676f6f676c652f70726f746f6275662f7374727563742e7072" + "6f746f120f676f6f676c652e70726f746f6275662284010a065374727563" + "7412330a066669656c647318012003280b32232e676f6f676c652e70726f" + "746f6275662e5374727563742e4669656c6473456e7472791a450a0b4669" + "656c6473456e747279120b0a036b657918012001280912250a0576616c75" + "6518022001280b32162e676f6f676c652e70726f746f6275662e56616c75" + "653a02380122ea010a0556616c756512300a0a6e756c6c5f76616c756518" + "012001280e321a2e676f6f676c652e70726f746f6275662e4e756c6c5661" + "6c7565480012160a0c6e756d6265725f76616c7565180220012801480012" + "160a0c737472696e675f76616c7565180320012809480012140a0a626f6f" + "6c5f76616c75651804200128084800122f0a0c7374727563745f76616c75" + "6518052001280b32172e676f6f676c652e70726f746f6275662e53747275" + "6374480012300a0a6c6973745f76616c756518062001280b321a2e676f6f" + "676c652e70726f746f6275662e4c69737456616c7565480042060a046b69" + "6e6422330a094c69737456616c756512260a0676616c7565731801200328" + "0b32162e676f6f676c652e70726f746f6275662e56616c75652a1b0a094e" + "756c6c56616c7565120e0a0a4e554c4c5f56414c554510004281010a1363" + "6f6d2e676f6f676c652e70726f746f627566420b53747275637450726f74" + "6f50015a316769746875622e636f6d2f676f6c616e672f70726f746f6275" + "662f7074797065732f7374727563743b7374727563747062f80101a20203" + "475042aa021e476f6f676c652e50726f746f6275662e57656c6c4b6e6f77" + "6e5479706573620670726f746f33"; + char* binary; + int binary_len; + hex_to_binary(generated_file, &binary, &binary_len); + internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC); + FREE(binary); + is_initialized = true; +} + +static void init_file_timestamp(TSRMLS_D) { + static bool is_initialized = false; + if (is_initialized) return; + init_generated_pool_once(TSRMLS_C); + const char* generated_file = + "0ae7010a1f676f6f676c652f70726f746f6275662f74696d657374616d70" + "2e70726f746f120f676f6f676c652e70726f746f627566222b0a0954696d" + "657374616d70120f0a077365636f6e6473180120012803120d0a056e616e" + "6f73180220012805427e0a13636f6d2e676f6f676c652e70726f746f6275" + "66420e54696d657374616d7050726f746f50015a2b6769746875622e636f" + "6d2f676f6c616e672f70726f746f6275662f7074797065732f74696d6573" + "74616d70f80101a20203475042aa021e476f6f676c652e50726f746f6275" + "662e57656c6c4b6e6f776e5479706573620670726f746f33"; + char* binary; + int binary_len; + hex_to_binary(generated_file, &binary, &binary_len); + internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC); + FREE(binary); + is_initialized = true; +} + +static void init_file_type(TSRMLS_D) { + static bool is_initialized = false; + if (is_initialized) return; + init_file_any(TSRMLS_C); + init_file_source_context(TSRMLS_C); + init_generated_pool_once(TSRMLS_C); + const char* generated_file = + "0aba0c0a1a676f6f676c652f70726f746f6275662f747970652e70726f74" + "6f120f676f6f676c652e70726f746f6275661a19676f6f676c652f70726f" + "746f6275662f616e792e70726f746f1a24676f6f676c652f70726f746f62" + "75662f736f757263655f636f6e746578742e70726f746f22d7010a045479" + "7065120c0a046e616d6518012001280912260a066669656c647318022003" + "280b32162e676f6f676c652e70726f746f6275662e4669656c64120e0a06" + "6f6e656f667318032003280912280a076f7074696f6e7318042003280b32" + "172e676f6f676c652e70726f746f6275662e4f7074696f6e12360a0e736f" + "757263655f636f6e7465787418052001280b321e2e676f6f676c652e7072" + "6f746f6275662e536f75726365436f6e7465787412270a0673796e746178" + "18062001280e32172e676f6f676c652e70726f746f6275662e53796e7461" + "7822d5050a054669656c6412290a046b696e6418012001280e321b2e676f" + "6f676c652e70726f746f6275662e4669656c642e4b696e6412370a0b6361" + "7264696e616c69747918022001280e32222e676f6f676c652e70726f746f" + "6275662e4669656c642e43617264696e616c697479120e0a066e756d6265" + "72180320012805120c0a046e616d6518042001280912100a08747970655f" + "75726c18062001280912130a0b6f6e656f665f696e646578180720012805" + "120e0a067061636b656418082001280812280a076f7074696f6e73180920" + "03280b32172e676f6f676c652e70726f746f6275662e4f7074696f6e1211" + "0a096a736f6e5f6e616d65180a2001280912150a0d64656661756c745f76" + "616c7565180b2001280922c8020a044b696e6412100a0c545950455f554e" + "4b4e4f574e1000120f0a0b545950455f444f55424c451001120e0a0a5459" + "50455f464c4f41541002120e0a0a545950455f494e5436341003120f0a0b" + "545950455f55494e5436341004120e0a0a545950455f494e543332100512" + "100a0c545950455f46495845443634100612100a0c545950455f46495845" + "4433321007120d0a09545950455f424f4f4c1008120f0a0b545950455f53" + "5452494e471009120e0a0a545950455f47524f5550100a12100a0c545950" + "455f4d455353414745100b120e0a0a545950455f4259544553100c120f0a" + "0b545950455f55494e543332100d120d0a09545950455f454e554d100e12" + "110a0d545950455f5346495845443332100f12110a0d545950455f534649" + "58454436341010120f0a0b545950455f53494e5433321011120f0a0b5459" + "50455f53494e543634101222740a0b43617264696e616c69747912170a13" + "43415244494e414c4954595f554e4b4e4f574e100012180a144341524449" + "4e414c4954595f4f5054494f4e414c100112180a1443415244494e414c49" + "54595f5245515549524544100212180a1443415244494e414c4954595f52" + "45504541544544100322ce010a04456e756d120c0a046e616d6518012001" + "2809122d0a09656e756d76616c756518022003280b321a2e676f6f676c65" + "2e70726f746f6275662e456e756d56616c756512280a076f7074696f6e73" + "18032003280b32172e676f6f676c652e70726f746f6275662e4f7074696f" + "6e12360a0e736f757263655f636f6e7465787418042001280b321e2e676f" + "6f676c652e70726f746f6275662e536f75726365436f6e7465787412270a" + "0673796e74617818052001280e32172e676f6f676c652e70726f746f6275" + "662e53796e74617822530a09456e756d56616c7565120c0a046e616d6518" + "0120012809120e0a066e756d62657218022001280512280a076f7074696f" + "6e7318032003280b32172e676f6f676c652e70726f746f6275662e4f7074" + "696f6e223b0a064f7074696f6e120c0a046e616d6518012001280912230a" + "0576616c756518022001280b32142e676f6f676c652e70726f746f627566" + "2e416e792a2e0a0653796e74617812110a0d53594e5441585f50524f544f" + "32100012110a0d53594e5441585f50524f544f331001427d0a13636f6d2e" + "676f6f676c652e70726f746f62756642095479706550726f746f50015a2f" + "676f6f676c652e676f6c616e672e6f72672f67656e70726f746f2f70726f" + "746f6275662f70747970653b7074797065f80101a20203475042aa021e47" + "6f6f676c652e50726f746f6275662e57656c6c4b6e6f776e547970657362" + "0670726f746f33"; + char* binary; + int binary_len; + hex_to_binary(generated_file, &binary, &binary_len); + internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC); + FREE(binary); + is_initialized = true; +} + +static void init_file_wrappers(TSRMLS_D) { + static bool is_initialized = false; + if (is_initialized) return; + init_generated_pool_once(TSRMLS_C); + const char* generated_file = + "0abf030a1e676f6f676c652f70726f746f6275662f77726170706572732e" + "70726f746f120f676f6f676c652e70726f746f627566221c0a0b446f7562" + "6c6556616c7565120d0a0576616c7565180120012801221b0a0a466c6f61" + "7456616c7565120d0a0576616c7565180120012802221b0a0a496e743634" + "56616c7565120d0a0576616c7565180120012803221c0a0b55496e743634" + "56616c7565120d0a0576616c7565180120012804221b0a0a496e74333256" + "616c7565120d0a0576616c7565180120012805221c0a0b55496e74333256" + "616c7565120d0a0576616c756518012001280d221a0a09426f6f6c56616c" + "7565120d0a0576616c7565180120012808221c0a0b537472696e6756616c" + "7565120d0a0576616c7565180120012809221b0a0a427974657356616c75" + "65120d0a0576616c756518012001280c427c0a13636f6d2e676f6f676c65" + "2e70726f746f627566420d577261707065727350726f746f50015a2a6769" + "746875622e636f6d2f676f6c616e672f70726f746f6275662f7074797065" + "732f7772617070657273f80101a20203475042aa021e476f6f676c652e50" + "726f746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33"; + char* binary; + int binary_len; + hex_to_binary(generated_file, &binary, &binary_len); + internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC); + FREE(binary); + is_initialized = true; +} + +// ----------------------------------------------------------------------------- +// Define enum +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// Field_Cardinality +// ----------------------------------------------------------------------------- + +static zend_function_entry field_cardinality_methods[] = { + {NULL, NULL, NULL} +}; + +zend_class_entry* field_cardinality_type; + +// Init class entry. +PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field_Cardinality", + Field_Cardinality, field_cardinality) + zend_declare_class_constant_long(field_cardinality_type, + "CARDINALITY_UNKNOWN", 19, 0 TSRMLS_CC); + zend_declare_class_constant_long(field_cardinality_type, + "CARDINALITY_OPTIONAL", 20, 1 TSRMLS_CC); + zend_declare_class_constant_long(field_cardinality_type, + "CARDINALITY_REQUIRED", 20, 2 TSRMLS_CC); + zend_declare_class_constant_long(field_cardinality_type, + "CARDINALITY_REPEATED", 20, 3 TSRMLS_CC); +PHP_PROTO_INIT_ENUMCLASS_END + +// ----------------------------------------------------------------------------- +// Field_Kind +// ----------------------------------------------------------------------------- + +static zend_function_entry field_kind_methods[] = { + {NULL, NULL, NULL} +}; + +zend_class_entry* field_kind_type; + +// Init class entry. +PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field_Kind", + Field_Kind, field_kind) + zend_declare_class_constant_long(field_kind_type, + "TYPE_UNKNOWN", 12, 0 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_DOUBLE", 11, 1 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_FLOAT", 10, 2 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_INT64", 10, 3 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_UINT64", 11, 4 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_INT32", 10, 5 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_FIXED64", 12, 6 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_FIXED32", 12, 7 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_BOOL", 9, 8 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_STRING", 11, 9 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_GROUP", 10, 10 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_MESSAGE", 12, 11 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_BYTES", 10, 12 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_UINT32", 11, 13 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_ENUM", 9, 14 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_SFIXED32", 13, 15 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_SFIXED64", 13, 16 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_SINT32", 11, 17 TSRMLS_CC); + zend_declare_class_constant_long(field_kind_type, + "TYPE_SINT64", 11, 18 TSRMLS_CC); +PHP_PROTO_INIT_ENUMCLASS_END + +// ----------------------------------------------------------------------------- +// NullValue +// ----------------------------------------------------------------------------- + +static zend_function_entry null_value_methods[] = { + {NULL, NULL, NULL} +}; + +zend_class_entry* null_value_type; + +// Init class entry. +PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\NullValue", + NullValue, null_value) + zend_declare_class_constant_long(null_value_type, + "NULL_VALUE", 10, 0 TSRMLS_CC); +PHP_PROTO_INIT_ENUMCLASS_END + +// ----------------------------------------------------------------------------- +// Syntax +// ----------------------------------------------------------------------------- + +static zend_function_entry syntax_methods[] = { + {NULL, NULL, NULL} +}; + +zend_class_entry* syntax_type; + +// Init class entry. +PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Syntax", + Syntax, syntax) + zend_declare_class_constant_long(syntax_type, + "SYNTAX_PROTO2", 13, 0 TSRMLS_CC); + zend_declare_class_constant_long(syntax_type, + "SYNTAX_PROTO3", 13, 1 TSRMLS_CC); +PHP_PROTO_INIT_ENUMCLASS_END + + + +// ----------------------------------------------------------------------------- +// Define message +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// Any +// ----------------------------------------------------------------------------- + +static zend_function_entry any_methods[] = { + PHP_ME(Any, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Any, getTypeUrl, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Any, setTypeUrl, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Any, getValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Any, setValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Any, pack, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Any, unpack, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Any, is, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* any_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Any", Any, any) + zend_class_implements(any_type TSRMLS_CC, 1, message_type); + zend_declare_property_string(any_type, "type_url", strlen("type_url"), + "" ,ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_string(any_type, "value", strlen("value"), + "" ,ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +static void hex_to_binary(const char* hex, char** binary, int* binary_len) { + int i; + int hex_len = strlen(hex); + *binary_len = hex_len / 2; + *binary = ALLOC_N(char, *binary_len); + for (i = 0; i < *binary_len; i++) { + char value = 0; + if (hex[i * 2] >= '0' && hex[i * 2] <= '9') { + value += (hex[i * 2] - '0') * 16; + } else { + value += (hex[i * 2] - 'a' + 10) * 16; + } + if (hex[i * 2 + 1] >= '0' && hex[i * 2 + 1] <= '9') { + value += hex[i * 2 + 1] - '0'; + } else { + value += hex[i * 2 + 1] - 'a' + 10; + } + (*binary)[i] = value; + } +} + +PHP_METHOD(Any, __construct) { + init_file_any(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(any_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(Any, any, TypeUrl, "type_url") +PHP_PROTO_FIELD_ACCESSORS(Any, any, Value, "value") + +PHP_METHOD(Any, unpack) { + // Get type url. + zval type_url_member; + PHP_PROTO_ZVAL_STRING(&type_url_member, "type_url", 1); + PHP_PROTO_FAKE_SCOPE_BEGIN(any_type); + zval* type_url_php = php_proto_message_read_property( + getThis(), &type_url_member PHP_PROTO_TSRMLS_CC); + PHP_PROTO_FAKE_SCOPE_END; + + // Get fully-qualified name from type url. + size_t url_prefix_len = strlen(TYPE_URL_PREFIX); + const char* type_url = Z_STRVAL_P(type_url_php); + size_t type_url_len = Z_STRLEN_P(type_url_php); + + if (url_prefix_len > type_url_len || + strncmp(TYPE_URL_PREFIX, type_url, url_prefix_len) != 0) { + zend_throw_exception( + NULL, "Type url needs to be type.googleapis.com/fully-qulified", + 0 TSRMLS_CC); + return; + } + + const char* fully_qualified_name = type_url + url_prefix_len; + PHP_PROTO_HASHTABLE_VALUE desc_php = get_proto_obj(fully_qualified_name); + if (desc_php == NULL) { + zend_throw_exception( + NULL, "Specified message in any hasn't been added to descriptor pool", + 0 TSRMLS_CC); + return; + } + Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php); + zend_class_entry* klass = desc->klass; + ZVAL_OBJ(return_value, klass->create_object(klass TSRMLS_CC)); + MessageHeader* msg = UNBOX(MessageHeader, return_value); + custom_data_init(klass, msg PHP_PROTO_TSRMLS_CC); + + // Get value. + zval value_member; + PHP_PROTO_ZVAL_STRING(&value_member, "value", 1); + PHP_PROTO_FAKE_SCOPE_RESTART(any_type); + zval* value = php_proto_message_read_property( + getThis(), &value_member PHP_PROTO_TSRMLS_CC); + PHP_PROTO_FAKE_SCOPE_END; + + merge_from_string(Z_STRVAL_P(value), Z_STRLEN_P(value), desc, msg); +} + +PHP_METHOD(Any, pack) { + zval* val; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &val) == + FAILURE) { + return; + } + + if (!instanceof_function(Z_OBJCE_P(val), message_type TSRMLS_CC)) { + zend_error(E_USER_ERROR, "Given value is not an instance of Message."); + return; + } + + // Set value by serialized data. + zval data; + serialize_to_string(val, &data TSRMLS_CC); + + zval member; + PHP_PROTO_ZVAL_STRING(&member, "value", 1); + + PHP_PROTO_FAKE_SCOPE_BEGIN(any_type); + message_handlers->write_property(getThis(), &member, &data, + NULL PHP_PROTO_TSRMLS_CC); + PHP_PROTO_FAKE_SCOPE_END; + + // Set type url. + Descriptor* desc = + UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(val))); + const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef); + size_t type_url_len = + strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1; + char* type_url = ALLOC_N(char, type_url_len); + sprintf(type_url, "%s%s", TYPE_URL_PREFIX, fully_qualified_name); + zval type_url_php; + PHP_PROTO_ZVAL_STRING(&type_url_php, type_url, 1); + PHP_PROTO_ZVAL_STRING(&member, "type_url", 1); + + PHP_PROTO_FAKE_SCOPE_RESTART(any_type); + message_handlers->write_property(getThis(), &member, &type_url_php, + NULL PHP_PROTO_TSRMLS_CC); + PHP_PROTO_FAKE_SCOPE_END; + FREE(type_url); +} + +PHP_METHOD(Any, is) { + zend_class_entry *klass = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "C", &klass) == + FAILURE) { + return; + } + + PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(klass); + if (desc_php == NULL) { + RETURN_BOOL(false); + } + + // Create corresponded type url. + Descriptor* desc = + UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(klass)); + const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef); + size_t type_url_len = + strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1; + char* type_url = ALLOC_N(char, type_url_len); + sprintf(type_url, "%s%s", TYPE_URL_PREFIX, fully_qualified_name); + + // Fetch stored type url. + zval member; + PHP_PROTO_ZVAL_STRING(&member, "type_url", 1); + PHP_PROTO_FAKE_SCOPE_BEGIN(any_type); + zval* value = + php_proto_message_read_property(getThis(), &member PHP_PROTO_TSRMLS_CC); + PHP_PROTO_FAKE_SCOPE_END; + + // Compare two type url. + bool is = strcmp(type_url, Z_STRVAL_P(value)) == 0; + FREE(type_url); + + RETURN_BOOL(is); +} + +// ----------------------------------------------------------------------------- +// Duration +// ----------------------------------------------------------------------------- + +static zend_function_entry duration_methods[] = { + PHP_ME(Duration, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Duration, getSeconds, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Duration, setSeconds, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Duration, getNanos, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Duration, setNanos, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* duration_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Duration", + Duration, duration) + zend_class_implements(duration_type TSRMLS_CC, 1, message_type); + zend_declare_property_long(duration_type, "seconds", strlen("seconds"), + 0 ,ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_long(duration_type, "nanos", strlen("nanos"), + 0 ,ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(Duration, __construct) { + init_file_duration(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(duration_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(Duration, duration, Seconds, "seconds") +PHP_PROTO_FIELD_ACCESSORS(Duration, duration, Nanos, "nanos") + +// ----------------------------------------------------------------------------- +// Timestamp +// ----------------------------------------------------------------------------- + +static zend_function_entry timestamp_methods[] = { + PHP_ME(Timestamp, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Timestamp, fromDateTime, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Timestamp, toDateTime, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Timestamp, getSeconds, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Timestamp, setSeconds, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Timestamp, getNanos, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Timestamp, setNanos, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* timestamp_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Timestamp", + Timestamp, timestamp) + zend_class_implements(timestamp_type TSRMLS_CC, 1, message_type); + zend_declare_property_long(timestamp_type, "seconds", strlen("seconds"), + 0 ,ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_long(timestamp_type, "nanos", strlen("nanos"), + 0 ,ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(Timestamp, __construct) { + init_file_timestamp(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(timestamp_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(Timestamp, timestamp, Seconds, "seconds") +PHP_PROTO_FIELD_ACCESSORS(Timestamp, timestamp, Nanos, "nanos") + +PHP_METHOD(Timestamp, fromDateTime) { + zval* datetime; + zval member; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &datetime, + php_date_get_date_ce()) == FAILURE) { + return; + } + + php_date_obj* dateobj = UNBOX(php_date_obj, datetime); + if (!dateobj->time->sse_uptodate) { + timelib_update_ts(dateobj->time, NULL); + } + + int64_t timestamp = dateobj->time->sse; + + // Set seconds + MessageHeader* self = UNBOX(MessageHeader, getThis()); + const upb_fielddef* field = + upb_msgdef_ntofz(self->descriptor->msgdef, "seconds"); + void* storage = message_data(self); + void* memory = slot_memory(self->descriptor->layout, storage, field); + *(int64_t*)memory = dateobj->time->sse; + + // Set nanos + field = upb_msgdef_ntofz(self->descriptor->msgdef, "nanos"); + storage = message_data(self); + memory = slot_memory(self->descriptor->layout, storage, field); + *(int32_t*)memory = 0; +} + +PHP_METHOD(Timestamp, toDateTime) { + zval datetime; + php_date_instantiate(php_date_get_date_ce(), &datetime TSRMLS_CC); + php_date_obj* dateobj = UNBOX(php_date_obj, &datetime); + + // Get seconds + MessageHeader* self = UNBOX(MessageHeader, getThis()); + const upb_fielddef* field = + upb_msgdef_ntofz(self->descriptor->msgdef, "seconds"); + void* storage = message_data(self); + void* memory = slot_memory(self->descriptor->layout, storage, field); + int64_t seconds = *(int64_t*)memory; + + // Get nanos + field = upb_msgdef_ntofz(self->descriptor->msgdef, "nanos"); + memory = slot_memory(self->descriptor->layout, storage, field); + int32_t nanos = *(int32_t*)memory; + + // Get formated time string. + char formated_time[50]; + time_t raw_time = seconds; + struct tm *utc_time = gmtime(&raw_time); + strftime(formated_time, sizeof(formated_time), "%Y-%m-%dT%H:%M:%SUTC", + utc_time); + + if (!php_date_initialize(dateobj, formated_time, strlen(formated_time), NULL, + NULL, 0 TSRMLS_CC)) { + zval_dtor(&datetime); + RETURN_NULL(); + } + + zval* datetime_ptr = &datetime; + PHP_PROTO_RETVAL_ZVAL(datetime_ptr); +} + +// ----------------------------------------------------------------------------- +// Api +// ----------------------------------------------------------------------------- + +static zend_function_entry api_methods[] = { + PHP_ME(Api, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Api, getName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Api, setName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Api, getMethods, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Api, setMethods, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Api, getOptions, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Api, setOptions, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Api, getVersion, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Api, setVersion, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Api, getSourceContext, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Api, setSourceContext, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Api, getMixins, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Api, setMixins, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Api, getSyntax, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Api, setSyntax, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* api_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Api", + Api, api) + zend_class_implements(api_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(api_type, "name", strlen("name"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(api_type, "methods", strlen("methods"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(api_type, "options", strlen("options"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(api_type, "version", strlen("version"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(api_type, "source_context", strlen("source_context"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(api_type, "mixins", strlen("mixins"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(api_type, "syntax", strlen("syntax"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(Api, __construct) { + init_file_api(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(api_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(Api, api, Name, "name") +PHP_PROTO_FIELD_ACCESSORS(Api, api, Methods, "methods") +PHP_PROTO_FIELD_ACCESSORS(Api, api, Options, "options") +PHP_PROTO_FIELD_ACCESSORS(Api, api, Version, "version") +PHP_PROTO_FIELD_ACCESSORS(Api, api, SourceContext, "source_context") +PHP_PROTO_FIELD_ACCESSORS(Api, api, Mixins, "mixins") +PHP_PROTO_FIELD_ACCESSORS(Api, api, Syntax, "syntax") + +// ----------------------------------------------------------------------------- +// BoolValue +// ----------------------------------------------------------------------------- + +static zend_function_entry bool_value_methods[] = { + PHP_ME(BoolValue, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(BoolValue, getValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(BoolValue, setValue, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* bool_value_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\BoolValue", + BoolValue, bool_value) + zend_class_implements(bool_value_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(bool_value_type, "value", strlen("value"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(BoolValue, __construct) { + init_file_wrappers(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(bool_value_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(BoolValue, bool_value, Value, "value") + +// ----------------------------------------------------------------------------- +// BytesValue +// ----------------------------------------------------------------------------- + +static zend_function_entry bytes_value_methods[] = { + PHP_ME(BytesValue, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(BytesValue, getValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(BytesValue, setValue, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* bytes_value_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\BytesValue", + BytesValue, bytes_value) + zend_class_implements(bytes_value_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(bytes_value_type, "value", strlen("value"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(BytesValue, __construct) { + init_file_wrappers(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(bytes_value_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(BytesValue, bytes_value, Value, "value") + +// ----------------------------------------------------------------------------- +// DoubleValue +// ----------------------------------------------------------------------------- + +static zend_function_entry double_value_methods[] = { + PHP_ME(DoubleValue, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(DoubleValue, getValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(DoubleValue, setValue, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* double_value_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\DoubleValue", + DoubleValue, double_value) + zend_class_implements(double_value_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(double_value_type, "value", strlen("value"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(DoubleValue, __construct) { + init_file_wrappers(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(double_value_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(DoubleValue, double_value, Value, "value") + +// ----------------------------------------------------------------------------- +// Enum +// ----------------------------------------------------------------------------- + +static zend_function_entry enum_methods[] = { + PHP_ME(Enum, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Enum, getName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Enum, setName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Enum, getEnumvalue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Enum, setEnumvalue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Enum, getOptions, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Enum, setOptions, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Enum, getSourceContext, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Enum, setSourceContext, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Enum, getSyntax, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Enum, setSyntax, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* enum_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Enum", + Enum, enum) + zend_class_implements(enum_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(enum_type, "name", strlen("name"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(enum_type, "enumvalue", strlen("enumvalue"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(enum_type, "options", strlen("options"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(enum_type, "source_context", strlen("source_context"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(enum_type, "syntax", strlen("syntax"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(Enum, __construct) { + init_file_type(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(enum_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(Enum, enum, Name, "name") +PHP_PROTO_FIELD_ACCESSORS(Enum, enum, Enumvalue, "enumvalue") +PHP_PROTO_FIELD_ACCESSORS(Enum, enum, Options, "options") +PHP_PROTO_FIELD_ACCESSORS(Enum, enum, SourceContext, "source_context") +PHP_PROTO_FIELD_ACCESSORS(Enum, enum, Syntax, "syntax") + +// ----------------------------------------------------------------------------- +// EnumValue +// ----------------------------------------------------------------------------- + +static zend_function_entry enum_value_methods[] = { + PHP_ME(EnumValue, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(EnumValue, getName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(EnumValue, setName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(EnumValue, getNumber, NULL, ZEND_ACC_PUBLIC) + PHP_ME(EnumValue, setNumber, NULL, ZEND_ACC_PUBLIC) + PHP_ME(EnumValue, getOptions, NULL, ZEND_ACC_PUBLIC) + PHP_ME(EnumValue, setOptions, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* enum_value_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\EnumValue", + EnumValue, enum_value) + zend_class_implements(enum_value_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(enum_value_type, "name", strlen("name"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(enum_value_type, "number", strlen("number"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(enum_value_type, "options", strlen("options"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(EnumValue, __construct) { + init_file_type(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(enum_value_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(EnumValue, enum_value, Name, "name") +PHP_PROTO_FIELD_ACCESSORS(EnumValue, enum_value, Number, "number") +PHP_PROTO_FIELD_ACCESSORS(EnumValue, enum_value, Options, "options") + +// ----------------------------------------------------------------------------- +// FieldMask +// ----------------------------------------------------------------------------- + +static zend_function_entry field_mask_methods[] = { + PHP_ME(FieldMask, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(FieldMask, getPaths, NULL, ZEND_ACC_PUBLIC) + PHP_ME(FieldMask, setPaths, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* field_mask_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\FieldMask", + FieldMask, field_mask) + zend_class_implements(field_mask_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(field_mask_type, "paths", strlen("paths"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(FieldMask, __construct) { + init_file_field_mask(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(field_mask_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(FieldMask, field_mask, Paths, "paths") + +// ----------------------------------------------------------------------------- +// Field +// ----------------------------------------------------------------------------- + +static zend_function_entry field_methods[] = { + PHP_ME(Field, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, getKind, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, setKind, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, getCardinality, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, setCardinality, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, getNumber, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, setNumber, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, getName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, setName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, getTypeUrl, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, setTypeUrl, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, getOneofIndex, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, setOneofIndex, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, getPacked, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, setPacked, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, getOptions, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, setOptions, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, getJsonName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, setJsonName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, getDefaultValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Field, setDefaultValue, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* field_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Field", + Field, field) + zend_class_implements(field_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(field_type, "kind", strlen("kind"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(field_type, "cardinality", strlen("cardinality"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(field_type, "number", strlen("number"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(field_type, "name", strlen("name"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(field_type, "type_url", strlen("type_url"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(field_type, "oneof_index", strlen("oneof_index"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(field_type, "packed", strlen("packed"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(field_type, "options", strlen("options"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(field_type, "json_name", strlen("json_name"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(field_type, "default_value", strlen("default_value"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(Field, __construct) { + init_file_type(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(field_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(Field, field, Kind, "kind") +PHP_PROTO_FIELD_ACCESSORS(Field, field, Cardinality, "cardinality") +PHP_PROTO_FIELD_ACCESSORS(Field, field, Number, "number") +PHP_PROTO_FIELD_ACCESSORS(Field, field, Name, "name") +PHP_PROTO_FIELD_ACCESSORS(Field, field, TypeUrl, "type_url") +PHP_PROTO_FIELD_ACCESSORS(Field, field, OneofIndex, "oneof_index") +PHP_PROTO_FIELD_ACCESSORS(Field, field, Packed, "packed") +PHP_PROTO_FIELD_ACCESSORS(Field, field, Options, "options") +PHP_PROTO_FIELD_ACCESSORS(Field, field, JsonName, "json_name") +PHP_PROTO_FIELD_ACCESSORS(Field, field, DefaultValue, "default_value") + +// ----------------------------------------------------------------------------- +// FloatValue +// ----------------------------------------------------------------------------- + +static zend_function_entry float_value_methods[] = { + PHP_ME(FloatValue, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(FloatValue, getValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(FloatValue, setValue, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* float_value_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\FloatValue", + FloatValue, float_value) + zend_class_implements(float_value_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(float_value_type, "value", strlen("value"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(FloatValue, __construct) { + init_file_wrappers(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(float_value_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(FloatValue, float_value, Value, "value") + +// ----------------------------------------------------------------------------- +// GPBEmpty +// ----------------------------------------------------------------------------- + +static zend_function_entry empty_methods[] = { + PHP_ME(GPBEmpty, __construct, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* empty_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\GPBEmpty", + GPBEmpty, empty) + zend_class_implements(empty_type TSRMLS_CC, 1, message_type); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(GPBEmpty, __construct) { + init_file_empty(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(empty_type, intern PHP_PROTO_TSRMLS_CC); +} + + +// ----------------------------------------------------------------------------- +// Int32Value +// ----------------------------------------------------------------------------- + +static zend_function_entry int32_value_methods[] = { + PHP_ME(Int32Value, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Int32Value, getValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Int32Value, setValue, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* int32_value_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Int32Value", + Int32Value, int32_value) + zend_class_implements(int32_value_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(int32_value_type, "value", strlen("value"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(Int32Value, __construct) { + init_file_wrappers(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(int32_value_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(Int32Value, int32_value, Value, "value") + +// ----------------------------------------------------------------------------- +// Int64Value +// ----------------------------------------------------------------------------- + +static zend_function_entry int64_value_methods[] = { + PHP_ME(Int64Value, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Int64Value, getValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Int64Value, setValue, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* int64_value_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Int64Value", + Int64Value, int64_value) + zend_class_implements(int64_value_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(int64_value_type, "value", strlen("value"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(Int64Value, __construct) { + init_file_wrappers(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(int64_value_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(Int64Value, int64_value, Value, "value") + +// ----------------------------------------------------------------------------- +// ListValue +// ----------------------------------------------------------------------------- + +static zend_function_entry list_value_methods[] = { + PHP_ME(ListValue, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ListValue, getValues, NULL, ZEND_ACC_PUBLIC) + PHP_ME(ListValue, setValues, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* list_value_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\ListValue", + ListValue, list_value) + zend_class_implements(list_value_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(list_value_type, "values", strlen("values"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(ListValue, __construct) { + init_file_struct(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(list_value_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(ListValue, list_value, Values, "values") + +// ----------------------------------------------------------------------------- +// Method +// ----------------------------------------------------------------------------- + +static zend_function_entry method_methods[] = { + PHP_ME(Method, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Method, getName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Method, setName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Method, getRequestTypeUrl, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Method, setRequestTypeUrl, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Method, getRequestStreaming, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Method, setRequestStreaming, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Method, getResponseTypeUrl, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Method, setResponseTypeUrl, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Method, getResponseStreaming, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Method, setResponseStreaming, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Method, getOptions, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Method, setOptions, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Method, getSyntax, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Method, setSyntax, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* method_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Method", + Method, method) + zend_class_implements(method_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(method_type, "name", strlen("name"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(method_type, "request_type_url", strlen("request_type_url"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(method_type, "request_streaming", strlen("request_streaming"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(method_type, "response_type_url", strlen("response_type_url"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(method_type, "response_streaming", strlen("response_streaming"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(method_type, "options", strlen("options"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(method_type, "syntax", strlen("syntax"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(Method, __construct) { + init_file_api(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(method_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(Method, method, Name, "name") +PHP_PROTO_FIELD_ACCESSORS(Method, method, RequestTypeUrl, "request_type_url") +PHP_PROTO_FIELD_ACCESSORS(Method, method, RequestStreaming, "request_streaming") +PHP_PROTO_FIELD_ACCESSORS(Method, method, ResponseTypeUrl, "response_type_url") +PHP_PROTO_FIELD_ACCESSORS(Method, method, ResponseStreaming, "response_streaming") +PHP_PROTO_FIELD_ACCESSORS(Method, method, Options, "options") +PHP_PROTO_FIELD_ACCESSORS(Method, method, Syntax, "syntax") + +// ----------------------------------------------------------------------------- +// Mixin +// ----------------------------------------------------------------------------- + +static zend_function_entry mixin_methods[] = { + PHP_ME(Mixin, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Mixin, getName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Mixin, setName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Mixin, getRoot, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Mixin, setRoot, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* mixin_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Mixin", + Mixin, mixin) + zend_class_implements(mixin_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(mixin_type, "name", strlen("name"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(mixin_type, "root", strlen("root"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(Mixin, __construct) { + init_file_api(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(mixin_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(Mixin, mixin, Name, "name") +PHP_PROTO_FIELD_ACCESSORS(Mixin, mixin, Root, "root") + +// ----------------------------------------------------------------------------- +// Option +// ----------------------------------------------------------------------------- + +static zend_function_entry option_methods[] = { + PHP_ME(Option, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Option, getName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Option, setName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Option, getValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Option, setValue, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* option_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Option", + Option, option) + zend_class_implements(option_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(option_type, "name", strlen("name"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(option_type, "value", strlen("value"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(Option, __construct) { + init_file_type(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(option_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(Option, option, Name, "name") +PHP_PROTO_FIELD_ACCESSORS(Option, option, Value, "value") + +// ----------------------------------------------------------------------------- +// SourceContext +// ----------------------------------------------------------------------------- + +static zend_function_entry source_context_methods[] = { + PHP_ME(SourceContext, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(SourceContext, getFileName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(SourceContext, setFileName, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* source_context_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\SourceContext", + SourceContext, source_context) + zend_class_implements(source_context_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(source_context_type, "file_name", strlen("file_name"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(SourceContext, __construct) { + init_file_source_context(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(source_context_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(SourceContext, source_context, FileName, "file_name") + +// ----------------------------------------------------------------------------- +// StringValue +// ----------------------------------------------------------------------------- + +static zend_function_entry string_value_methods[] = { + PHP_ME(StringValue, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(StringValue, getValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(StringValue, setValue, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* string_value_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\StringValue", + StringValue, string_value) + zend_class_implements(string_value_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(string_value_type, "value", strlen("value"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(StringValue, __construct) { + init_file_wrappers(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(string_value_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(StringValue, string_value, Value, "value") + +// ----------------------------------------------------------------------------- +// Struct +// ----------------------------------------------------------------------------- + +static zend_function_entry struct_methods[] = { + PHP_ME(Struct, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Struct, getFields, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Struct, setFields, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* struct_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Struct", + Struct, struct) + zend_class_implements(struct_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(struct_type, "fields", strlen("fields"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(Struct, __construct) { + init_file_struct(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(struct_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(Struct, struct, Fields, "fields") + +// ----------------------------------------------------------------------------- +// Type +// ----------------------------------------------------------------------------- + +static zend_function_entry type_methods[] = { + PHP_ME(Type, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Type, getName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Type, setName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Type, getFields, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Type, setFields, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Type, getOneofs, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Type, setOneofs, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Type, getOptions, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Type, setOptions, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Type, getSourceContext, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Type, setSourceContext, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Type, getSyntax, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Type, setSyntax, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* type_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Type", + Type, type) + zend_class_implements(type_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(type_type, "name", strlen("name"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(type_type, "fields", strlen("fields"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(type_type, "oneofs", strlen("oneofs"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(type_type, "options", strlen("options"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(type_type, "source_context", strlen("source_context"), + ZEND_ACC_PRIVATE TSRMLS_CC); + zend_declare_property_null(type_type, "syntax", strlen("syntax"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(Type, __construct) { + init_file_type(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(type_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(Type, type, Name, "name") +PHP_PROTO_FIELD_ACCESSORS(Type, type, Fields, "fields") +PHP_PROTO_FIELD_ACCESSORS(Type, type, Oneofs, "oneofs") +PHP_PROTO_FIELD_ACCESSORS(Type, type, Options, "options") +PHP_PROTO_FIELD_ACCESSORS(Type, type, SourceContext, "source_context") +PHP_PROTO_FIELD_ACCESSORS(Type, type, Syntax, "syntax") + +// ----------------------------------------------------------------------------- +// UInt32Value +// ----------------------------------------------------------------------------- + +static zend_function_entry u_int32_value_methods[] = { + PHP_ME(UInt32Value, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(UInt32Value, getValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(UInt32Value, setValue, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* u_int32_value_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\UInt32Value", + UInt32Value, u_int32_value) + zend_class_implements(u_int32_value_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(u_int32_value_type, "value", strlen("value"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(UInt32Value, __construct) { + init_file_wrappers(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(u_int32_value_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(UInt32Value, u_int32_value, Value, "value") + +// ----------------------------------------------------------------------------- +// UInt64Value +// ----------------------------------------------------------------------------- + +static zend_function_entry u_int64_value_methods[] = { + PHP_ME(UInt64Value, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(UInt64Value, getValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(UInt64Value, setValue, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* u_int64_value_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\UInt64Value", + UInt64Value, u_int64_value) + zend_class_implements(u_int64_value_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(u_int64_value_type, "value", strlen("value"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(UInt64Value, __construct) { + init_file_wrappers(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(u_int64_value_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_FIELD_ACCESSORS(UInt64Value, u_int64_value, Value, "value") + +// ----------------------------------------------------------------------------- +// Value +// ----------------------------------------------------------------------------- + +static zend_function_entry value_methods[] = { + PHP_ME(Value, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Value, getNullValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Value, setNullValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Value, getNumberValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Value, setNumberValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Value, getStringValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Value, setStringValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Value, getBoolValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Value, setBoolValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Value, getStructValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Value, setStructValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Value, getListValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Value, setListValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Value, getKind, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +zend_class_entry* value_type; + +// Init class entry. +PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Value", + Value, value) + zend_class_implements(value_type TSRMLS_CC, 1, message_type); + zend_declare_property_null(value_type, "kind", strlen("kind"), + ZEND_ACC_PRIVATE TSRMLS_CC); +PHP_PROTO_INIT_SUBMSGCLASS_END + +PHP_METHOD(Value, __construct) { + init_file_struct(TSRMLS_C); + MessageHeader* intern = UNBOX(MessageHeader, getThis()); + custom_data_init(value_type, intern PHP_PROTO_TSRMLS_CC); +} + +PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, NullValue, "null_value") +PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, NumberValue, "number_value") +PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, StringValue, "string_value") +PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, BoolValue, "bool_value") +PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, StructValue, "struct_value") +PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, ListValue, "list_value") +PHP_PROTO_ONEOF_ACCESSORS(Value, value, Kind, "kind") diff --git a/php/ext/google/protobuf/protobuf.c b/php/ext/google/protobuf/protobuf.c index 43b4e584..b67089e0 100644 --- a/php/ext/google/protobuf/protobuf.c +++ b/php/ext/google/protobuf/protobuf.c @@ -46,6 +46,9 @@ static HashTable* upb_def_to_php_obj_map; // Global map from message/enum's php class entry to corresponding wrapper // Descriptor/EnumDescriptor instances. static HashTable* ce_to_php_obj_map; +// Global map from message/enum's proto fully-qualified name to corresponding +// wrapper Descriptor/EnumDescriptor instances. +static HashTable* proto_to_php_obj_map; static HashTable* reserved_names; // ----------------------------------------------------------------------------- @@ -81,6 +84,22 @@ static void add_to_list(HashTable* t, void* value) { (void**)&pDest); } +static void add_to_strtable(HashTable* t, const char* key, int key_size, + void* value) { + zval* pDest = NULL; + php_proto_zend_hash_update_mem(t, key, key_size, &value, sizeof(void*), + (void**)&pDest); +} + +static void* get_from_strtable(const HashTable* t, const char* key, int key_size) { + void** value; + if (php_proto_zend_hash_find_mem(t, key, key_size, (void**)&value) == + FAILURE) { + return NULL; + } + return *value; +} + void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value) { #if PHP_MAJOR_VERSION < 7 Z_ADDREF_P(value); @@ -111,6 +130,20 @@ bool class_added(const void* ce) { return exist_in_table(ce_to_php_obj_map, ce); } +void add_proto_obj(const char* proto, PHP_PROTO_HASHTABLE_VALUE value) { +#if PHP_MAJOR_VERSION < 7 + Z_ADDREF_P(value); +#else + ++GC_REFCOUNT(value); +#endif + add_to_strtable(proto_to_php_obj_map, proto, strlen(proto), value); +} + +PHP_PROTO_HASHTABLE_VALUE get_proto_obj(const char* proto) { + return (PHP_PROTO_HASHTABLE_VALUE)get_from_strtable(proto_to_php_obj_map, + proto, strlen(proto)); +} + // ----------------------------------------------------------------------------- // Reserved Name. // ----------------------------------------------------------------------------- @@ -196,6 +229,9 @@ static PHP_RINIT_FUNCTION(protobuf) { ALLOC_HASHTABLE(ce_to_php_obj_map); zend_hash_init(ce_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0); + ALLOC_HASHTABLE(proto_to_php_obj_map); + zend_hash_init(proto_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0); + ALLOC_HASHTABLE(reserved_names); zend_hash_init(reserved_names, 16, NULL, NULL, 0); for (i = 0; i < kReservedNamesSize; i++) { @@ -217,6 +253,9 @@ static PHP_RSHUTDOWN_FUNCTION(protobuf) { zend_hash_destroy(ce_to_php_obj_map); FREE_HASHTABLE(ce_to_php_obj_map); + zend_hash_destroy(proto_to_php_obj_map); + FREE_HASHTABLE(proto_to_php_obj_map); + zend_hash_destroy(reserved_names); FREE_HASHTABLE(reserved_names); @@ -261,6 +300,37 @@ static PHP_MINIT_FUNCTION(protobuf) { repeated_field_iter_init(TSRMLS_C); util_init(TSRMLS_C); + any_init(TSRMLS_C); + api_init(TSRMLS_C); + bool_value_init(TSRMLS_C); + bytes_value_init(TSRMLS_C); + double_value_init(TSRMLS_C); + duration_init(TSRMLS_C); + enum_init(TSRMLS_C); + enum_value_init(TSRMLS_C); + field_cardinality_init(TSRMLS_C); + field_init(TSRMLS_C); + field_kind_init(TSRMLS_C); + field_mask_init(TSRMLS_C); + float_value_init(TSRMLS_C); + empty_init(TSRMLS_C); + int32_value_init(TSRMLS_C); + int64_value_init(TSRMLS_C); + list_value_init(TSRMLS_C); + method_init(TSRMLS_C); + mixin_init(TSRMLS_C); + null_value_init(TSRMLS_C); + option_init(TSRMLS_C); + source_context_init(TSRMLS_C); + string_value_init(TSRMLS_C); + struct_init(TSRMLS_C); + syntax_init(TSRMLS_C); + timestamp_init(TSRMLS_C); + type_init(TSRMLS_C); + u_int32_value_init(TSRMLS_C); + u_int64_value_init(TSRMLS_C); + value_init(TSRMLS_C); + return 0; } diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h index 23c51c64..cb098747 100644 --- a/php/ext/google/protobuf/protobuf.h +++ b/php/ext/google/protobuf/protobuf.h @@ -77,12 +77,19 @@ #define php_proto_zend_hash_index_update_zval(ht, h, pData) \ zend_hash_index_update(ht, h, &(pData), sizeof(void*), NULL) +#define php_proto_zend_hash_update_zval(ht, key, key_len, value) \ + zend_hash_update(ht, key, key_len, value, sizeof(void*), NULL) + #define php_proto_zend_hash_update(ht, key, key_len) \ zend_hash_update(ht, key, key_len, 0, 0, NULL) #define php_proto_zend_hash_index_update_mem(ht, h, pData, nDataSize, pDest) \ zend_hash_index_update(ht, h, pData, nDataSize, pDest) +#define php_proto_zend_hash_update_mem(ht, key, key_len, pData, nDataSize, \ + pDest) \ + zend_hash_update(ht, key, key_len, pData, nDataSize, pDest) + #define php_proto_zend_hash_index_find_zval(ht, h, pDest) \ zend_hash_index_find(ht, h, pDest) @@ -92,6 +99,12 @@ #define php_proto_zend_hash_index_find_mem(ht, h, pDest) \ zend_hash_index_find(ht, h, pDest) +#define php_proto_zend_hash_find_zval(ht, key, key_len, pDest) \ + zend_hash_find(ht, key, key_len, pDest) + +#define php_proto_zend_hash_find_mem(ht, key, key_len, pDest) \ + zend_hash_find(ht, key, key_len, pDest) + #define php_proto_zend_hash_next_index_insert_zval(ht, pData) \ zend_hash_next_index_insert(ht, pData, sizeof(void*), NULL) @@ -109,6 +122,27 @@ #define PHP_PROTO_WRAP_OBJECT_END \ }; +#define PHP_PROTO_INIT_SUBMSGCLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \ + void LOWWERNAME##_init(TSRMLS_D) { \ + zend_class_entry class_type; \ + const char* class_name = CLASSNAME; \ + INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \ + LOWWERNAME##_methods); \ + LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \ + LOWWERNAME##_type->create_object = message_create; +#define PHP_PROTO_INIT_SUBMSGCLASS_END \ + } + +#define PHP_PROTO_INIT_ENUMCLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \ + void LOWWERNAME##_init(TSRMLS_D) { \ + zend_class_entry class_type; \ + const char* class_name = CLASSNAME; \ + INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \ + LOWWERNAME##_methods); \ + LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); +#define PHP_PROTO_INIT_ENUMCLASS_END \ + } + #define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \ void LOWWERNAME##_init(TSRMLS_D) { \ zend_class_entry class_type; \ @@ -208,6 +242,8 @@ #define php_proto_zend_lookup_class(name, name_length, ce) \ zend_lookup_class(name, name_length, ce TSRMLS_CC) +#define PHP_PROTO_RETVAL_ZVAL(value) ZVAL_ZVAL(return_value, value, 1, 0) + #else // PHP_MAJOR_VERSION >= 7 #define php_proto_zend_literal void** @@ -258,6 +294,23 @@ static inline int php_proto_zend_hash_index_update_mem(HashTable* ht, ulong h, return result != NULL ? SUCCESS : FAILURE; } +static inline int php_proto_zend_hash_update_zval(HashTable* ht, + const char* key, uint key_len, + zval* pData) { + zend_string* internal_key = zend_string_init(key, key_len, 0); + zend_hash_update(ht, internal_key, pData); +} + +static inline int php_proto_zend_hash_update_mem(HashTable* ht, const char* key, + uint key_len, void* pData, + uint nDataSize, void** pDest) { + zend_string* internal_key = zend_string_init(key, key_len, 0); + void* result = zend_hash_update_mem(ht, internal_key, pData, nDataSize); + zend_string_release(internal_key); + if (pDest != NULL) *pDest = result; + return result != NULL ? SUCCESS : FAILURE; +} + static inline int php_proto_zend_hash_index_find_zval(const HashTable* ht, ulong h, void** pDest) { zval* result = zend_hash_index_find(ht, h); @@ -280,6 +333,25 @@ static inline int php_proto_zend_hash_index_find_mem(const HashTable* ht, return result != NULL ? SUCCESS : FAILURE; } +static inline int php_proto_zend_hash_find_zval(const HashTable* ht, + const char* key, uint key_len, + void** pDest) { + zend_string* internal_key = zend_string_init(key, key_len, 1); + zval* result = zend_hash_find(ht, internal_key); + if (pDest != NULL) *pDest = result; + return result != NULL ? SUCCESS : FAILURE; +} + +static inline int php_proto_zend_hash_find_mem(const HashTable* ht, + const char* key, uint key_len, + void** pDest) { + zend_string* internal_key = zend_string_init(key, key_len, 1); + void* result = zend_hash_find_ptr(ht, internal_key); + zend_string_release(internal_key); + if (pDest != NULL) *pDest = result; + return result != NULL ? SUCCESS : FAILURE; +} + static inline int php_proto_zend_hash_next_index_insert_zval(HashTable* ht, void* pData) { zval tmp; @@ -314,6 +386,27 @@ static inline int php_proto_zend_hash_get_current_data_ex(HashTable* ht, zend_object std; \ }; +#define PHP_PROTO_INIT_SUBMSGCLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \ + void LOWWERNAME##_init(TSRMLS_D) { \ + zend_class_entry class_type; \ + const char* class_name = CLASSNAME; \ + INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \ + LOWWERNAME##_methods); \ + LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \ + LOWWERNAME##_type->create_object = message_create; +#define PHP_PROTO_INIT_SUBMSGCLASS_END \ + } + +#define PHP_PROTO_INIT_ENUMCLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \ + void LOWWERNAME##_init(TSRMLS_D) { \ + zend_class_entry class_type; \ + const char* class_name = CLASSNAME; \ + INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \ + LOWWERNAME##_methods); \ + LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); +#define PHP_PROTO_INIT_ENUMCLASS_END \ + } + #define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \ void LOWWERNAME##_init(TSRMLS_D) { \ zend_class_entry class_type; \ @@ -412,41 +505,162 @@ static inline int php_proto_zend_lookup_class( return *ce != NULL ? SUCCESS : FAILURE; } +#define PHP_PROTO_RETVAL_ZVAL(value) ZVAL_COPY(return_value, value) + #endif // PHP_MAJOR_VERSION >= 7 +#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0) +#define PHP_PROTO_FAKE_SCOPE_BEGIN(klass) \ + zend_class_entry* old_scope = EG(scope); \ + EG(scope) = klass; +#define PHP_PROTO_FAKE_SCOPE_RESTART(klass) \ + old_scope = EG(scope); \ + EG(scope) = klass; +#define PHP_PROTO_FAKE_SCOPE_END EG(scope) = old_scope; +#else +#define PHP_PROTO_FAKE_SCOPE_BEGIN(klass) \ + zend_class_entry* old_scope = EG(fake_scope); \ + EG(fake_scope) = klass; +#define PHP_PROTO_FAKE_SCOPE_RESTART(klass) \ + old_scope = EG(fake_scope); \ + EG(fake_scope) = klass; +#define PHP_PROTO_FAKE_SCOPE_END EG(fake_scope) = old_scope; +#endif + +// Define PHP class +#define DEFINE_PROTOBUF_INIT_CLASS(CLASSNAME, CAMELNAME, LOWERNAME) \ + PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWERNAME) \ + PHP_PROTO_INIT_CLASS_END + +#define DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME) \ + PHP_PROTO_OBJECT_CREATE_START(NAME, LOWERNAME) \ + LOWERNAME##_init_c_instance(intern TSRMLS_CC); \ + PHP_PROTO_OBJECT_CREATE_END(NAME, LOWERNAME) + +#define DEFINE_PROTOBUF_FREE(CAMELNAME, LOWERNAME) \ + PHP_PROTO_OBJECT_FREE_START(CAMELNAME, LOWERNAME) \ + LOWERNAME##_free_c(intern TSRMLS_CC); \ + PHP_PROTO_OBJECT_FREE_END + +#define DEFINE_PROTOBUF_DTOR(CAMELNAME, LOWERNAME) \ + PHP_PROTO_OBJECT_DTOR_START(CAMELNAME, LOWERNAME) \ + PHP_PROTO_OBJECT_DTOR_END + +#define DEFINE_CLASS(NAME, LOWERNAME, string_name) \ + zend_class_entry *LOWERNAME##_type; \ + zend_object_handlers *LOWERNAME##_handlers; \ + DEFINE_PROTOBUF_FREE(NAME, LOWERNAME) \ + DEFINE_PROTOBUF_DTOR(NAME, LOWERNAME) \ + DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME) \ + DEFINE_PROTOBUF_INIT_CLASS(string_name, NAME, LOWERNAME) + // ----------------------------------------------------------------------------- // Forward Declaration // ---------------------------------------------------------------------------- -struct DescriptorPool; +struct Any; +struct Api; +struct BoolValue; +struct BytesValue; struct Descriptor; +struct DescriptorPool; +struct DoubleValue; +struct Duration; +struct Enum; struct EnumDescriptor; +struct EnumValue; struct EnumValueDescriptor; +struct Field; struct FieldDescriptor; +struct FieldMask; +struct Field_Cardinality; +struct Field_Kind; +struct FloatValue; +struct GPBEmpty; +struct Int32Value; +struct Int64Value; struct InternalDescriptorPool; +struct ListValue; +struct Map; +struct MapIter; struct MessageField; struct MessageHeader; struct MessageLayout; +struct Method; +struct Mixin; +struct NullValue; +struct Oneof; +struct Option; struct RepeatedField; struct RepeatedFieldIter; -struct Map; -struct MapIter; -struct Oneof; - -typedef struct DescriptorPool DescriptorPool; +struct SourceContext; +struct StringValue; +struct Struct; +struct Syntax; +struct Timestamp; +struct Type; +struct UInt32Value; +struct UInt64Value; +struct Value; + +typedef struct Any Any; +typedef struct Api Api; +typedef struct BoolValue BoolValue; +typedef struct BytesValue BytesValue; typedef struct Descriptor Descriptor; +typedef struct Descriptor Descriptor; +typedef struct DescriptorPool DescriptorPool; +typedef struct DescriptorPool DescriptorPool; +typedef struct DoubleValue DoubleValue; +typedef struct Duration Duration; +typedef struct Enum Enum; +typedef struct EnumDescriptor EnumDescriptor; typedef struct EnumDescriptor EnumDescriptor; +typedef struct EnumValue EnumValue; typedef struct EnumValueDescriptor EnumValueDescriptor; +typedef struct EnumValueDescriptor EnumValueDescriptor; +typedef struct Field Field; +typedef struct FieldDescriptor FieldDescriptor; typedef struct FieldDescriptor FieldDescriptor; +typedef struct FieldMask FieldMask; +typedef struct Field_Cardinality Field_Cardinality; +typedef struct Field_Kind Field_Kind; +typedef struct FloatValue FloatValue; +typedef struct GPBEmpty GPBEmpty; +typedef struct Int32Value Int32Value; +typedef struct Int64Value Int64Value; +typedef struct InternalDescriptorPool InternalDescriptorPool; typedef struct InternalDescriptorPool InternalDescriptorPool; +typedef struct ListValue ListValue; +typedef struct Map Map; +typedef struct Map Map; +typedef struct MapIter MapIter; +typedef struct MapIter MapIter; +typedef struct MessageField MessageField; typedef struct MessageField MessageField; typedef struct MessageHeader MessageHeader; +typedef struct MessageHeader MessageHeader; typedef struct MessageLayout MessageLayout; +typedef struct MessageLayout MessageLayout; +typedef struct Method Method; +typedef struct Mixin Mixin; +typedef struct NullValue NullValue; +typedef struct Oneof Oneof; +typedef struct Oneof Oneof; +typedef struct Option Option; +typedef struct RepeatedField RepeatedField; typedef struct RepeatedField RepeatedField; typedef struct RepeatedFieldIter RepeatedFieldIter; -typedef struct Map Map; -typedef struct MapIter MapIter; -typedef struct Oneof Oneof; +typedef struct RepeatedFieldIter RepeatedFieldIter; +typedef struct SourceContext SourceContext; +typedef struct StringValue StringValue; +typedef struct Struct Struct; +typedef struct Syntax Syntax; +typedef struct Timestamp Timestamp; +typedef struct Type Type; +typedef struct UInt32Value UInt32Value; +typedef struct UInt64Value UInt64Value; +typedef struct Value Value; // ----------------------------------------------------------------------------- // Globals. @@ -456,19 +670,49 @@ ZEND_BEGIN_MODULE_GLOBALS(protobuf) ZEND_END_MODULE_GLOBALS(protobuf) // Init module and PHP classes. +void any_init(TSRMLS_D); +void api_init(TSRMLS_D); +void bool_value_init(TSRMLS_D); +void bytes_value_init(TSRMLS_D); void descriptor_init(TSRMLS_D); -void enum_descriptor_init(TSRMLS_D); void descriptor_pool_init(TSRMLS_D); -void internal_descriptor_pool_init(TSRMLS_D); +void double_value_init(TSRMLS_D); +void duration_init(TSRMLS_D); +void empty_init(TSRMLS_D); +void enum_descriptor_init(TSRMLS_D); +void enum_init(TSRMLS_D); +void enum_value_init(TSRMLS_D); +void field_cardinality_init(TSRMLS_D); void field_descriptor_init(TSRMLS_D); +void field_init(TSRMLS_D); +void field_kind_init(TSRMLS_D); +void field_mask_init(TSRMLS_D); +void float_value_init(TSRMLS_D); void gpb_type_init(TSRMLS_D); +void int32_value_init(TSRMLS_D); +void int64_value_init(TSRMLS_D); +void internal_descriptor_pool_init(TSRMLS_D); +void list_value_init(TSRMLS_D); void map_field_init(TSRMLS_D); void map_field_iter_init(TSRMLS_D); +void message_init(TSRMLS_D); +void method_init(TSRMLS_D); +void mixin_init(TSRMLS_D); +void null_value_init(TSRMLS_D); void oneof_descriptor_init(TSRMLS_D); +void option_init(TSRMLS_D); void repeated_field_init(TSRMLS_D); void repeated_field_iter_init(TSRMLS_D); +void source_context_init(TSRMLS_D); +void string_value_init(TSRMLS_D); +void struct_init(TSRMLS_D); +void syntax_init(TSRMLS_D); +void timestamp_init(TSRMLS_D); +void type_init(TSRMLS_D); +void uint32_value_init(TSRMLS_D); +void uint64_value_init(TSRMLS_D); void util_init(TSRMLS_D); -void message_init(TSRMLS_D); +void value_init(TSRMLS_D); // Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor // instances. @@ -481,6 +725,11 @@ void add_ce_obj(const void* ce, PHP_PROTO_HASHTABLE_VALUE value); PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce); bool class_added(const void* ce); +// Global map from message/enum's proto fully-qualified name to corresponding +// wrapper Descriptor/EnumDescriptor instances. +void add_proto_obj(const char* proto, PHP_PROTO_HASHTABLE_VALUE value); +PHP_PROTO_HASHTABLE_VALUE get_proto_obj(const char* proto); + extern zend_class_entry* map_field_type; extern zend_class_entry* repeated_field_type; @@ -504,6 +753,10 @@ PHP_PROTO_WRAP_OBJECT_END PHP_METHOD(InternalDescriptorPool, getGeneratedPool); PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile); +void internal_add_generated_file(const char* data, PHP_PROTO_SIZE data_len, + InternalDescriptorPool* pool TSRMLS_DC); +void init_generated_pool_once(TSRMLS_D); + // wrapper of generated pool #if PHP_MAJOR_VERSION < 7 extern zval* generated_pool_php; @@ -589,6 +842,7 @@ void custom_data_init(const zend_class_entry* ce, void build_class_from_descriptor( PHP_PROTO_HASHTABLE_VALUE php_descriptor TSRMLS_DC); +extern zend_class_entry* message_type; extern zend_object_handlers* message_handlers; // ----------------------------------------------------------------------------- @@ -676,6 +930,8 @@ void layout_merge(MessageLayout* layout, MessageHeader* from, const char* layout_get_oneof_case(MessageLayout* layout, const void* storage, const upb_oneofdef* oneof TSRMLS_DC); void free_layout(MessageLayout* layout); +void* slot_memory(MessageLayout* layout, const void* storage, + const upb_fielddef* field); PHP_METHOD(Message, clear); PHP_METHOD(Message, mergeFrom); @@ -696,6 +952,9 @@ PHP_METHOD(Message, __construct); // This is called from the message class creation code. const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor *desc, const void *owner); +void serialize_to_string(zval* val, zval* return_value TSRMLS_DC); +void merge_from_string(const char* data, int data_len, const Descriptor* desc, + MessageHeader* msg); PHP_METHOD(Message, serializeToString); PHP_METHOD(Message, mergeFromString); @@ -715,6 +974,11 @@ bool protobuf_convert_to_double(zval* from, double* to); bool protobuf_convert_to_bool(zval* from, int8_t* to); bool protobuf_convert_to_string(zval* from); +void check_repeated_field(const zend_class_entry* klass, PHP_PROTO_LONG type, + zval* val, zval* return_value); +void check_map_field(const zend_class_entry* klass, PHP_PROTO_LONG key_type, + PHP_PROTO_LONG value_type, zval* val, zval* return_value); + PHP_METHOD(Util, checkInt32); PHP_METHOD(Util, checkUint32); PHP_METHOD(Util, checkInt64); @@ -903,6 +1167,233 @@ extern zend_class_entry* oneof_descriptor_type; #define ONEOF_CASE_NONE 0 // ----------------------------------------------------------------------------- +// Well Known Type. +// ----------------------------------------------------------------------------- + +PHP_METHOD(Any, __construct); +PHP_METHOD(Any, getTypeUrl); +PHP_METHOD(Any, setTypeUrl); +PHP_METHOD(Any, getValue); +PHP_METHOD(Any, setValue); +PHP_METHOD(Any, unpack); +PHP_METHOD(Any, pack); +PHP_METHOD(Any, is); + +PHP_METHOD(Duration, __construct); +PHP_METHOD(Duration, getSeconds); +PHP_METHOD(Duration, setSeconds); +PHP_METHOD(Duration, getNanos); +PHP_METHOD(Duration, setNanos); + +PHP_METHOD(Timestamp, __construct); +PHP_METHOD(Timestamp, fromDateTime); +PHP_METHOD(Timestamp, toDateTime); +PHP_METHOD(Timestamp, getSeconds); +PHP_METHOD(Timestamp, setSeconds); +PHP_METHOD(Timestamp, getNanos); +PHP_METHOD(Timestamp, setNanos); + +PHP_METHOD(Api, __construct); +PHP_METHOD(Api, getName); +PHP_METHOD(Api, setName); +PHP_METHOD(Api, getMethods); +PHP_METHOD(Api, setMethods); +PHP_METHOD(Api, getOptions); +PHP_METHOD(Api, setOptions); +PHP_METHOD(Api, getVersion); +PHP_METHOD(Api, setVersion); +PHP_METHOD(Api, getSourceContext); +PHP_METHOD(Api, setSourceContext); +PHP_METHOD(Api, getMixins); +PHP_METHOD(Api, setMixins); +PHP_METHOD(Api, getSyntax); +PHP_METHOD(Api, setSyntax); + +PHP_METHOD(BoolValue, __construct); +PHP_METHOD(BoolValue, getValue); +PHP_METHOD(BoolValue, setValue); + +PHP_METHOD(BytesValue, __construct); +PHP_METHOD(BytesValue, getValue); +PHP_METHOD(BytesValue, setValue); + +PHP_METHOD(DoubleValue, __construct); +PHP_METHOD(DoubleValue, getValue); +PHP_METHOD(DoubleValue, setValue); + +PHP_METHOD(Enum, __construct); +PHP_METHOD(Enum, getName); +PHP_METHOD(Enum, setName); +PHP_METHOD(Enum, getEnumvalue); +PHP_METHOD(Enum, setEnumvalue); +PHP_METHOD(Enum, getOptions); +PHP_METHOD(Enum, setOptions); +PHP_METHOD(Enum, getSourceContext); +PHP_METHOD(Enum, setSourceContext); +PHP_METHOD(Enum, getSyntax); +PHP_METHOD(Enum, setSyntax); + +PHP_METHOD(EnumValue, __construct); +PHP_METHOD(EnumValue, getName); +PHP_METHOD(EnumValue, setName); +PHP_METHOD(EnumValue, getNumber); +PHP_METHOD(EnumValue, setNumber); +PHP_METHOD(EnumValue, getOptions); +PHP_METHOD(EnumValue, setOptions); + +PHP_METHOD(FieldMask, __construct); +PHP_METHOD(FieldMask, getPaths); +PHP_METHOD(FieldMask, setPaths); + +PHP_METHOD(Field, __construct); +PHP_METHOD(Field, getKind); +PHP_METHOD(Field, setKind); +PHP_METHOD(Field, getCardinality); +PHP_METHOD(Field, setCardinality); +PHP_METHOD(Field, getNumber); +PHP_METHOD(Field, setNumber); +PHP_METHOD(Field, getName); +PHP_METHOD(Field, setName); +PHP_METHOD(Field, getTypeUrl); +PHP_METHOD(Field, setTypeUrl); +PHP_METHOD(Field, getOneofIndex); +PHP_METHOD(Field, setOneofIndex); +PHP_METHOD(Field, getPacked); +PHP_METHOD(Field, setPacked); +PHP_METHOD(Field, getOptions); +PHP_METHOD(Field, setOptions); +PHP_METHOD(Field, getJsonName); +PHP_METHOD(Field, setJsonName); +PHP_METHOD(Field, getDefaultValue); +PHP_METHOD(Field, setDefaultValue); + +PHP_METHOD(FloatValue, __construct); +PHP_METHOD(FloatValue, getValue); +PHP_METHOD(FloatValue, setValue); + +PHP_METHOD(GPBEmpty, __construct); + +PHP_METHOD(Int32Value, __construct); +PHP_METHOD(Int32Value, getValue); +PHP_METHOD(Int32Value, setValue); + +PHP_METHOD(Int64Value, __construct); +PHP_METHOD(Int64Value, getValue); +PHP_METHOD(Int64Value, setValue); + +PHP_METHOD(ListValue, __construct); +PHP_METHOD(ListValue, getValues); +PHP_METHOD(ListValue, setValues); + +PHP_METHOD(Method, __construct); +PHP_METHOD(Method, getName); +PHP_METHOD(Method, setName); +PHP_METHOD(Method, getRequestTypeUrl); +PHP_METHOD(Method, setRequestTypeUrl); +PHP_METHOD(Method, getRequestStreaming); +PHP_METHOD(Method, setRequestStreaming); +PHP_METHOD(Method, getResponseTypeUrl); +PHP_METHOD(Method, setResponseTypeUrl); +PHP_METHOD(Method, getResponseStreaming); +PHP_METHOD(Method, setResponseStreaming); +PHP_METHOD(Method, getOptions); +PHP_METHOD(Method, setOptions); +PHP_METHOD(Method, getSyntax); +PHP_METHOD(Method, setSyntax); + +PHP_METHOD(Mixin, __construct); +PHP_METHOD(Mixin, getName); +PHP_METHOD(Mixin, setName); +PHP_METHOD(Mixin, getRoot); +PHP_METHOD(Mixin, setRoot); + +PHP_METHOD(Option, __construct); +PHP_METHOD(Option, getName); +PHP_METHOD(Option, setName); +PHP_METHOD(Option, getValue); +PHP_METHOD(Option, setValue); + +PHP_METHOD(SourceContext, __construct); +PHP_METHOD(SourceContext, getFileName); +PHP_METHOD(SourceContext, setFileName); + +PHP_METHOD(StringValue, __construct); +PHP_METHOD(StringValue, getValue); +PHP_METHOD(StringValue, setValue); + +PHP_METHOD(Struct, __construct); +PHP_METHOD(Struct, getFields); +PHP_METHOD(Struct, setFields); + +PHP_METHOD(Type, __construct); +PHP_METHOD(Type, getName); +PHP_METHOD(Type, setName); +PHP_METHOD(Type, getFields); +PHP_METHOD(Type, setFields); +PHP_METHOD(Type, getOneofs); +PHP_METHOD(Type, setOneofs); +PHP_METHOD(Type, getOptions); +PHP_METHOD(Type, setOptions); +PHP_METHOD(Type, getSourceContext); +PHP_METHOD(Type, setSourceContext); +PHP_METHOD(Type, getSyntax); +PHP_METHOD(Type, setSyntax); + +PHP_METHOD(UInt32Value, __construct); +PHP_METHOD(UInt32Value, getValue); +PHP_METHOD(UInt32Value, setValue); + +PHP_METHOD(UInt64Value, __construct); +PHP_METHOD(UInt64Value, getValue); +PHP_METHOD(UInt64Value, setValue); + +PHP_METHOD(Value, __construct); +PHP_METHOD(Value, getNullValue); +PHP_METHOD(Value, setNullValue); +PHP_METHOD(Value, getNumberValue); +PHP_METHOD(Value, setNumberValue); +PHP_METHOD(Value, getStringValue); +PHP_METHOD(Value, setStringValue); +PHP_METHOD(Value, getBoolValue); +PHP_METHOD(Value, setBoolValue); +PHP_METHOD(Value, getStructValue); +PHP_METHOD(Value, setStructValue); +PHP_METHOD(Value, getListValue); +PHP_METHOD(Value, setListValue); +PHP_METHOD(Value, getKind); + +extern zend_class_entry* any_type; +extern zend_class_entry* api_type; +extern zend_class_entry* bool_value_type; +extern zend_class_entry* bytes_value_type; +extern zend_class_entry* double_value_type; +extern zend_class_entry* duration_type; +extern zend_class_entry* empty_type; +extern zend_class_entry* enum_type; +extern zend_class_entry* enum_value_type; +extern zend_class_entry* field_cardinality_type; +extern zend_class_entry* field_kind_type; +extern zend_class_entry* field_mask_type; +extern zend_class_entry* field_type; +extern zend_class_entry* float_value_type; +extern zend_class_entry* int32_value_type; +extern zend_class_entry* int64_value_type; +extern zend_class_entry* list_value_type; +extern zend_class_entry* method_type; +extern zend_class_entry* mixin_type; +extern zend_class_entry* null_value_type; +extern zend_class_entry* option_type; +extern zend_class_entry* source_context_type; +extern zend_class_entry* string_value_type; +extern zend_class_entry* struct_type; +extern zend_class_entry* syntax_type; +extern zend_class_entry* timestamp_type; +extern zend_class_entry* type_type; +extern zend_class_entry* uint32_value_type; +extern zend_class_entry* uint64_value_type; +extern zend_class_entry* value_type; + +// ----------------------------------------------------------------------------- // Upb. // ----------------------------------------------------------------------------- @@ -932,6 +1423,18 @@ const zend_class_entry* field_type_class( .bucket.obj.object)) #endif +// Message handler +static inline zval* php_proto_message_read_property( + zval* msg, zval* member PHP_PROTO_TSRMLS_DC) { +#if PHP_MAJOR_VERSION < 7 + return message_handlers->read_property(msg, member, BP_VAR_R, + NULL PHP_PROTO_TSRMLS_CC); +#else + return message_handlers->read_property(msg, member, BP_VAR_R, NULL, + NULL PHP_PROTO_TSRMLS_CC); +#endif +} + // Reserved name bool is_reserved_name(const char* name); bool is_valid_constant_name(const char* name); diff --git a/php/ext/google/protobuf/storage.c b/php/ext/google/protobuf/storage.c index 4830e15f..e7910c85 100644 --- a/php/ext/google/protobuf/storage.c +++ b/php/ext/google/protobuf/storage.c @@ -560,11 +560,6 @@ static size_t align_up_to(size_t offset, size_t granularity) { return (offset + granularity - 1) & ~(granularity - 1); } -static void* slot_memory(MessageLayout* layout, const void* storage, - const upb_fielddef* field) { - return ((uint8_t*)storage) + layout->fields[upb_fielddef_index(field)].offset; -} - static uint32_t* slot_oneof_case(MessageLayout* layout, const void* storage, const upb_fielddef* field) { return (uint32_t*)(((uint8_t*)storage) + @@ -576,6 +571,11 @@ static int slot_property_cache(MessageLayout* layout, const void* storage, return layout->fields[upb_fielddef_index(field)].cache_index; } +void* slot_memory(MessageLayout* layout, const void* storage, + const upb_fielddef* field) { + return ((uint8_t*)storage) + layout->fields[upb_fielddef_index(field)].offset; +} + MessageLayout* create_layout(const upb_msgdef* msgdef) { MessageLayout* layout = ALLOC(MessageLayout); int nfields = upb_msgdef_numfields(msgdef); @@ -583,9 +583,12 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) { upb_msg_oneof_iter oit; size_t off = 0; int i = 0; + + // Reserve space for unknown fields. + off += sizeof(void*); + TSRMLS_FETCH(); Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msgdef)); - layout->fields = ALLOC_N(MessageField, nfields); for (upb_msg_field_begin(&it, msgdef); !upb_msg_field_done(&it); @@ -744,6 +747,10 @@ void layout_init(MessageLayout* layout, void* storage, zend_object* object PHP_PROTO_TSRMLS_DC) { int i; upb_msg_field_iter it; + + // Init unknown fields + memset(storage, 0, sizeof(void*)); + for (upb_msg_field_begin(&it, layout->msgdef), i = 0; !upb_msg_field_done(&it); upb_msg_field_next(&it), i++) { const upb_fielddef* field = upb_msg_iter_field(&it); @@ -856,12 +863,41 @@ void layout_set(MessageLayout* layout, MessageHeader* header, zval* property_ptr = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory); if (EXPECTED(property_ptr != val)) { + zend_class_entry *subce = NULL; + zval converted_value; + + if (upb_fielddef_ismap(field)) { + const upb_msgdef* mapmsg = upb_fielddef_msgsubdef(field); + const upb_fielddef* keyfield = upb_msgdef_ntof(mapmsg, "key", 3); + const upb_fielddef* valuefield = upb_msgdef_ntof(mapmsg, "value", 5); + if (upb_fielddef_descriptortype(valuefield) == + UPB_DESCRIPTOR_TYPE_MESSAGE) { + const upb_msgdef* submsg = upb_fielddef_msgsubdef(valuefield); + Descriptor* subdesc = + UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(submsg)); + subce = subdesc->klass; + } + check_map_field(subce, upb_fielddef_descriptortype(keyfield), + upb_fielddef_descriptortype(valuefield), val, + &converted_value); + } else { + if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) { + const upb_msgdef* submsg = upb_fielddef_msgsubdef(field); + Descriptor* subdesc = + UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(submsg)); + subce = subdesc->klass; + } + + check_repeated_field(subce, upb_fielddef_descriptortype(field), val, + &converted_value); + } #if PHP_MAJOR_VERSION < 7 - REPLACE_ZVAL_VALUE((zval**)memory, val, 1); + REPLACE_ZVAL_VALUE((zval**)memory, &converted_value, 1); #else - php_proto_zval_ptr_dtor(property_ptr); - ZVAL_ZVAL(property_ptr, val, 1, 0); + php_proto_zval_ptr_dtor(property_ptr); + ZVAL_ZVAL(property_ptr, &converted_value, 1, 0); #endif + zval_dtor(&converted_value); } } else { upb_fieldtype_t type = upb_fielddef_type(field); diff --git a/php/ext/google/protobuf/type_check.c b/php/ext/google/protobuf/type_check.c index fada8d6a..f588774c 100644 --- a/php/ext/google/protobuf/type_check.c +++ b/php/ext/google/protobuf/type_check.c @@ -428,21 +428,15 @@ PHP_METHOD(Util, checkMessage) { RETURN_ZVAL(val, 1, 0); } -PHP_METHOD(Util, checkRepeatedField) { - zval* val; - PHP_PROTO_LONG type; - const zend_class_entry* klass = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl|C", &val, &type, - &klass) == FAILURE) { - return; - } - +void check_repeated_field(const zend_class_entry* klass, PHP_PROTO_LONG type, + zval* val, zval* return_value) { #if PHP_MAJOR_VERSION >= 7 if (Z_ISREF_P(val)) { ZVAL_DEREF(val); } #endif + TSRMLS_FETCH(); if (Z_TYPE_P(val) == IS_ARRAY) { HashTable* table = HASH_OF(val); HashPosition pointer; @@ -492,24 +486,28 @@ PHP_METHOD(Util, checkRepeatedField) { zend_error(E_USER_ERROR, "Incorrect repeated field type."); return; } - } -PHP_METHOD(Util, checkMapField) { +PHP_METHOD(Util, checkRepeatedField) { zval* val; - PHP_PROTO_LONG key_type, value_type; + PHP_PROTO_LONG type; const zend_class_entry* klass = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zll|C", &val, &key_type, - &value_type, &klass) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl|C", &val, &type, + &klass) == FAILURE) { return; } + RETURN_ZVAL(val, 1, 0); +} +void check_map_field(const zend_class_entry* klass, PHP_PROTO_LONG key_type, + PHP_PROTO_LONG value_type, zval* val, zval* return_value) { #if PHP_MAJOR_VERSION >= 7 if (Z_ISREF_P(val)) { ZVAL_DEREF(val); } #endif + TSRMLS_FETCH(); if (Z_TYPE_P(val) == IS_ARRAY) { HashTable* table = Z_ARRVAL_P(val); HashPosition pointer; @@ -565,3 +563,14 @@ PHP_METHOD(Util, checkMapField) { return; } } + +PHP_METHOD(Util, checkMapField) { + zval* val; + PHP_PROTO_LONG key_type, value_type; + const zend_class_entry* klass = NULL; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zll|C", &val, &key_type, + &value_type, &klass) == FAILURE) { + return; + } + RETURN_ZVAL(val, 1, 0); +} diff --git a/php/ext/google/protobuf/upb.c b/php/ext/google/protobuf/upb.c index d701dcba..c02a5ce4 100644 --- a/php/ext/google/protobuf/upb.c +++ b/php/ext/google/protobuf/upb.c @@ -2,6 +2,585 @@ #include "upb.h" +/* Maps descriptor type -> upb field type. */ +static const uint8_t upb_desctype_to_fieldtype[] = { + UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */ + UPB_TYPE_DOUBLE, /* DOUBLE */ + UPB_TYPE_FLOAT, /* FLOAT */ + UPB_TYPE_INT64, /* INT64 */ + UPB_TYPE_UINT64, /* UINT64 */ + UPB_TYPE_INT32, /* INT32 */ + UPB_TYPE_UINT64, /* FIXED64 */ + UPB_TYPE_UINT32, /* FIXED32 */ + UPB_TYPE_BOOL, /* BOOL */ + UPB_TYPE_STRING, /* STRING */ + UPB_TYPE_MESSAGE, /* GROUP */ + UPB_TYPE_MESSAGE, /* MESSAGE */ + UPB_TYPE_BYTES, /* BYTES */ + UPB_TYPE_UINT32, /* UINT32 */ + UPB_TYPE_ENUM, /* ENUM */ + UPB_TYPE_INT32, /* SFIXED32 */ + UPB_TYPE_INT64, /* SFIXED64 */ + UPB_TYPE_INT32, /* SINT32 */ + UPB_TYPE_INT64, /* SINT64 */ +}; + +/* Data pertaining to the parse. */ +typedef struct { + upb_env *env; + /* Current decoding pointer. Points to the beginning of a field until we + * have finished decoding the whole field. */ + const char *ptr; +} upb_decstate; + +/* Data pertaining to a single message frame. */ +typedef struct { + const char *limit; + int32_t group_number; /* 0 if we are not parsing a group. */ + + /* These members are unset for an unknown group frame. */ + char *msg; + const upb_msglayout_msginit_v1 *m; +} upb_decframe; + +#define CHK(x) if (!(x)) { return false; } + +static bool upb_skip_unknowngroup(upb_decstate *d, int field_number, + const char *limit); +static bool upb_decode_message(upb_decstate *d, const char *limit, + int group_number, char *msg, + const upb_msglayout_msginit_v1 *l); + +static bool upb_decode_varint(const char **ptr, const char *limit, + uint64_t *val) { + uint8_t byte; + int bitpos = 0; + const char *p = *ptr; + *val = 0; + + do { + CHK(bitpos < 70 && p < limit); + byte = *p; + *val |= (uint64_t)(byte & 0x7F) << bitpos; + p++; + bitpos += 7; + } while (byte & 0x80); + + *ptr = p; + return true; +} + +static bool upb_decode_varint32(const char **ptr, const char *limit, + uint32_t *val) { + uint64_t u64; + CHK(upb_decode_varint(ptr, limit, &u64) && u64 <= UINT32_MAX); + *val = u64; + return true; +} + +static bool upb_decode_64bit(const char **ptr, const char *limit, + uint64_t *val) { + CHK(limit - *ptr >= 8); + memcpy(val, *ptr, 8); + *ptr += 8; + return true; +} + +static bool upb_decode_32bit(const char **ptr, const char *limit, + uint32_t *val) { + CHK(limit - *ptr >= 4); + memcpy(val, *ptr, 4); + *ptr += 4; + return true; +} + +static bool upb_decode_tag(const char **ptr, const char *limit, + int *field_number, int *wire_type) { + uint32_t tag = 0; + CHK(upb_decode_varint32(ptr, limit, &tag)); + *field_number = tag >> 3; + *wire_type = tag & 7; + return true; +} + +static int32_t upb_zzdecode_32(uint32_t n) { + return (n >> 1) ^ -(int32_t)(n & 1); +} + +static int64_t upb_zzdecode_64(uint64_t n) { + return (n >> 1) ^ -(int64_t)(n & 1); +} + +static bool upb_decode_string(const char **ptr, const char *limit, + upb_stringview *val) { + uint32_t len; + + CHK(upb_decode_varint32(ptr, limit, &len) && + len < INT32_MAX && + limit - *ptr >= (int32_t)len); + + *val = upb_stringview_make(*ptr, len); + *ptr += len; + return true; +} + +static void upb_set32(void *msg, size_t ofs, uint32_t val) { + memcpy((char*)msg + ofs, &val, sizeof(val)); +} + +static bool upb_append_unknown(upb_decstate *d, upb_decframe *frame, + const char *start) { + UPB_UNUSED(d); + UPB_UNUSED(frame); + UPB_UNUSED(start); + return true; +} + +static bool upb_skip_unknownfielddata(upb_decstate *d, upb_decframe *frame, + int field_number, int wire_type) { + switch (wire_type) { + case UPB_WIRE_TYPE_VARINT: { + uint64_t val; + return upb_decode_varint(&d->ptr, frame->limit, &val); + } + case UPB_WIRE_TYPE_32BIT: { + uint32_t val; + return upb_decode_32bit(&d->ptr, frame->limit, &val); + } + case UPB_WIRE_TYPE_64BIT: { + uint64_t val; + return upb_decode_64bit(&d->ptr, frame->limit, &val); + } + case UPB_WIRE_TYPE_DELIMITED: { + upb_stringview val; + return upb_decode_string(&d->ptr, frame->limit, &val); + } + case UPB_WIRE_TYPE_START_GROUP: + return upb_skip_unknowngroup(d, field_number, frame->limit); + case UPB_WIRE_TYPE_END_GROUP: + CHK(field_number == frame->group_number); + frame->limit = d->ptr; + return true; + } + return false; +} + +static bool upb_array_grow(upb_array *arr, size_t elements) { + size_t needed = arr->len + elements; + size_t new_size = UPB_MAX(arr->size, 8); + size_t new_bytes; + size_t old_bytes; + void *new_data; + + while (new_size < needed) { + new_size *= 2; + } + + old_bytes = arr->len * arr->element_size; + new_bytes = new_size * arr->element_size; + new_data = upb_realloc(arr->alloc, arr->data, old_bytes, new_bytes); + CHK(new_data); + + arr->data = new_data; + arr->size = new_size; + return true; +} + +static void *upb_array_reserve(upb_array *arr, size_t elements) { + if (arr->size - arr->len < elements) { + CHK(upb_array_grow(arr, elements)); + } + return (char*)arr->data + (arr->len * arr->element_size); +} + +static void *upb_array_add(upb_array *arr, size_t elements) { + void *ret = upb_array_reserve(arr, elements); + arr->len += elements; + return ret; +} + +static upb_array *upb_getarr(upb_decframe *frame, + const upb_msglayout_fieldinit_v1 *field) { + UPB_ASSERT(field->label == UPB_LABEL_REPEATED); + return *(upb_array**)&frame->msg[field->offset]; +} + +static upb_array *upb_getorcreatearr(upb_decstate *d, + upb_decframe *frame, + const upb_msglayout_fieldinit_v1 *field) { + upb_array *arr = upb_getarr(frame, field); + + if (!arr) { + arr = upb_env_malloc(d->env, sizeof(*arr)); + if (!arr) { + return NULL; + } + upb_array_init(arr, upb_desctype_to_fieldtype[field->type], + upb_arena_alloc(upb_env_arena(d->env))); + *(upb_array**)&frame->msg[field->offset] = arr; + } + + return arr; +} + +static void upb_sethasbit(upb_decframe *frame, + const upb_msglayout_fieldinit_v1 *field) { + UPB_ASSERT(field->hasbit != UPB_NO_HASBIT); + frame->msg[field->hasbit / 8] |= (1 << (field->hasbit % 8)); +} + +static void upb_setoneofcase(upb_decframe *frame, + const upb_msglayout_fieldinit_v1 *field) { + UPB_ASSERT(field->oneof_index != UPB_NOT_IN_ONEOF); + upb_set32(frame->msg, frame->m->oneofs[field->oneof_index].case_offset, + field->number); +} + +static char *upb_decode_prepareslot(upb_decstate *d, + upb_decframe *frame, + const upb_msglayout_fieldinit_v1 *field) { + char *field_mem = frame->msg + field->offset; + upb_array *arr; + + if (field->label == UPB_LABEL_REPEATED) { + arr = upb_getorcreatearr(d, frame, field); + field_mem = upb_array_reserve(arr, 1); + } + + return field_mem; +} + +static void upb_decode_setpresent(upb_decframe *frame, + const upb_msglayout_fieldinit_v1 *field) { + if (field->label == UPB_LABEL_REPEATED) { + upb_array *arr = upb_getarr(frame, field); + UPB_ASSERT(arr->len < arr->size); + arr->len++; + } else if (field->oneof_index != UPB_NOT_IN_ONEOF) { + upb_setoneofcase(frame, field); + } else if (field->hasbit != UPB_NO_HASBIT) { + upb_sethasbit(frame, field); + } +} + +static bool upb_decode_submsg(upb_decstate *d, + upb_decframe *frame, + const char *limit, + const upb_msglayout_fieldinit_v1 *field, + int group_number) { + char *submsg = *(void**)&frame->msg[field->offset]; + const upb_msglayout_msginit_v1 *subm; + + UPB_ASSERT(field->submsg_index != UPB_NO_SUBMSG); + subm = frame->m->submsgs[field->submsg_index]; + UPB_ASSERT(subm); + + if (!submsg) { + submsg = upb_env_malloc(d->env, upb_msg_sizeof((upb_msglayout *)subm)); + CHK(submsg); + submsg = upb_msg_init( + submsg, (upb_msglayout*)subm, upb_arena_alloc(upb_env_arena(d->env))); + *(void**)&frame->msg[field->offset] = submsg; + } + + upb_decode_message(d, limit, group_number, submsg, subm); + + return true; +} + +static bool upb_decode_varintfield(upb_decstate *d, upb_decframe *frame, + const char *field_start, + const upb_msglayout_fieldinit_v1 *field) { + uint64_t val; + void *field_mem; + + field_mem = upb_decode_prepareslot(d, frame, field); + CHK(field_mem); + CHK(upb_decode_varint(&d->ptr, frame->limit, &val)); + + switch ((upb_descriptortype_t)field->type) { + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + memcpy(field_mem, &val, sizeof(val)); + break; + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_ENUM: { + uint32_t val32 = val; + memcpy(field_mem, &val32, sizeof(val32)); + break; + } + case UPB_DESCRIPTOR_TYPE_BOOL: { + bool valbool = val != 0; + memcpy(field_mem, &valbool, sizeof(valbool)); + break; + } + case UPB_DESCRIPTOR_TYPE_SINT32: { + int32_t decoded = upb_zzdecode_32(val); + memcpy(field_mem, &decoded, sizeof(decoded)); + break; + } + case UPB_DESCRIPTOR_TYPE_SINT64: { + int64_t decoded = upb_zzdecode_64(val); + memcpy(field_mem, &decoded, sizeof(decoded)); + break; + } + default: + return upb_append_unknown(d, frame, field_start); + } + + upb_decode_setpresent(frame, field); + return true; +} + +static bool upb_decode_64bitfield(upb_decstate *d, upb_decframe *frame, + const char *field_start, + const upb_msglayout_fieldinit_v1 *field) { + void *field_mem; + uint64_t val; + + field_mem = upb_decode_prepareslot(d, frame, field); + CHK(field_mem); + CHK(upb_decode_64bit(&d->ptr, frame->limit, &val)); + + switch ((upb_descriptortype_t)field->type) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + case UPB_DESCRIPTOR_TYPE_FIXED64: + case UPB_DESCRIPTOR_TYPE_SFIXED64: + memcpy(field_mem, &val, sizeof(val)); + break; + default: + return upb_append_unknown(d, frame, field_start); + } + + upb_decode_setpresent(frame, field); + return true; +} + +static bool upb_decode_32bitfield(upb_decstate *d, upb_decframe *frame, + const char *field_start, + const upb_msglayout_fieldinit_v1 *field) { + void *field_mem; + uint32_t val; + + field_mem = upb_decode_prepareslot(d, frame, field); + CHK(field_mem); + CHK(upb_decode_32bit(&d->ptr, frame->limit, &val)); + + switch ((upb_descriptortype_t)field->type) { + case UPB_DESCRIPTOR_TYPE_FLOAT: + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + memcpy(field_mem, &val, sizeof(val)); + break; + default: + return upb_append_unknown(d, frame, field_start); + } + + upb_decode_setpresent(frame, field); + return true; +} + +static bool upb_decode_fixedpacked(upb_array *arr, upb_stringview data, + int elem_size) { + int elements = data.size / elem_size; + void *field_mem; + + CHK((size_t)(elements * elem_size) == data.size); + field_mem = upb_array_add(arr, elements); + CHK(field_mem); + memcpy(field_mem, data.data, data.size); + return true; +} + +static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame, + const char *field_start, + const upb_msglayout_fieldinit_v1 *field, + upb_stringview val) { + upb_array *arr = upb_getorcreatearr(d, frame, field); + +#define VARINT_CASE(ctype, decode) { \ + const char *ptr = val.data; \ + const char *limit = ptr + val.size; \ + while (ptr < limit) { \ + uint64_t val; \ + void *field_mem; \ + ctype decoded; \ + CHK(upb_decode_varint(&ptr, limit, &val)); \ + decoded = (decode)(val); \ + field_mem = upb_array_add(arr, 1); \ + CHK(field_mem); \ + memcpy(field_mem, &decoded, sizeof(ctype)); \ + } \ + return true; \ +} + + switch ((upb_descriptortype_t)field->type) { + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: { + void *field_mem = upb_array_add(arr, 1); + CHK(field_mem); + memcpy(field_mem, &val, sizeof(val)); + return true; + } + case UPB_DESCRIPTOR_TYPE_FLOAT: + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + return upb_decode_fixedpacked(arr, val, sizeof(int32_t)); + case UPB_DESCRIPTOR_TYPE_DOUBLE: + case UPB_DESCRIPTOR_TYPE_FIXED64: + case UPB_DESCRIPTOR_TYPE_SFIXED64: + return upb_decode_fixedpacked(arr, val, sizeof(int64_t)); + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_ENUM: + /* TODO: proto2 enum field that isn't in the enum. */ + VARINT_CASE(uint32_t, uint32_t); + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + VARINT_CASE(uint64_t, uint64_t); + case UPB_DESCRIPTOR_TYPE_BOOL: + VARINT_CASE(bool, bool); + case UPB_DESCRIPTOR_TYPE_SINT32: + VARINT_CASE(int32_t, upb_zzdecode_32); + case UPB_DESCRIPTOR_TYPE_SINT64: + VARINT_CASE(int64_t, upb_zzdecode_64); + case UPB_DESCRIPTOR_TYPE_MESSAGE: + CHK(val.size <= (size_t)(frame->limit - val.data)); + return upb_decode_submsg(d, frame, val.data + val.size, field, 0); + case UPB_DESCRIPTOR_TYPE_GROUP: + return upb_append_unknown(d, frame, field_start); + } +#undef VARINT_CASE + UPB_UNREACHABLE(); +} + +static bool upb_decode_delimitedfield(upb_decstate *d, upb_decframe *frame, + const char *field_start, + const upb_msglayout_fieldinit_v1 *field) { + upb_stringview val; + + CHK(upb_decode_string(&d->ptr, frame->limit, &val)); + + if (field->label == UPB_LABEL_REPEATED) { + return upb_decode_toarray(d, frame, field_start, field, val); + } else { + switch ((upb_descriptortype_t)field->type) { + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: { + void *field_mem = upb_decode_prepareslot(d, frame, field); + CHK(field_mem); + memcpy(field_mem, &val, sizeof(val)); + break; + } + case UPB_DESCRIPTOR_TYPE_MESSAGE: + CHK(val.size <= (size_t)(frame->limit - val.data)); + CHK(upb_decode_submsg(d, frame, val.data + val.size, field, 0)); + break; + default: + /* TODO(haberman): should we accept the last element of a packed? */ + return upb_append_unknown(d, frame, field_start); + } + upb_decode_setpresent(frame, field); + return true; + } +} + +static const upb_msglayout_fieldinit_v1 *upb_find_field( + const upb_msglayout_msginit_v1 *l, uint32_t field_number) { + /* Lots of optimization opportunities here. */ + int i; + for (i = 0; i < l->field_count; i++) { + if (l->fields[i].number == field_number) { + return &l->fields[i]; + } + } + + return NULL; /* Unknown field. */ +} + +static bool upb_decode_field(upb_decstate *d, upb_decframe *frame) { + int field_number; + int wire_type; + const char *field_start = d->ptr; + const upb_msglayout_fieldinit_v1 *field; + + CHK(upb_decode_tag(&d->ptr, frame->limit, &field_number, &wire_type)); + field = upb_find_field(frame->m, field_number); + + if (field) { + switch (wire_type) { + case UPB_WIRE_TYPE_VARINT: + return upb_decode_varintfield(d, frame, field_start, field); + case UPB_WIRE_TYPE_32BIT: + return upb_decode_32bitfield(d, frame, field_start, field); + case UPB_WIRE_TYPE_64BIT: + return upb_decode_64bitfield(d, frame, field_start, field); + case UPB_WIRE_TYPE_DELIMITED: + return upb_decode_delimitedfield(d, frame, field_start, field); + case UPB_WIRE_TYPE_START_GROUP: + CHK(field->type == UPB_DESCRIPTOR_TYPE_GROUP); + return upb_decode_submsg(d, frame, frame->limit, field, field_number); + case UPB_WIRE_TYPE_END_GROUP: + CHK(frame->group_number == field_number) + frame->limit = d->ptr; + return true; + default: + return false; + } + } else { + CHK(field_number != 0); + return upb_skip_unknownfielddata(d, frame, field_number, wire_type); + } +} + +static bool upb_skip_unknowngroup(upb_decstate *d, int field_number, + const char *limit) { + upb_decframe frame; + frame.msg = NULL; + frame.m = NULL; + frame.group_number = field_number; + frame.limit = limit; + + while (d->ptr < frame.limit) { + int wire_type; + int field_number; + + CHK(upb_decode_tag(&d->ptr, frame.limit, &field_number, &wire_type)); + CHK(upb_skip_unknownfielddata(d, &frame, field_number, wire_type)); + } + + return true; +} + +static bool upb_decode_message(upb_decstate *d, const char *limit, + int group_number, char *msg, + const upb_msglayout_msginit_v1 *l) { + upb_decframe frame; + frame.group_number = group_number; + frame.limit = limit; + frame.msg = msg; + frame.m = l; + + while (d->ptr < frame.limit) { + CHK(upb_decode_field(d, &frame)); + } + + return true; +} + +bool upb_decode(upb_stringview buf, void *msg, + const upb_msglayout_msginit_v1 *l, upb_env *env) { + upb_decstate state; + state.ptr = buf.data; + state.env = env; + + return upb_decode_message(&state, buf.data + buf.size, 0, msg, l); +} + +#undef CHK + + #include <ctype.h> #include <stdlib.h> #include <string.h> @@ -326,6 +905,7 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { v = upb_value_bool(true); upb_inttable_insert(&t, UPB_STARTMSG_SELECTOR, v); upb_inttable_insert(&t, UPB_ENDMSG_SELECTOR, v); + upb_inttable_insert(&t, UPB_UNKNOWN_SELECTOR, v); for(upb_msg_field_begin(&j, m); !upb_msg_field_done(&j); upb_msg_field_next(&j)) { @@ -2359,6 +2939,397 @@ bool upb_symtab_done(const upb_symtab_iter *iter) { const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) { return upb_value_getptr(upb_strtable_iter_value(&iter->iter)); } +/* We encode backwards, to avoid pre-computing lengths (one-pass encode). */ + + +#define UPB_PB_VARINT_MAX_LEN 10 +#define CHK(x) do { if (!(x)) { return false; } } while(0) + +/* Maps descriptor type -> upb field type. */ +static const uint8_t upb_desctype_to_fieldtype2[] = { + UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */ + UPB_TYPE_DOUBLE, /* DOUBLE */ + UPB_TYPE_FLOAT, /* FLOAT */ + UPB_TYPE_INT64, /* INT64 */ + UPB_TYPE_UINT64, /* UINT64 */ + UPB_TYPE_INT32, /* INT32 */ + UPB_TYPE_UINT64, /* FIXED64 */ + UPB_TYPE_UINT32, /* FIXED32 */ + UPB_TYPE_BOOL, /* BOOL */ + UPB_TYPE_STRING, /* STRING */ + UPB_TYPE_MESSAGE, /* GROUP */ + UPB_TYPE_MESSAGE, /* MESSAGE */ + UPB_TYPE_BYTES, /* BYTES */ + UPB_TYPE_UINT32, /* UINT32 */ + UPB_TYPE_ENUM, /* ENUM */ + UPB_TYPE_INT32, /* SFIXED32 */ + UPB_TYPE_INT64, /* SFIXED64 */ + UPB_TYPE_INT32, /* SINT32 */ + UPB_TYPE_INT64, /* SINT64 */ +}; + +static size_t upb_encode_varint(uint64_t val, char *buf) { + size_t i; + if (val < 128) { buf[0] = val; return 1; } + i = 0; + while (val) { + uint8_t byte = val & 0x7fU; + val >>= 7; + if (val) byte |= 0x80U; + buf[i++] = byte; + } + return i; +} + +static uint32_t upb_zzencode_32(int32_t n) { return (n << 1) ^ (n >> 31); } +static uint64_t upb_zzencode_64(int64_t n) { return (n << 1) ^ (n >> 63); } + +typedef struct { + upb_env *env; + char *buf, *ptr, *limit; +} upb_encstate; + +static size_t upb_roundup_pow2(size_t bytes) { + size_t ret = 128; + while (ret < bytes) { + ret *= 2; + } + return ret; +} + +static bool upb_encode_growbuffer(upb_encstate *e, size_t bytes) { + size_t old_size = e->limit - e->buf; + size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr)); + char *new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size); + CHK(new_buf); + + /* We want previous data at the end, realloc() put it at the beginning. */ + memmove(e->limit - old_size, e->buf, old_size); + + e->ptr = new_buf + new_size - (e->limit - e->ptr); + e->limit = new_buf + new_size; + e->buf = new_buf; + return true; +} + +/* Call to ensure that at least "bytes" bytes are available for writing at + * e->ptr. Returns false if the bytes could not be allocated. */ +static bool upb_encode_reserve(upb_encstate *e, size_t bytes) { + CHK(UPB_LIKELY((size_t)(e->ptr - e->buf) >= bytes) || + upb_encode_growbuffer(e, bytes)); + + e->ptr -= bytes; + return true; +} + +/* Writes the given bytes to the buffer, handling reserve/advance. */ +static bool upb_put_bytes(upb_encstate *e, const void *data, size_t len) { + CHK(upb_encode_reserve(e, len)); + memcpy(e->ptr, data, len); + return true; +} + +static bool upb_put_fixed64(upb_encstate *e, uint64_t val) { + /* TODO(haberman): byte-swap for big endian. */ + return upb_put_bytes(e, &val, sizeof(uint64_t)); +} + +static bool upb_put_fixed32(upb_encstate *e, uint32_t val) { + /* TODO(haberman): byte-swap for big endian. */ + return upb_put_bytes(e, &val, sizeof(uint32_t)); +} + +static bool upb_put_varint(upb_encstate *e, uint64_t val) { + size_t len; + char *start; + CHK(upb_encode_reserve(e, UPB_PB_VARINT_MAX_LEN)); + len = upb_encode_varint(val, e->ptr); + start = e->ptr + UPB_PB_VARINT_MAX_LEN - len; + memmove(start, e->ptr, len); + e->ptr = start; + return true; +} + +static bool upb_put_double(upb_encstate *e, double d) { + uint64_t u64; + UPB_ASSERT(sizeof(double) == sizeof(uint64_t)); + memcpy(&u64, &d, sizeof(uint64_t)); + return upb_put_fixed64(e, u64); +} + +static bool upb_put_float(upb_encstate *e, float d) { + uint32_t u32; + UPB_ASSERT(sizeof(float) == sizeof(uint32_t)); + memcpy(&u32, &d, sizeof(uint32_t)); + return upb_put_fixed32(e, u32); +} + +static uint32_t upb_readcase(const char *msg, const upb_msglayout_msginit_v1 *m, + int oneof_index) { + uint32_t ret; + memcpy(&ret, msg + m->oneofs[oneof_index].case_offset, sizeof(ret)); + return ret; +} + +static bool upb_readhasbit(const char *msg, + const upb_msglayout_fieldinit_v1 *f) { + UPB_ASSERT(f->hasbit != UPB_NO_HASBIT); + return msg[f->hasbit / 8] & (1 << (f->hasbit % 8)); +} + +static bool upb_put_tag(upb_encstate *e, int field_number, int wire_type) { + return upb_put_varint(e, (field_number << 3) | wire_type); +} + +static bool upb_put_fixedarray(upb_encstate *e, const upb_array *arr, + size_t size) { + size_t bytes = arr->len * size; + return upb_put_bytes(e, arr->data, bytes) && upb_put_varint(e, bytes); +} + +bool upb_encode_message(upb_encstate *e, const char *msg, + const upb_msglayout_msginit_v1 *m, + size_t *size); + +static bool upb_encode_array(upb_encstate *e, const char *field_mem, + const upb_msglayout_msginit_v1 *m, + const upb_msglayout_fieldinit_v1 *f) { + const upb_array *arr = *(const upb_array**)field_mem; + + if (arr == NULL || arr->len == 0) { + return true; + } + + UPB_ASSERT(arr->type == upb_desctype_to_fieldtype2[f->type]); + +#define VARINT_CASE(ctype, encode) { \ + ctype *start = arr->data; \ + ctype *ptr = start + arr->len; \ + size_t pre_len = e->limit - e->ptr; \ + do { \ + ptr--; \ + CHK(upb_put_varint(e, encode)); \ + } while (ptr != start); \ + CHK(upb_put_varint(e, e->limit - e->ptr - pre_len)); \ +} \ +break; \ +do { ; } while(0) + + switch (f->type) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + CHK(upb_put_fixedarray(e, arr, sizeof(double))); + break; + case UPB_DESCRIPTOR_TYPE_FLOAT: + CHK(upb_put_fixedarray(e, arr, sizeof(float))); + break; + case UPB_DESCRIPTOR_TYPE_SFIXED64: + case UPB_DESCRIPTOR_TYPE_FIXED64: + CHK(upb_put_fixedarray(e, arr, sizeof(uint64_t))); + break; + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + CHK(upb_put_fixedarray(e, arr, sizeof(uint32_t))); + break; + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + VARINT_CASE(uint64_t, *ptr); + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_ENUM: + VARINT_CASE(uint32_t, *ptr); + case UPB_DESCRIPTOR_TYPE_BOOL: + VARINT_CASE(bool, *ptr); + case UPB_DESCRIPTOR_TYPE_SINT32: + VARINT_CASE(int32_t, upb_zzencode_32(*ptr)); + case UPB_DESCRIPTOR_TYPE_SINT64: + VARINT_CASE(int64_t, upb_zzencode_64(*ptr)); + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: { + upb_stringview *start = arr->data; + upb_stringview *ptr = start + arr->len; + do { + ptr--; + CHK(upb_put_bytes(e, ptr->data, ptr->size) && + upb_put_varint(e, ptr->size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)); + } while (ptr != start); + return true; + } + case UPB_DESCRIPTOR_TYPE_GROUP: { + void **start = arr->data; + void **ptr = start + arr->len; + const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; + do { + size_t size; + ptr--; + CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) && + upb_encode_message(e, *ptr, subm, &size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP)); + } while (ptr != start); + return true; + } + case UPB_DESCRIPTOR_TYPE_MESSAGE: { + void **start = arr->data; + void **ptr = start + arr->len; + const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; + do { + size_t size; + ptr--; + CHK(upb_encode_message(e, *ptr, subm, &size) && + upb_put_varint(e, size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)); + } while (ptr != start); + return true; + } + } +#undef VARINT_CASE + + /* We encode all primitive arrays as packed, regardless of what was specified + * in the .proto file. Could special case 1-sized arrays. */ + CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED)); + return true; +} + +static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem, + const upb_msglayout_msginit_v1 *m, + const upb_msglayout_fieldinit_v1 *f, + bool is_proto3) { + bool skip_zero_value = is_proto3 && f->oneof_index == UPB_NOT_IN_ONEOF; + +#define CASE(ctype, type, wire_type, encodeval) do { \ + ctype val = *(ctype*)field_mem; \ + if (skip_zero_value && val == 0) { \ + return true; \ + } \ + return upb_put_ ## type(e, encodeval) && \ + upb_put_tag(e, f->number, wire_type); \ +} while(0) + + switch (f->type) { + case UPB_DESCRIPTOR_TYPE_DOUBLE: + CASE(double, double, UPB_WIRE_TYPE_64BIT, val); + case UPB_DESCRIPTOR_TYPE_FLOAT: + CASE(float, float, UPB_WIRE_TYPE_32BIT, val); + case UPB_DESCRIPTOR_TYPE_INT64: + case UPB_DESCRIPTOR_TYPE_UINT64: + CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val); + case UPB_DESCRIPTOR_TYPE_UINT32: + case UPB_DESCRIPTOR_TYPE_INT32: + case UPB_DESCRIPTOR_TYPE_ENUM: + CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val); + case UPB_DESCRIPTOR_TYPE_SFIXED64: + case UPB_DESCRIPTOR_TYPE_FIXED64: + CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val); + case UPB_DESCRIPTOR_TYPE_FIXED32: + case UPB_DESCRIPTOR_TYPE_SFIXED32: + CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val); + case UPB_DESCRIPTOR_TYPE_BOOL: + CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val); + case UPB_DESCRIPTOR_TYPE_SINT32: + CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_32(val)); + case UPB_DESCRIPTOR_TYPE_SINT64: + CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_64(val)); + case UPB_DESCRIPTOR_TYPE_STRING: + case UPB_DESCRIPTOR_TYPE_BYTES: { + upb_stringview view = *(upb_stringview*)field_mem; + if (skip_zero_value && view.size == 0) { + return true; + } + return upb_put_bytes(e, view.data, view.size) && + upb_put_varint(e, view.size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); + } + case UPB_DESCRIPTOR_TYPE_GROUP: { + size_t size; + void *submsg = *(void**)field_mem; + const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; + if (skip_zero_value && submsg == NULL) { + return true; + } + return upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) && + upb_encode_message(e, submsg, subm, &size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP); + } + case UPB_DESCRIPTOR_TYPE_MESSAGE: { + size_t size; + void *submsg = *(void**)field_mem; + const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index]; + if (skip_zero_value && submsg == NULL) { + return true; + } + return upb_encode_message(e, submsg, subm, &size) && + upb_put_varint(e, size) && + upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); + } + } +#undef CASE + UPB_UNREACHABLE(); +} + +bool upb_encode_hasscalarfield(const char *msg, + const upb_msglayout_msginit_v1 *m, + const upb_msglayout_fieldinit_v1 *f) { + if (f->oneof_index != UPB_NOT_IN_ONEOF) { + return upb_readcase(msg, m, f->oneof_index) == f->number; + } else if (m->is_proto2) { + return upb_readhasbit(msg, f); + } else { + /* For proto3, we'll test for the field being empty later. */ + return true; + } +} + +bool upb_encode_message(upb_encstate* e, const char *msg, + const upb_msglayout_msginit_v1 *m, + size_t *size) { + int i; + char *buf_end = e->ptr; + + if (msg == NULL) { + return true; + } + + for (i = m->field_count - 1; i >= 0; i--) { + const upb_msglayout_fieldinit_v1 *f = &m->fields[i]; + + if (f->label == UPB_LABEL_REPEATED) { + CHK(upb_encode_array(e, msg + f->offset, m, f)); + } else { + if (upb_encode_hasscalarfield(msg, m, f)) { + CHK(upb_encode_scalarfield(e, msg + f->offset, m, f, !m->is_proto2)); + } + } + } + + *size = buf_end - e->ptr; + return true; +} + +char *upb_encode(const void *msg, const upb_msglayout_msginit_v1 *m, + upb_env *env, size_t *size) { + upb_encstate e; + e.env = env; + e.buf = NULL; + e.limit = NULL; + e.ptr = NULL; + + if (!upb_encode_message(&e, msg, m, size)) { + *size = 0; + return NULL; + } + + *size = e.limit - e.ptr; + + if (*size == 0) { + static char ch; + return &ch; + } else { + UPB_ASSERT(e.ptr); + return e.ptr; + } +} + +#undef CHK /* ** TODO(haberman): it's unclear whether a lot of the consistency checks should ** UPB_ASSERT() or return false. @@ -2730,6 +3701,12 @@ SETTER(endseq, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSEQ) #undef SETTER +bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func, + upb_handlerattr *attr) { + return doset(h, UPB_UNKNOWN_SELECTOR, NULL, UPB_HANDLER_INT32, + (upb_func *)func, attr); +} + bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func, upb_handlerattr *attr) { return doset(h, UPB_STARTMSG_SELECTOR, NULL, UPB_HANDLER_INT32, @@ -3079,7 +4056,8 @@ bool upb_fieldtype_mapkeyok(upb_fieldtype_t type) { void *upb_array_pack(const upb_array *arr, void *p, size_t *ofs, size_t size); void *upb_map_pack(const upb_map *map, void *p, size_t *ofs, size_t size); -#define CHARPTR_AT(msg, ofs) ((char*)msg + ofs) +#define PTR_AT(msg, ofs, type) (type*)((char*)msg + ofs) +#define VOIDPTR_AT(msg, ofs) PTR_AT(msg, ofs, void) #define ENCODE_MAX_NESTING 64 #define CHECK_TRUE(x) if (!(x)) { return false; } @@ -3121,12 +4099,20 @@ static size_t upb_msgval_sizeof(upb_fieldtype_t type) { case UPB_TYPE_MESSAGE: return sizeof(void*); case UPB_TYPE_STRING: - return sizeof(char*) + sizeof(size_t); + return sizeof(upb_stringview); } UPB_UNREACHABLE(); } -static uint8_t upb_msg_fieldsize(const upb_fielddef *f) { +static uint8_t upb_msg_fieldsize(const upb_msglayout_fieldinit_v1 *field) { + if (field->label == UPB_LABEL_REPEATED) { + return sizeof(void*); + } else { + return upb_msgval_sizeof(field->type); + } +} + +static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) { if (upb_fielddef_isseq(f)) { return sizeof(void*); } else { @@ -3170,7 +4156,6 @@ static upb_ctype_t upb_fieldtotabtype(upb_fieldtype_t type) { } static upb_msgval upb_msgval_fromdefault(const upb_fielddef *f) { - /* TODO(haberman): improve/optimize this (maybe use upb_msgval in fielddef) */ switch (upb_fielddef_type(f)) { case UPB_TYPE_FLOAT: return upb_msgval_float(upb_fielddef_defaultfloat(f)); @@ -3182,7 +4167,7 @@ static upb_msgval upb_msgval_fromdefault(const upb_fielddef *f) { case UPB_TYPE_BYTES: { size_t len; const char *ptr = upb_fielddef_defaultstr(f, &len); - return upb_msgval_str(ptr, len); + return upb_msgval_makestr(ptr, len); } case UPB_TYPE_MESSAGE: return upb_msgval_msg(NULL); @@ -3205,63 +4190,44 @@ static upb_msgval upb_msgval_fromdefault(const upb_fielddef *f) { /** upb_msglayout *************************************************************/ struct upb_msglayout { - upb_msgfactory *factory; - const upb_msgdef *msgdef; - size_t size; - size_t extdict_offset; - void *default_msg; - uint32_t *field_offsets; - uint32_t *case_offsets; - uint32_t *hasbits; - bool has_extdict; - uint8_t align; + struct upb_msglayout_msginit_v1 data; }; -static void upb_msg_checkfield(const upb_msglayout *l, const upb_fielddef *f) { - UPB_ASSERT(l->msgdef == upb_fielddef_containingtype(f)); -} - static void upb_msglayout_free(upb_msglayout *l) { - upb_gfree(l->default_msg); + upb_gfree(l->data.default_msg); upb_gfree(l); } -const upb_msgdef *upb_msglayout_msgdef(const upb_msglayout *l) { - return l->msgdef; -} - static size_t upb_msglayout_place(upb_msglayout *l, size_t size) { size_t ret; - l->size = align_up(l->size, size); - l->align = align_up(l->align, size); - ret = l->size; - l->size += size; + l->data.size = align_up(l->data.size, size); + ret = l->data.size; + l->data.size += size; return ret; } static uint32_t upb_msglayout_offset(const upb_msglayout *l, const upb_fielddef *f) { - return l->field_offsets[upb_fielddef_index(f)]; + return l->data.fields[upb_fielddef_index(f)].offset; } static uint32_t upb_msglayout_hasbit(const upb_msglayout *l, const upb_fielddef *f) { - return l->hasbits[upb_fielddef_index(f)]; + return l->data.fields[upb_fielddef_index(f)].hasbit; } -static bool upb_msglayout_initdefault(upb_msglayout *l) { - const upb_msgdef *m = l->msgdef; +static bool upb_msglayout_initdefault(upb_msglayout *l, const upb_msgdef *m) { upb_msg_field_iter it; - if (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2 && l->size) { + if (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2 && l->data.size) { /* Allocate default message and set default values in it. */ - l->default_msg = upb_gmalloc(l->size); - if (!l->default_msg) { + l->data.default_msg = upb_gmalloc(l->data.size); + if (!l->data.default_msg) { return false; } - memset(l->default_msg, 0, l->size); + memset(l->data.default_msg, 0, l->data.size); for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); upb_msg_field_next(&it)) { @@ -3271,10 +4237,14 @@ static bool upb_msglayout_initdefault(upb_msglayout *l) { continue; } + /* TODO(haberman): handle strings. */ if (!upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f) && !upb_fielddef_isseq(f)) { - upb_msg_set(l->default_msg, f, upb_msgval_fromdefault(f), l); + upb_msg_set(l->data.default_msg, + upb_fielddef_index(f), + upb_msgval_fromdefault(f), + l); } } } @@ -3287,22 +4257,46 @@ static upb_msglayout *upb_msglayout_new(const upb_msgdef *m) { upb_msg_oneof_iter oit; upb_msglayout *l; size_t hasbit; - size_t array_size = upb_msgdef_numfields(m) + upb_msgdef_numoneofs(m); + size_t submsg_count = 0; + const upb_msglayout_msginit_v1 **submsgs; + upb_msglayout_fieldinit_v1 *fields; + upb_msglayout_oneofinit_v1 *oneofs; - if (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2) { - array_size += upb_msgdef_numfields(m); /* hasbits. */ + for (upb_msg_field_begin(&it, m); + !upb_msg_field_done(&it); + upb_msg_field_next(&it)) { + const upb_fielddef* f = upb_msg_iter_field(&it); + if (upb_fielddef_issubmsg(f)) { + submsg_count++; + } } - l = upb_gmalloc(sizeof(*l) + (sizeof(uint32_t) * array_size)); + l = upb_gmalloc(sizeof(*l)); if (!l) return NULL; memset(l, 0, sizeof(*l)); - l->msgdef = m; - l->align = 1; - l->field_offsets = (uint32_t*)CHARPTR_AT(l, sizeof(*l)); - l->case_offsets = l->field_offsets + upb_msgdef_numfields(m); - l->hasbits = l->case_offsets + upb_msgdef_numoneofs(m); + fields = upb_gmalloc(upb_msgdef_numfields(m) * sizeof(*fields)); + submsgs = upb_gmalloc(submsg_count * sizeof(*submsgs)); + oneofs = upb_gmalloc(upb_msgdef_numoneofs(m) * sizeof(*oneofs)); + + if ((!fields && upb_msgdef_numfields(m)) || + (!submsgs && submsg_count) || + (!oneofs && upb_msgdef_numoneofs(m))) { + /* OOM. */ + upb_gfree(l); + upb_gfree(fields); + upb_gfree(submsgs); + upb_gfree(oneofs); + return NULL; + } + + l->data.field_count = upb_msgdef_numfields(m); + l->data.oneof_count = upb_msgdef_numoneofs(m); + l->data.fields = fields; + l->data.submsgs = submsgs; + l->data.oneofs = oneofs; + l->data.is_proto2 = (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2); /* Allocate data offsets in three stages: * @@ -3313,74 +4307,75 @@ static upb_msglayout *upb_msglayout_new(const upb_msgdef *m) { * OPT: There is a lot of room for optimization here to minimize the size. */ - /* Allocate hasbits. Start at sizeof(void*) for upb_alloc*. */ - for (upb_msg_field_begin(&it, m), hasbit = sizeof(void*) * 8; + /* Allocate hasbits and set basic field attributes. */ + for (upb_msg_field_begin(&it, m), hasbit = 0; !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* f = upb_msg_iter_field(&it); + upb_msglayout_fieldinit_v1 *field = &fields[upb_fielddef_index(f)]; + + field->number = upb_fielddef_number(f); + field->type = upb_fielddef_type(f); + field->label = upb_fielddef_label(f); + + if (upb_fielddef_containingoneof(f)) { + field->oneof_index = upb_oneofdef_index(upb_fielddef_containingoneof(f)); + } else { + field->oneof_index = UPB_NOT_IN_ONEOF; + } if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) { - l->hasbits[upb_fielddef_index(f)] = hasbit++; + field->hasbit = hasbit++; } } /* Account for space used by hasbits. */ - l->size = div_round_up(hasbit, 8); + l->data.size = div_round_up(hasbit, 8); /* Allocate non-oneof fields. */ for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* f = upb_msg_iter_field(&it); - size_t field_size = upb_msg_fieldsize(f); + size_t field_size = upb_msg_fielddefsize(f); size_t index = upb_fielddef_index(f); - if (upb_fielddef_containingoneof(f)) { /* Oneofs are handled separately below. */ continue; } - l->field_offsets[index] = upb_msglayout_place(l, field_size); + fields[index].offset = upb_msglayout_place(l, field_size); } /* Allocate oneof fields. Each oneof field consists of a uint32 for the case * and space for the actual data. */ for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit); upb_msg_oneof_next(&oit)) { - const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit); + const upb_oneofdef* o = upb_msg_iter_oneof(&oit); upb_oneof_iter fit; + size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */ + upb_msglayout_oneofinit_v1 *oneof = &oneofs[upb_oneofdef_index(o)]; size_t field_size = 0; - size_t case_offset; - size_t val_offset; /* Calculate field size: the max of all field sizes. */ - for (upb_oneof_begin(&fit, oneof); + for (upb_oneof_begin(&fit, o); !upb_oneof_done(&fit); upb_oneof_next(&fit)) { const upb_fielddef* f = upb_oneof_iter_field(&fit); - field_size = UPB_MAX(field_size, upb_msg_fieldsize(f)); + field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f)); } /* Align and allocate case offset. */ - case_offset = upb_msglayout_place(l, case_size); - val_offset = upb_msglayout_place(l, field_size); - - l->case_offsets[upb_oneofdef_index(oneof)] = case_offset; - - /* Assign all fields in the oneof this same offset. */ - for (upb_oneof_begin(&fit, oneof); !upb_oneof_done(&fit); - upb_oneof_next(&fit)) { - const upb_fielddef* f = upb_oneof_iter_field(&fit); - l->field_offsets[upb_fielddef_index(f)] = val_offset; - } + oneof->case_offset = upb_msglayout_place(l, case_size); + oneof->data_offset = upb_msglayout_place(l, field_size); } /* Size of the entire structure should be a multiple of its greatest - * alignment. */ - l->size = align_up(l->size, l->align); + * alignment. TODO: track overall alignment for real? */ + l->data.size = align_up(l->data.size, 8); - if (upb_msglayout_initdefault(l)) { + if (upb_msglayout_initdefault(l, m)) { return l; } else { upb_msglayout_free(l); @@ -3388,10 +4383,6 @@ static upb_msglayout *upb_msglayout_new(const upb_msgdef *m) { } } -upb_msgfactory *upb_msglayout_factory(const upb_msglayout *layout) { - return layout->factory; -} - /** upb_msgfactory ************************************************************/ @@ -3448,7 +4439,6 @@ const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f, upb_msglayout *l = upb_msglayout_new(m); upb_inttable_insertptr(&mutable_f->layouts, m, upb_value_ptr(l)); UPB_ASSERT(l); - l->factory = f; return l; } } @@ -3457,16 +4447,15 @@ const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f, void *upb_msg_startstr(void *msg, const void *hd, size_t size_hint) { uint32_t ofs = (uintptr_t)hd; - /* We pass NULL here because we know we can get away with it. */ - upb_alloc *alloc = upb_msg_alloc(msg, NULL); + upb_alloc *alloc = upb_msg_alloc(msg); upb_msgval val; UPB_UNUSED(size_hint); val = upb_msgval_read(msg, ofs, upb_msgval_sizeof(UPB_TYPE_STRING)); - upb_free(alloc, (void*)val.str.ptr); - val.str.ptr = NULL; - val.str.len = 0; + upb_free(alloc, (void*)val.str.data); + val.str.data = NULL; + val.str.size = 0; upb_msgval_write(msg, ofs, val, upb_msgval_sizeof(UPB_TYPE_STRING)); return msg; @@ -3475,23 +4464,22 @@ void *upb_msg_startstr(void *msg, const void *hd, size_t size_hint) { size_t upb_msg_str(void *msg, const void *hd, const char *ptr, size_t size, const upb_bufhandle *handle) { uint32_t ofs = (uintptr_t)hd; - /* We pass NULL here because we know we can get away with it. */ - upb_alloc *alloc = upb_msg_alloc(msg, NULL); + upb_alloc *alloc = upb_msg_alloc(msg); upb_msgval val; size_t newsize; UPB_UNUSED(handle); val = upb_msgval_read(msg, ofs, upb_msgval_sizeof(UPB_TYPE_STRING)); - newsize = val.str.len + size; - val.str.ptr = upb_realloc(alloc, (void*)val.str.ptr, val.str.len, newsize); + newsize = val.str.size + size; + val.str.data = upb_realloc(alloc, (void*)val.str.data, val.str.size, newsize); - if (!val.str.ptr) { + if (!val.str.data) { return false; } - memcpy((char*)val.str.ptr + val.str.len, ptr, size); - val.str.len = newsize; + memcpy((char*)val.str.data + val.str.size, ptr, size); + val.str.size = newsize; upb_msgval_write(msg, ofs, val, upb_msgval_sizeof(UPB_TYPE_STRING)); return size; } @@ -3556,13 +4544,14 @@ static upb_selector_t getsel2(const upb_fielddef *f, upb_handlertype_t type) { static bool upb_visitor_hasfield(const upb_msg *msg, const upb_fielddef *f, const upb_msglayout *layout) { + int field_index = upb_fielddef_index(f); if (upb_fielddef_isseq(f)) { - return upb_msgval_getarr(upb_msg_get(msg, f, layout)) != NULL; + return upb_msgval_getarr(upb_msg_get(msg, field_index, layout)) != NULL; } else if (upb_msgdef_syntax(upb_fielddef_containingtype(f)) == UPB_SYNTAX_PROTO2) { - return upb_msg_has(msg, f, layout); + return upb_msg_has(msg, field_index, layout); } else { - upb_msgval val = upb_msg_get(msg, f, layout); + upb_msgval val = upb_msg_get(msg, field_index, layout); switch (upb_fielddef_type(f)) { case UPB_TYPE_FLOAT: return upb_msgval_getfloat(val) != 0; @@ -3581,7 +4570,7 @@ static bool upb_visitor_hasfield(const upb_msg *msg, const upb_fielddef *f, return upb_msgval_getuint64(val) != 0; case UPB_TYPE_STRING: case UPB_TYPE_BYTES: - return upb_msgval_getstr(val) && upb_msgval_getstrlen(val) > 0; + return upb_msgval_getstr(val).size > 0; case UPB_TYPE_MESSAGE: return upb_msgval_getmsg(val) != NULL; } @@ -3592,7 +4581,7 @@ static bool upb_visitor_hasfield(const upb_msg *msg, const upb_fielddef *f, static bool upb_visitor_visitmsg2(const upb_msg *msg, const upb_msglayout *layout, upb_sink *sink, int depth) { - const upb_msgdef *md = upb_msglayout_msgdef(layout); + const upb_msgdef *md = upb_handlers_msgdef(sink->handlers); upb_msg_field_iter i; upb_status status; @@ -3614,7 +4603,7 @@ static bool upb_visitor_visitmsg2(const upb_msg *msg, continue; } - val = upb_msg_get(msg, f, layout); + val = upb_msg_get(msg, upb_fielddef_index(f), layout); if (upb_fielddef_isseq(f)) { const upb_array *arr = upb_msgval_getarr(val); @@ -3683,194 +4672,160 @@ bool upb_visitor_visitmsg(upb_visitor *visitor, const upb_msg *msg) { /* If we always read/write as a consistent type to each address, this shouldn't * violate aliasing. */ -#define DEREF(msg, ofs, type) *(type*)CHARPTR_AT(msg, ofs) - -static upb_inttable *upb_msg_trygetextdict(const upb_msg *msg, - const upb_msglayout *l) { - return l->has_extdict ? DEREF(msg, l->extdict_offset, upb_inttable*) : NULL; -} +#define DEREF(msg, ofs, type) *PTR_AT(msg, ofs, type) -static upb_inttable *upb_msg_getextdict(upb_msg *msg, - const upb_msglayout *l, - upb_alloc *a) { - upb_inttable *ext_dict; - UPB_ASSERT(l->has_extdict); +/* Internal members of a upb_msg. We can change this without breaking binary + * compatibility. We put these before the user's data. The user's upb_msg* + * points after the upb_msg_internal. */ - ext_dict = upb_msg_trygetextdict(msg, l); +/* Used when a message is not extendable. */ +typedef struct { + /* TODO(haberman): add unknown fields. */ + upb_alloc *alloc; +} upb_msg_internal; - if (!ext_dict) { - ext_dict = upb_malloc(a, sizeof(upb_inttable)); +/* Used when a message is extendable. */ +typedef struct { + upb_inttable *extdict; + upb_msg_internal base; +} upb_msg_internal_withext; - if (!ext_dict) { - return NULL; - } +static int upb_msg_internalsize(const upb_msglayout *l) { + return sizeof(upb_msg_internal) - l->data.extendable * sizeof(void*); +} - /* Use an 8-byte type to ensure all bytes are copied. */ - if (!upb_inttable_init2(ext_dict, UPB_CTYPE_INT64, a)) { - upb_free(a, ext_dict); - return NULL; - } +static upb_msg_internal *upb_msg_getinternal(upb_msg *msg) { + return VOIDPTR_AT(msg, -sizeof(upb_msg_internal)); +} - DEREF(msg, l->extdict_offset, upb_inttable*) = ext_dict; - } +static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) { + return VOIDPTR_AT(msg, -sizeof(upb_msg_internal)); +} - return ext_dict; +static upb_msg_internal_withext *upb_msg_getinternalwithext( + upb_msg *msg, const upb_msglayout *l) { + UPB_ASSERT(l->data.extendable); + return VOIDPTR_AT(msg, -sizeof(upb_msg_internal_withext)); } -static uint32_t upb_msg_getoneofint(const upb_msg *msg, - const upb_oneofdef *o, - const upb_msglayout *l) { - size_t oneof_ofs = l->case_offsets[upb_oneofdef_index(o)]; - return DEREF(msg, oneof_ofs, uint8_t); +static const upb_msglayout_fieldinit_v1 *upb_msg_checkfield( + int field_index, const upb_msglayout *l) { + UPB_ASSERT(field_index >= 0 && field_index < l->data.field_count); + return &l->data.fields[field_index]; } -static void upb_msg_setoneofcase(const upb_msg *msg, - const upb_oneofdef *o, - const upb_msglayout *l, - uint32_t val) { - size_t oneof_ofs = l->case_offsets[upb_oneofdef_index(o)]; - DEREF(msg, oneof_ofs, uint8_t) = val; +static bool upb_msg_inoneof(const upb_msglayout_fieldinit_v1 *field) { + return field->oneof_index != UPB_NOT_IN_ONEOF; } +static uint32_t *upb_msg_oneofcase(const upb_msg *msg, int field_index, + const upb_msglayout *l) { + const upb_msglayout_fieldinit_v1 *field = upb_msg_checkfield(field_index, l); + UPB_ASSERT(upb_msg_inoneof(field)); + return PTR_AT(msg, l->data.oneofs[field->oneof_index].case_offset, uint32_t); +} -static bool upb_msg_oneofis(const upb_msg *msg, const upb_msglayout *l, - const upb_oneofdef *o, const upb_fielddef *f) { - return upb_msg_getoneofint(msg, o, l) == upb_fielddef_number(f); +size_t upb_msg_sizeof(const upb_msglayout *l) { + return l->data.size + upb_msg_internalsize(l); } -size_t upb_msg_sizeof(const upb_msglayout *l) { return l->size; } +upb_msg *upb_msg_init(void *mem, const upb_msglayout *l, upb_alloc *a) { + upb_msg *msg = VOIDPTR_AT(mem, upb_msg_internalsize(l)); -void upb_msg_init(upb_msg *msg, const upb_msglayout *l, upb_alloc *a) { - if (l->default_msg) { - memcpy(msg, l->default_msg, l->size); + /* Initialize normal members. */ + if (l->data.default_msg) { + memcpy(msg, l->data.default_msg, l->data.size); } else { - memset(msg, 0, l->size); + memset(msg, 0, l->data.size); } - /* Set arena pointer. */ - memcpy(msg, &a, sizeof(a)); -} + /* Initialize internal members. */ + upb_msg_getinternal(msg)->alloc = a; -void upb_msg_uninit(upb_msg *msg, const upb_msglayout *l) { - upb_inttable *ext_dict = upb_msg_trygetextdict(msg, l); - if (ext_dict) { - upb_inttable_uninit2(ext_dict, upb_msg_alloc(msg, l)); + if (l->data.extendable) { + upb_msg_getinternalwithext(msg, l)->extdict = NULL; } -} -upb_msg *upb_msg_new(const upb_msglayout *l, upb_alloc *a) { - upb_msg *msg = upb_malloc(a, upb_msg_sizeof(l)); + return msg; +} - if (msg) { - upb_msg_init(msg, l, a); +void *upb_msg_uninit(upb_msg *msg, const upb_msglayout *l) { + if (l->data.extendable) { + upb_inttable *ext_dict = upb_msg_getinternalwithext(msg, l)->extdict; + if (ext_dict) { + upb_inttable_uninit2(ext_dict, upb_msg_alloc(msg)); + upb_free(upb_msg_alloc(msg), ext_dict); + } } - return msg; + return VOIDPTR_AT(msg, -upb_msg_internalsize(l)); +} + +upb_msg *upb_msg_new(const upb_msglayout *l, upb_alloc *a) { + void *mem = upb_malloc(a, upb_msg_sizeof(l)); + return mem ? upb_msg_init(mem, l, a) : NULL; } void upb_msg_free(upb_msg *msg, const upb_msglayout *l) { - upb_msg_uninit(msg, l); - upb_free(upb_msg_alloc(msg, l), msg); + upb_free(upb_msg_alloc(msg), upb_msg_uninit(msg, l)); } -upb_alloc *upb_msg_alloc(const upb_msg *msg, const upb_msglayout *l) { - upb_alloc *alloc; - UPB_UNUSED(l); - memcpy(&alloc, msg, sizeof(alloc)); - return alloc; +upb_alloc *upb_msg_alloc(const upb_msg *msg) { + return upb_msg_getinternal_const(msg)->alloc; } bool upb_msg_has(const upb_msg *msg, - const upb_fielddef *f, + int field_index, const upb_msglayout *l) { - const upb_oneofdef *o; - upb_msg_checkfield(l, f); - UPB_ASSERT(upb_fielddef_haspresence(f)); + const upb_msglayout_fieldinit_v1 *field = upb_msg_checkfield(field_index, l); - if (upb_fielddef_isextension(f)) { - /* Extensions are set when they are present in the extension dict. */ - upb_inttable *ext_dict = upb_msg_trygetextdict(msg, l); - upb_value v; - return ext_dict != NULL && - upb_inttable_lookup32(ext_dict, upb_fielddef_number(f), &v); - } else if ((o = upb_fielddef_containingoneof(f)) != NULL) { + UPB_ASSERT(l->data.is_proto2); + + if (upb_msg_inoneof(field)) { /* Oneofs are set when the oneof number is set to this field. */ - return upb_msg_getoneofint(msg, o, l) == upb_fielddef_number(f); + return *upb_msg_oneofcase(msg, field_index, l) == field->number; } else { /* Other fields are set when their hasbit is set. */ - uint32_t hasbit = l->hasbits[upb_fielddef_index(f)]; + uint32_t hasbit = l->data.fields[field_index].hasbit; return DEREF(msg, hasbit / 8, char) | (1 << (hasbit % 8)); } } -upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f, +upb_msgval upb_msg_get(const upb_msg *msg, int field_index, const upb_msglayout *l) { - upb_msg_checkfield(l, f); + const upb_msglayout_fieldinit_v1 *field = upb_msg_checkfield(field_index, l); + int size = upb_msg_fieldsize(field); - if (upb_fielddef_isextension(f)) { - upb_inttable *ext_dict = upb_msg_trygetextdict(msg, l); - upb_value val; - if (upb_inttable_lookup32(ext_dict, upb_fielddef_number(f), &val)) { - return upb_msgval_fromval(val); + if (upb_msg_inoneof(field)) { + if (*upb_msg_oneofcase(msg, field_index, l) == field->number) { + size_t ofs = l->data.oneofs[field->oneof_index].data_offset; + return upb_msgval_read(msg, ofs, size); } else { - return upb_msgval_fromdefault(f); + /* Return default. */ + return upb_msgval_read(l->data.default_msg, field->offset, size); } } else { - size_t ofs = l->field_offsets[upb_fielddef_index(f)]; - const upb_oneofdef *o = upb_fielddef_containingoneof(f); - upb_msgval ret; - - if (o && !upb_msg_oneofis(msg, l, o, f)) { - /* Oneof defaults can't come from the message because the memory is reused - * by all types in the oneof. */ - return upb_msgval_fromdefault(f); - } - - ret = upb_msgval_read(msg, ofs, upb_msg_fieldsize(f)); - return ret; + return upb_msgval_read(msg, field->offset, size); } } -bool upb_msg_set(upb_msg *msg, - const upb_fielddef *f, - upb_msgval val, +void upb_msg_set(upb_msg *msg, int field_index, upb_msgval val, const upb_msglayout *l) { - upb_alloc *a = upb_msg_alloc(msg, l); - upb_msg_checkfield(l, f); - - if (upb_fielddef_isextension(f)) { - /* TODO(haberman): introduce table API that can do this in one call. */ - upb_inttable *ext = upb_msg_getextdict(msg, l, a); - upb_value val2 = upb_toval(val); - if (!upb_inttable_replace(ext, upb_fielddef_number(f), val2) && - !upb_inttable_insert2(ext, upb_fielddef_number(f), val2, a)) { - return false; - } - } else { - size_t ofs = l->field_offsets[upb_fielddef_index(f)]; - const upb_oneofdef *o = upb_fielddef_containingoneof(f); - - if (o) { - upb_msg_setoneofcase(msg, o, l, upb_fielddef_number(f)); - } + const upb_msglayout_fieldinit_v1 *field = upb_msg_checkfield(field_index, l); + int size = upb_msg_fieldsize(field); - upb_msgval_write(msg, ofs, val, upb_msg_fieldsize(f)); + if (upb_msg_inoneof(field)) { + size_t ofs = l->data.oneofs[field->oneof_index].data_offset; + *upb_msg_oneofcase(msg, field_index, l) = field->number; + upb_msgval_write(msg, ofs, val, size); + } else { + upb_msgval_write(msg, field->offset, val, size); } - return true; } /** upb_array *****************************************************************/ -struct upb_array { - upb_fieldtype_t type; - uint8_t element_size; - void *data; /* Each element is element_size. */ - size_t len; /* Measured in elements. */ - size_t size; /* Measured in elements. */ - upb_alloc *alloc; -}; - #define DEREF_ARR(arr, i, type) ((type*)arr->data)[i] size_t upb_array_sizeof(upb_fieldtype_t type) { @@ -3965,8 +4920,8 @@ static void upb_map_tokey(upb_fieldtype_t type, upb_msgval *key, switch (type) { case UPB_TYPE_STRING: /* Point to string data of the input key. */ - *out_key = key->str.ptr; - *out_len = key->str.len; + *out_key = key->str.data; + *out_len = key->str.size; return; case UPB_TYPE_BOOL: case UPB_TYPE_INT32: @@ -3991,7 +4946,7 @@ static upb_msgval upb_map_fromkey(upb_fieldtype_t type, const char *key, size_t len) { switch (type) { case UPB_TYPE_STRING: - return upb_msgval_str(key, len); + return upb_msgval_makestr(key, len); case UPB_TYPE_BOOL: case UPB_TYPE_INT32: case UPB_TYPE_UINT32: @@ -6451,138 +7406,138 @@ static upb_inttable reftables[268]; #endif static const upb_msgdef msgs[22] = { - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", 40, 8, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[0], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[0]), false, UPB_SYNTAX_PROTO2, &reftables[0], &reftables[1]), - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", 4, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[11], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[16]), false, UPB_SYNTAX_PROTO2, &reftables[2], &reftables[3]), - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ReservedRange", 4, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[14], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[20]), false, UPB_SYNTAX_PROTO2, &reftables[4], &reftables[5]), - UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[17], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[24]), false, UPB_SYNTAX_PROTO2, &reftables[6], &reftables[7]), - UPB_MSGDEF_INIT("google.protobuf.EnumOptions", 8, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[0], &arrays[21], 4, 2), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[28]), false, UPB_SYNTAX_PROTO2, &reftables[8], &reftables[9]), - UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", 8, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[25], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[32]), false, UPB_SYNTAX_PROTO2, &reftables[10], &reftables[11]), - UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", 7, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[2], &arrays[29], 2, 1), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[36]), false, UPB_SYNTAX_PROTO2, &reftables[12], &reftables[13]), - UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", 23, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[31], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[40]), false, UPB_SYNTAX_PROTO2, &reftables[14], &reftables[15]), - UPB_MSGDEF_INIT("google.protobuf.FieldOptions", 12, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[4], &arrays[42], 11, 6), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[56]), false, UPB_SYNTAX_PROTO2, &reftables[16], &reftables[17]), - UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", 42, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[53], 13, 12), UPB_STRTABLE_INIT(12, 15, UPB_CTYPE_PTR, 4, &strentries[72]), false, UPB_SYNTAX_PROTO2, &reftables[18], &reftables[19]), - UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[66], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[88]), false, UPB_SYNTAX_PROTO2, &reftables[20], &reftables[21]), - UPB_MSGDEF_INIT("google.protobuf.FileOptions", 37, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 42, 17), UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_PTR, 5, &strentries[92]), false, UPB_SYNTAX_PROTO2, &reftables[22], &reftables[23]), - UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 10, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[110], 8, 4), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[124]), false, UPB_SYNTAX_PROTO2, &reftables[24], &reftables[25]), - UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 15, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[118], 7, 6), UPB_STRTABLE_INIT(6, 7, UPB_CTYPE_PTR, 3, &strentries[132]), false, UPB_SYNTAX_PROTO2, &reftables[26], &reftables[27]), - UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[10], &arrays[125], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[140]), false, UPB_SYNTAX_PROTO2, &reftables[28], &reftables[29]), - UPB_MSGDEF_INIT("google.protobuf.OneofDescriptorProto", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[126], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[144]), false, UPB_SYNTAX_PROTO2, &reftables[30], &reftables[31]), - UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[128], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[148]), false, UPB_SYNTAX_PROTO2, &reftables[32], &reftables[33]), - UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[14], &arrays[132], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[152]), false, UPB_SYNTAX_PROTO2, &reftables[34], &reftables[35]), - UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[133], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[156]), false, UPB_SYNTAX_PROTO2, &reftables[36], &reftables[37]), - UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 19, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[135], 7, 5), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[160]), false, UPB_SYNTAX_PROTO2, &reftables[38], &reftables[39]), - UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 18, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[142], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[168]), false, UPB_SYNTAX_PROTO2, &reftables[40], &reftables[41]), - UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[151], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[184]), false, UPB_SYNTAX_PROTO2, &reftables[42], &reftables[43]), + UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", 41, 8, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[0], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[0]), false, UPB_SYNTAX_PROTO2, &reftables[0], &reftables[1]), + UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[11], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[16]), false, UPB_SYNTAX_PROTO2, &reftables[2], &reftables[3]), + UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ReservedRange", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[14], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[20]), false, UPB_SYNTAX_PROTO2, &reftables[4], &reftables[5]), + UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", 12, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[17], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[24]), false, UPB_SYNTAX_PROTO2, &reftables[6], &reftables[7]), + UPB_MSGDEF_INIT("google.protobuf.EnumOptions", 9, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[0], &arrays[21], 4, 2), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[28]), false, UPB_SYNTAX_PROTO2, &reftables[8], &reftables[9]), + UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", 9, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[25], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[32]), false, UPB_SYNTAX_PROTO2, &reftables[10], &reftables[11]), + UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", 8, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[2], &arrays[29], 2, 1), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[36]), false, UPB_SYNTAX_PROTO2, &reftables[12], &reftables[13]), + UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", 24, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[31], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[40]), false, UPB_SYNTAX_PROTO2, &reftables[14], &reftables[15]), + UPB_MSGDEF_INIT("google.protobuf.FieldOptions", 13, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[4], &arrays[42], 11, 6), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[56]), false, UPB_SYNTAX_PROTO2, &reftables[16], &reftables[17]), + UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", 43, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[53], 13, 12), UPB_STRTABLE_INIT(12, 15, UPB_CTYPE_PTR, 4, &strentries[72]), false, UPB_SYNTAX_PROTO2, &reftables[18], &reftables[19]), + UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", 7, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[66], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[88]), false, UPB_SYNTAX_PROTO2, &reftables[20], &reftables[21]), + UPB_MSGDEF_INIT("google.protobuf.FileOptions", 38, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 42, 17), UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_PTR, 5, &strentries[92]), false, UPB_SYNTAX_PROTO2, &reftables[22], &reftables[23]), + UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 11, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[110], 8, 4), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[124]), false, UPB_SYNTAX_PROTO2, &reftables[24], &reftables[25]), + UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 16, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[118], 7, 6), UPB_STRTABLE_INIT(6, 7, UPB_CTYPE_PTR, 3, &strentries[132]), false, UPB_SYNTAX_PROTO2, &reftables[26], &reftables[27]), + UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 8, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[10], &arrays[125], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[140]), false, UPB_SYNTAX_PROTO2, &reftables[28], &reftables[29]), + UPB_MSGDEF_INIT("google.protobuf.OneofDescriptorProto", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[126], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[144]), false, UPB_SYNTAX_PROTO2, &reftables[30], &reftables[31]), + UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 12, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[128], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[148]), false, UPB_SYNTAX_PROTO2, &reftables[32], &reftables[33]), + UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 8, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[14], &arrays[132], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[152]), false, UPB_SYNTAX_PROTO2, &reftables[34], &reftables[35]), + UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 7, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[133], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[156]), false, UPB_SYNTAX_PROTO2, &reftables[36], &reftables[37]), + UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 20, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[135], 7, 5), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[160]), false, UPB_SYNTAX_PROTO2, &reftables[38], &reftables[39]), + UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 19, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[142], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[168]), false, UPB_SYNTAX_PROTO2, &reftables[40], &reftables[41]), + UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 7, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[151], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[184]), false, UPB_SYNTAX_PROTO2, &reftables[42], &reftables[43]), }; static const upb_fielddef fields[107] = { - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "aggregate_value", 8, &msgs[20], NULL, 15, 6, {0},&reftables[44], &reftables[45]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "allow_alias", 2, &msgs[4], NULL, 6, 1, {0},&reftables[46], &reftables[47]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_enable_arenas", 31, &msgs[11], NULL, 23, 12, {0},&reftables[48], &reftables[49]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_generic_services", 16, &msgs[11], NULL, 17, 6, {0},&reftables[50], &reftables[51]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "client_streaming", 5, &msgs[13], NULL, 13, 4, {0},&reftables[52], &reftables[53]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "csharp_namespace", 37, &msgs[11], NULL, 27, 14, {0},&reftables[54], &reftables[55]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "ctype", 1, &msgs[8], (const upb_def*)(&enums[2]), 6, 1, {0},&reftables[56], &reftables[57]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "default_value", 7, &msgs[7], NULL, 16, 7, {0},&reftables[58], &reftables[59]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "dependency", 3, &msgs[9], NULL, 30, 8, {0},&reftables[60], &reftables[61]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[8], NULL, 8, 3, {0},&reftables[62], &reftables[63]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[14], NULL, 6, 1, {0},&reftables[64], &reftables[65]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[12], NULL, 8, 3, {0},&reftables[66], &reftables[67]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 23, &msgs[11], NULL, 21, 10, {0},&reftables[68], &reftables[69]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 1, &msgs[6], NULL, 6, 1, {0},&reftables[70], &reftables[71]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[4], NULL, 7, 2, {0},&reftables[72], &reftables[73]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[17], NULL, 6, 1, {0},&reftables[74], &reftables[75]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, false, false, false, "double_value", 6, &msgs[20], NULL, 11, 4, {0},&reftables[76], &reftables[77]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[2], NULL, 3, 1, {0},&reftables[78], &reftables[79]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[1], NULL, 3, 1, {0},&reftables[80], &reftables[81]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 5, &msgs[9], (const upb_def*)(&msgs[3]), 13, 1, {0},&reftables[82], &reftables[83]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 4, &msgs[0], (const upb_def*)(&msgs[3]), 18, 2, {0},&reftables[84], &reftables[85]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "extendee", 2, &msgs[7], NULL, 7, 2, {0},&reftables[86], &reftables[87]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 6, &msgs[0], (const upb_def*)(&msgs[7]), 24, 4, {0},&reftables[88], &reftables[89]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 7, &msgs[9], (const upb_def*)(&msgs[7]), 19, 3, {0},&reftables[90], &reftables[91]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension_range", 5, &msgs[0], (const upb_def*)(&msgs[1]), 21, 3, {0},&reftables[92], &reftables[93]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "field", 2, &msgs[0], (const upb_def*)(&msgs[7]), 12, 0, {0},&reftables[94], &reftables[95]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "file", 1, &msgs[10], (const upb_def*)(&msgs[9]), 5, 0, {0},&reftables[96], &reftables[97]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "go_package", 11, &msgs[11], NULL, 14, 5, {0},&reftables[98], &reftables[99]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "identifier_value", 3, &msgs[20], NULL, 6, 1, {0},&reftables[100], &reftables[101]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "input_type", 2, &msgs[13], NULL, 7, 2, {0},&reftables[102], &reftables[103]), - UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, false, false, false, "is_extension", 2, &msgs[21], NULL, 5, 1, {0},&reftables[104], &reftables[105]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generate_equals_and_hash", 20, &msgs[11], NULL, 20, 9, {0},&reftables[106], &reftables[107]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generic_services", 17, &msgs[11], NULL, 18, 7, {0},&reftables[108], &reftables[109]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_multiple_files", 10, &msgs[11], NULL, 13, 4, {0},&reftables[110], &reftables[111]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_outer_classname", 8, &msgs[11], NULL, 9, 2, {0},&reftables[112], &reftables[113]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_package", 1, &msgs[11], NULL, 6, 1, {0},&reftables[114], &reftables[115]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_string_check_utf8", 27, &msgs[11], NULL, 22, 11, {0},&reftables[116], &reftables[117]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "javanano_use_deprecated_package", 38, &msgs[11], NULL, 30, 15, {0},&reftables[118], &reftables[119]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "json_name", 10, &msgs[7], NULL, 20, 9, {0},&reftables[120], &reftables[121]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "jstype", 6, &msgs[8], (const upb_def*)(&enums[3]), 10, 5, {0},&reftables[122], &reftables[123]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "label", 4, &msgs[7], (const upb_def*)(&enums[0]), 11, 4, {0},&reftables[124], &reftables[125]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "lazy", 5, &msgs[8], NULL, 9, 4, {0},&reftables[126], &reftables[127]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "leading_comments", 3, &msgs[19], NULL, 8, 2, {0},&reftables[128], &reftables[129]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "leading_detached_comments", 6, &msgs[19], NULL, 16, 4, {0},&reftables[130], &reftables[131]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "location", 1, &msgs[18], (const upb_def*)(&msgs[19]), 5, 0, {0},&reftables[132], &reftables[133]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "map_entry", 7, &msgs[12], NULL, 9, 4, {0},&reftables[134], &reftables[135]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "message_set_wire_format", 1, &msgs[12], NULL, 6, 1, {0},&reftables[136], &reftables[137]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "message_type", 4, &msgs[9], (const upb_def*)(&msgs[0]), 10, 0, {0},&reftables[138], &reftables[139]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "method", 2, &msgs[16], (const upb_def*)(&msgs[13]), 6, 0, {0},&reftables[140], &reftables[141]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "name", 2, &msgs[20], (const upb_def*)(&msgs[21]), 5, 0, {0},&reftables[142], &reftables[143]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[5], NULL, 4, 1, {0},&reftables[144], &reftables[145]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[9], NULL, 22, 6, {0},&reftables[146], &reftables[147]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[3], NULL, 8, 2, {0},&reftables[148], &reftables[149]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[16], NULL, 8, 2, {0},&reftables[150], &reftables[151]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[15], NULL, 2, 0, {0},&reftables[152], &reftables[153]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[13], NULL, 4, 1, {0},&reftables[154], &reftables[155]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[7], NULL, 4, 1, {0},&reftables[156], &reftables[157]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 32, 8, {0},&reftables[158], &reftables[159]), - UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, false, false, false, "name_part", 1, &msgs[21], NULL, 2, 0, {0},&reftables[160], &reftables[161]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, false, false, false, "negative_int_value", 5, &msgs[20], NULL, 10, 3, {0},&reftables[162], &reftables[163]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "nested_type", 3, &msgs[0], (const upb_def*)(&msgs[0]), 15, 1, {0},&reftables[164], &reftables[165]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "no_standard_descriptor_accessor", 2, &msgs[12], NULL, 7, 2, {0},&reftables[166], &reftables[167]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 3, &msgs[7], NULL, 10, 3, {0},&reftables[168], &reftables[169]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 2, &msgs[5], NULL, 7, 2, {0},&reftables[170], &reftables[171]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "objc_class_prefix", 36, &msgs[11], NULL, 24, 13, {0},&reftables[172], &reftables[173]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "oneof_decl", 8, &msgs[0], (const upb_def*)(&msgs[15]), 28, 6, {0},&reftables[174], &reftables[175]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "oneof_index", 9, &msgs[7], NULL, 19, 8, {0},&reftables[176], &reftables[177]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "optimize_for", 9, &msgs[11], (const upb_def*)(&enums[4]), 12, 3, {0},&reftables[178], &reftables[179]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 7, &msgs[0], (const upb_def*)(&msgs[12]), 25, 5, {0},&reftables[180], &reftables[181]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[9], (const upb_def*)(&msgs[11]), 20, 4, {0},&reftables[182], &reftables[183]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[7], (const upb_def*)(&msgs[8]), 3, 0, {0},&reftables[184], &reftables[185]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 4, &msgs[13], (const upb_def*)(&msgs[14]), 3, 0, {0},&reftables[186], &reftables[187]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[16], (const upb_def*)(&msgs[17]), 7, 1, {0},&reftables[188], &reftables[189]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[3], (const upb_def*)(&msgs[4]), 7, 1, {0},&reftables[190], &reftables[191]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[5], (const upb_def*)(&msgs[6]), 3, 0, {0},&reftables[192], &reftables[193]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "output_type", 3, &msgs[13], NULL, 10, 3, {0},&reftables[194], &reftables[195]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "package", 2, &msgs[9], NULL, 25, 7, {0},&reftables[196], &reftables[197]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "packed", 2, &msgs[8], NULL, 7, 2, {0},&reftables[198], &reftables[199]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "path", 1, &msgs[19], NULL, 4, 0, {0},&reftables[200], &reftables[201]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "php_class_prefix", 40, &msgs[11], NULL, 31, 16, {0},&reftables[202], &reftables[203]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "php_namespace", 41, &msgs[11], NULL, 34, 17, {0},&reftables[204], &reftables[205]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, false, "positive_int_value", 4, &msgs[20], NULL, 9, 2, {0},&reftables[206], &reftables[207]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "public_dependency", 10, &msgs[9], NULL, 35, 9, {0},&reftables[208], &reftables[209]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "py_generic_services", 18, &msgs[11], NULL, 19, 8, {0},&reftables[210], &reftables[211]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "reserved_name", 10, &msgs[0], NULL, 37, 9, {0},&reftables[212], &reftables[213]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "reserved_range", 9, &msgs[0], (const upb_def*)(&msgs[2]), 31, 7, {0},&reftables[214], &reftables[215]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "server_streaming", 6, &msgs[13], NULL, 14, 5, {0},&reftables[216], &reftables[217]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "service", 6, &msgs[9], (const upb_def*)(&msgs[16]), 16, 2, {0},&reftables[218], &reftables[219]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "source_code_info", 9, &msgs[9], (const upb_def*)(&msgs[18]), 21, 5, {0},&reftables[220], &reftables[221]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "span", 2, &msgs[19], NULL, 7, 1, {0},&reftables[222], &reftables[223]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[2], NULL, 2, 0, {0},&reftables[224], &reftables[225]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[1], NULL, 2, 0, {0},&reftables[226], &reftables[227]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[20], NULL, 12, 5, {0},&reftables[228], &reftables[229]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "syntax", 12, &msgs[9], NULL, 39, 11, {0},&reftables[230], &reftables[231]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[19], NULL, 11, 3, {0},&reftables[232], &reftables[233]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "type", 5, &msgs[7], (const upb_def*)(&enums[1]), 12, 5, {0},&reftables[234], &reftables[235]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[7], NULL, 13, 6, {0},&reftables[236], &reftables[237]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[12], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[238], &reftables[239]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[17], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[240], &reftables[241]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[11], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[242], &reftables[243]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[14], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[244], &reftables[245]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[8], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[246], &reftables[247]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[6], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[248], &reftables[249]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[4], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[250], &reftables[251]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "value", 2, &msgs[3], (const upb_def*)(&msgs[5]), 6, 0, {0},&reftables[252], &reftables[253]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[8], NULL, 11, 6, {0},&reftables[254], &reftables[255]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "weak_dependency", 11, &msgs[9], NULL, 38, 10, {0},&reftables[256], &reftables[257]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "aggregate_value", 8, &msgs[20], NULL, 16, 6, {0},&reftables[44], &reftables[45]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "allow_alias", 2, &msgs[4], NULL, 7, 1, {0},&reftables[46], &reftables[47]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_enable_arenas", 31, &msgs[11], NULL, 24, 12, {0},&reftables[48], &reftables[49]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_generic_services", 16, &msgs[11], NULL, 18, 6, {0},&reftables[50], &reftables[51]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "client_streaming", 5, &msgs[13], NULL, 14, 4, {0},&reftables[52], &reftables[53]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "csharp_namespace", 37, &msgs[11], NULL, 28, 14, {0},&reftables[54], &reftables[55]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "ctype", 1, &msgs[8], (const upb_def*)(&enums[2]), 7, 1, {0},&reftables[56], &reftables[57]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "default_value", 7, &msgs[7], NULL, 17, 7, {0},&reftables[58], &reftables[59]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "dependency", 3, &msgs[9], NULL, 31, 8, {0},&reftables[60], &reftables[61]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[8], NULL, 9, 3, {0},&reftables[62], &reftables[63]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[14], NULL, 7, 1, {0},&reftables[64], &reftables[65]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[12], NULL, 9, 3, {0},&reftables[66], &reftables[67]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 23, &msgs[11], NULL, 22, 10, {0},&reftables[68], &reftables[69]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 1, &msgs[6], NULL, 7, 1, {0},&reftables[70], &reftables[71]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[4], NULL, 8, 2, {0},&reftables[72], &reftables[73]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[17], NULL, 7, 1, {0},&reftables[74], &reftables[75]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, false, false, false, "double_value", 6, &msgs[20], NULL, 12, 4, {0},&reftables[76], &reftables[77]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[2], NULL, 4, 1, {0},&reftables[78], &reftables[79]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[1], NULL, 4, 1, {0},&reftables[80], &reftables[81]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 5, &msgs[9], (const upb_def*)(&msgs[3]), 14, 1, {0},&reftables[82], &reftables[83]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 4, &msgs[0], (const upb_def*)(&msgs[3]), 19, 2, {0},&reftables[84], &reftables[85]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "extendee", 2, &msgs[7], NULL, 8, 2, {0},&reftables[86], &reftables[87]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 6, &msgs[0], (const upb_def*)(&msgs[7]), 25, 4, {0},&reftables[88], &reftables[89]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 7, &msgs[9], (const upb_def*)(&msgs[7]), 20, 3, {0},&reftables[90], &reftables[91]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension_range", 5, &msgs[0], (const upb_def*)(&msgs[1]), 22, 3, {0},&reftables[92], &reftables[93]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "field", 2, &msgs[0], (const upb_def*)(&msgs[7]), 13, 0, {0},&reftables[94], &reftables[95]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "file", 1, &msgs[10], (const upb_def*)(&msgs[9]), 6, 0, {0},&reftables[96], &reftables[97]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "go_package", 11, &msgs[11], NULL, 15, 5, {0},&reftables[98], &reftables[99]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "identifier_value", 3, &msgs[20], NULL, 7, 1, {0},&reftables[100], &reftables[101]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "input_type", 2, &msgs[13], NULL, 8, 2, {0},&reftables[102], &reftables[103]), + UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, false, false, false, "is_extension", 2, &msgs[21], NULL, 6, 1, {0},&reftables[104], &reftables[105]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generate_equals_and_hash", 20, &msgs[11], NULL, 21, 9, {0},&reftables[106], &reftables[107]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generic_services", 17, &msgs[11], NULL, 19, 7, {0},&reftables[108], &reftables[109]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_multiple_files", 10, &msgs[11], NULL, 14, 4, {0},&reftables[110], &reftables[111]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_outer_classname", 8, &msgs[11], NULL, 10, 2, {0},&reftables[112], &reftables[113]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_package", 1, &msgs[11], NULL, 7, 1, {0},&reftables[114], &reftables[115]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_string_check_utf8", 27, &msgs[11], NULL, 23, 11, {0},&reftables[116], &reftables[117]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "javanano_use_deprecated_package", 38, &msgs[11], NULL, 31, 15, {0},&reftables[118], &reftables[119]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "json_name", 10, &msgs[7], NULL, 21, 9, {0},&reftables[120], &reftables[121]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "jstype", 6, &msgs[8], (const upb_def*)(&enums[3]), 11, 5, {0},&reftables[122], &reftables[123]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "label", 4, &msgs[7], (const upb_def*)(&enums[0]), 12, 4, {0},&reftables[124], &reftables[125]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "lazy", 5, &msgs[8], NULL, 10, 4, {0},&reftables[126], &reftables[127]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "leading_comments", 3, &msgs[19], NULL, 9, 2, {0},&reftables[128], &reftables[129]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "leading_detached_comments", 6, &msgs[19], NULL, 17, 4, {0},&reftables[130], &reftables[131]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "location", 1, &msgs[18], (const upb_def*)(&msgs[19]), 6, 0, {0},&reftables[132], &reftables[133]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "map_entry", 7, &msgs[12], NULL, 10, 4, {0},&reftables[134], &reftables[135]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "message_set_wire_format", 1, &msgs[12], NULL, 7, 1, {0},&reftables[136], &reftables[137]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "message_type", 4, &msgs[9], (const upb_def*)(&msgs[0]), 11, 0, {0},&reftables[138], &reftables[139]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "method", 2, &msgs[16], (const upb_def*)(&msgs[13]), 7, 0, {0},&reftables[140], &reftables[141]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "name", 2, &msgs[20], (const upb_def*)(&msgs[21]), 6, 0, {0},&reftables[142], &reftables[143]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[5], NULL, 5, 1, {0},&reftables[144], &reftables[145]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[9], NULL, 23, 6, {0},&reftables[146], &reftables[147]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[3], NULL, 9, 2, {0},&reftables[148], &reftables[149]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[16], NULL, 9, 2, {0},&reftables[150], &reftables[151]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[15], NULL, 3, 0, {0},&reftables[152], &reftables[153]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[13], NULL, 5, 1, {0},&reftables[154], &reftables[155]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[7], NULL, 5, 1, {0},&reftables[156], &reftables[157]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 33, 8, {0},&reftables[158], &reftables[159]), + UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, false, false, false, "name_part", 1, &msgs[21], NULL, 3, 0, {0},&reftables[160], &reftables[161]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, false, false, false, "negative_int_value", 5, &msgs[20], NULL, 11, 3, {0},&reftables[162], &reftables[163]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "nested_type", 3, &msgs[0], (const upb_def*)(&msgs[0]), 16, 1, {0},&reftables[164], &reftables[165]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "no_standard_descriptor_accessor", 2, &msgs[12], NULL, 8, 2, {0},&reftables[166], &reftables[167]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 3, &msgs[7], NULL, 11, 3, {0},&reftables[168], &reftables[169]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 2, &msgs[5], NULL, 8, 2, {0},&reftables[170], &reftables[171]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "objc_class_prefix", 36, &msgs[11], NULL, 25, 13, {0},&reftables[172], &reftables[173]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "oneof_decl", 8, &msgs[0], (const upb_def*)(&msgs[15]), 29, 6, {0},&reftables[174], &reftables[175]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "oneof_index", 9, &msgs[7], NULL, 20, 8, {0},&reftables[176], &reftables[177]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "optimize_for", 9, &msgs[11], (const upb_def*)(&enums[4]), 13, 3, {0},&reftables[178], &reftables[179]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 7, &msgs[0], (const upb_def*)(&msgs[12]), 26, 5, {0},&reftables[180], &reftables[181]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[9], (const upb_def*)(&msgs[11]), 21, 4, {0},&reftables[182], &reftables[183]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[7], (const upb_def*)(&msgs[8]), 4, 0, {0},&reftables[184], &reftables[185]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 4, &msgs[13], (const upb_def*)(&msgs[14]), 4, 0, {0},&reftables[186], &reftables[187]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[16], (const upb_def*)(&msgs[17]), 8, 1, {0},&reftables[188], &reftables[189]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[3], (const upb_def*)(&msgs[4]), 8, 1, {0},&reftables[190], &reftables[191]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[5], (const upb_def*)(&msgs[6]), 4, 0, {0},&reftables[192], &reftables[193]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "output_type", 3, &msgs[13], NULL, 11, 3, {0},&reftables[194], &reftables[195]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "package", 2, &msgs[9], NULL, 26, 7, {0},&reftables[196], &reftables[197]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "packed", 2, &msgs[8], NULL, 8, 2, {0},&reftables[198], &reftables[199]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "path", 1, &msgs[19], NULL, 5, 0, {0},&reftables[200], &reftables[201]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "php_class_prefix", 40, &msgs[11], NULL, 32, 16, {0},&reftables[202], &reftables[203]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "php_namespace", 41, &msgs[11], NULL, 35, 17, {0},&reftables[204], &reftables[205]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, false, "positive_int_value", 4, &msgs[20], NULL, 10, 2, {0},&reftables[206], &reftables[207]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "public_dependency", 10, &msgs[9], NULL, 36, 9, {0},&reftables[208], &reftables[209]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "py_generic_services", 18, &msgs[11], NULL, 20, 8, {0},&reftables[210], &reftables[211]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "reserved_name", 10, &msgs[0], NULL, 38, 9, {0},&reftables[212], &reftables[213]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "reserved_range", 9, &msgs[0], (const upb_def*)(&msgs[2]), 32, 7, {0},&reftables[214], &reftables[215]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "server_streaming", 6, &msgs[13], NULL, 15, 5, {0},&reftables[216], &reftables[217]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "service", 6, &msgs[9], (const upb_def*)(&msgs[16]), 17, 2, {0},&reftables[218], &reftables[219]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "source_code_info", 9, &msgs[9], (const upb_def*)(&msgs[18]), 22, 5, {0},&reftables[220], &reftables[221]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "span", 2, &msgs[19], NULL, 8, 1, {0},&reftables[222], &reftables[223]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[2], NULL, 3, 0, {0},&reftables[224], &reftables[225]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[1], NULL, 3, 0, {0},&reftables[226], &reftables[227]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[20], NULL, 13, 5, {0},&reftables[228], &reftables[229]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "syntax", 12, &msgs[9], NULL, 40, 11, {0},&reftables[230], &reftables[231]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[19], NULL, 12, 3, {0},&reftables[232], &reftables[233]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "type", 5, &msgs[7], (const upb_def*)(&enums[1]), 13, 5, {0},&reftables[234], &reftables[235]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[7], NULL, 14, 6, {0},&reftables[236], &reftables[237]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[12], (const upb_def*)(&msgs[20]), 6, 0, {0},&reftables[238], &reftables[239]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[17], (const upb_def*)(&msgs[20]), 6, 0, {0},&reftables[240], &reftables[241]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[11], (const upb_def*)(&msgs[20]), 6, 0, {0},&reftables[242], &reftables[243]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[14], (const upb_def*)(&msgs[20]), 6, 0, {0},&reftables[244], &reftables[245]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[8], (const upb_def*)(&msgs[20]), 6, 0, {0},&reftables[246], &reftables[247]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[6], (const upb_def*)(&msgs[20]), 6, 0, {0},&reftables[248], &reftables[249]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[4], (const upb_def*)(&msgs[20]), 6, 0, {0},&reftables[250], &reftables[251]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "value", 2, &msgs[3], (const upb_def*)(&msgs[5]), 7, 0, {0},&reftables[252], &reftables[253]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[8], NULL, 12, 6, {0},&reftables[254], &reftables[255]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "weak_dependency", 11, &msgs[9], NULL, 39, 10, {0},&reftables[256], &reftables[257]), }; static const upb_enumdef enums[5] = { @@ -7401,6 +8356,7 @@ typedef struct { struct upb_descreader { upb_sink sink; upb_inttable files; + upb_strtable files_by_name; upb_filedef *file; /* The last file in files. */ upb_descreader_frame stack[UPB_MAX_MESSAGE_NESTING]; int stack_len; @@ -7567,6 +8523,7 @@ static size_t file_onname(void *closure, const void *hd, const char *buf, UPB_UNUSED(handle); name = upb_gstrndup(buf, n); + upb_strtable_insert(&r->files_by_name, name, upb_value_ptr(r->file)); /* XXX: see comment at the top of the file. */ ok = upb_filedef_setname(r->file, name, NULL); upb_gfree(name); @@ -7680,6 +8637,18 @@ static void *file_startext(void *closure, const void *hd) { return r; } +static size_t file_ondep(void *closure, const void *hd, const char *buf, + size_t n, const upb_bufhandle *handle) { + upb_descreader *r = closure; + upb_value val; + if (upb_strtable_lookup2(&r->files_by_name, buf, n, &val)) { + upb_filedef_adddep(r->file, upb_value_getptr(val)); + } + UPB_UNUSED(hd); + UPB_UNUSED(handle); + return n; +} + /** Handlers for google.protobuf.EnumValueDescriptorProto. *********************/ static bool enumval_startmsg(void *closure, const void *hd) { @@ -8124,6 +9093,8 @@ static void reghandlers(const void *closure, upb_handlers *h) { &file_startenum, NULL); upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, extension), &file_startext, NULL); + upb_handlers_setstring(h, F(FileDescriptorProto, dependency), + &file_ondep, NULL); } else if (upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)) { upb_handlers_setstartmsg(h, &enumval_startmsg, NULL); upb_handlers_setendmsg(h, &enumval_endmsg, NULL); @@ -8183,6 +9154,7 @@ void descreader_cleanup(void *_r) { upb_gfree(r->name); upb_inttable_uninit(&r->files); + upb_strtable_uninit(&r->files_by_name); upb_inttable_uninit(&r->oneofs); upb_gfree(r->default_string); while (r->stack_len > 0) { @@ -8201,6 +9173,7 @@ upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h) { } upb_inttable_init(&r->files, UPB_CTYPE_PTR); + upb_strtable_init(&r->files_by_name, UPB_CTYPE_PTR); upb_inttable_init(&r->oneofs, UPB_CTYPE_PTR); upb_sink_reset(upb_descreader_input(r), h, r); r->stack_len = 0; @@ -8500,7 +9473,7 @@ static void put32(compiler *c, uint32_t v) { *c->pc++ = v; } -static void putop(compiler *c, opcode op, ...) { +static void putop(compiler *c, int op, ...) { va_list ap; va_start(ap, op); @@ -9783,7 +10756,6 @@ have_tag: return upb_pbdecoder_suspend(d); } - /* TODO: deliver to unknown field callback. */ switch (wire_type) { case UPB_WIRE_TYPE_32BIT: CHECK_RETURN(skip(d, 4)); @@ -9821,6 +10793,8 @@ have_tag: } if (d->top->groupnum >= 0) { + /* TODO: More code needed for handling unknown groups. */ + upb_sink_putunknown(&d->top->sink, d->checkpoint, d->ptr - d->checkpoint); return DECODE_OK; } @@ -10676,6 +11650,12 @@ static void *encode_startdelimfield(void *c, const void *hd) { return ok ? c : UPB_BREAK; } +static bool encode_unknown(void *c, const void *hd, const char *buf, + size_t len) { + UPB_UNUSED(hd); + return encode_bytes(c, buf, len) && commit(c); +} + static bool encode_enddelimfield(void *c, const void *hd) { UPB_UNUSED(hd); return end_delim(c); @@ -10738,6 +11718,7 @@ static void newhandlers_callback(const void *closure, upb_handlers *h) { upb_handlers_setstartmsg(h, startmsg, NULL); upb_handlers_setendmsg(h, endmsg, NULL); + upb_handlers_setunknown(h, encode_unknown, NULL); m = upb_handlers_msgdef(h); for(upb_msg_field_begin(&i, m); @@ -11350,8 +12331,9 @@ done: ** - handling of keys/escape-sequences/etc that span input buffers. */ -#include <assert.h> #include <errno.h> +#include <float.h> +#include <math.h> #include <stdint.h> #include <stdlib.h> #include <string.h> @@ -11936,103 +12918,160 @@ static void start_number(upb_json_parser *p, const char *ptr) { capture_begin(p, ptr); } -static bool parse_number(upb_json_parser *p); +static bool parse_number(upb_json_parser *p, bool is_quoted); static bool end_number(upb_json_parser *p, const char *ptr) { if (!capture_end(p, ptr)) { return false; } - return parse_number(p); + return parse_number(p, false); } -static bool parse_number(upb_json_parser *p) { - size_t len; - const char *buf; - const char *myend; +/* |buf| is NULL-terminated. |buf| itself will never include quotes; + * |is_quoted| tells us whether this text originally appeared inside quotes. */ +static bool parse_number_from_buffer(upb_json_parser *p, const char *buf, + bool is_quoted) { + size_t len = strlen(buf); + const char *bufend = buf + len; char *end; + upb_fieldtype_t type = upb_fielddef_type(p->top->f); + double val; + double dummy; + double inf = 1.0 / 0.0; /* C89 does not have an INFINITY macro. */ - /* strtol() and friends unfortunately do not support specifying the length of - * the input string, so we need to force a copy into a NULL-terminated buffer. */ - if (!multipart_text(p, "\0", 1, false)) { + errno = 0; + + if (len == 0 || buf[0] == ' ') { return false; } - buf = accumulate_getptr(p, &len); - myend = buf + len - 1; /* One for NULL. */ - - /* XXX: We are using strtol to parse integers, but this is wrong as even - * integers can be represented as 1e6 (for example), which strtol can't - * handle correctly. - * - * XXX: Also, we can't handle large integers properly because strto[u]ll - * isn't in C89. - * - * XXX: Also, we don't properly check floats for overflow, since strtof - * isn't in C89. */ - switch (upb_fielddef_type(p->top->f)) { + /* For integer types, first try parsing with integer-specific routines. + * If these succeed, they will be more accurate for int64/uint64 than + * strtod(). + */ + switch (type) { case UPB_TYPE_ENUM: case UPB_TYPE_INT32: { - long val = strtol(p->accumulated, &end, 0); - if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || end != myend) - goto err; - else + long val = strtol(buf, &end, 0); + if (errno == ERANGE || end != bufend) { + break; + } else if (val > INT32_MAX || val < INT32_MIN) { + return false; + } else { upb_sink_putint32(&p->top->sink, parser_getsel(p), val); - break; - } - case UPB_TYPE_INT64: { - long long val = strtol(p->accumulated, &end, 0); - if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || end != myend) - goto err; - else - upb_sink_putint64(&p->top->sink, parser_getsel(p), val); - break; + return true; + } } case UPB_TYPE_UINT32: { - unsigned long val = strtoul(p->accumulated, &end, 0); - if (val > UINT32_MAX || errno == ERANGE || end != myend) - goto err; - else + unsigned long val = strtoul(buf, &end, 0); + if (end != bufend) { + break; + } else if (val > UINT32_MAX || errno == ERANGE) { + return false; + } else { upb_sink_putuint32(&p->top->sink, parser_getsel(p), val); - break; + return true; + } + } + /* XXX: We can't handle [u]int64 properly on 32-bit machines because + * strto[u]ll isn't in C89. */ + case UPB_TYPE_INT64: { + long val = strtol(buf, &end, 0); + if (errno == ERANGE || end != bufend) { + break; + } else { + upb_sink_putint64(&p->top->sink, parser_getsel(p), val); + return true; + } } case UPB_TYPE_UINT64: { - unsigned long long val = strtoul(p->accumulated, &end, 0); - if (val > UINT64_MAX || errno == ERANGE || end != myend) - goto err; - else + unsigned long val = strtoul(p->accumulated, &end, 0); + if (end != bufend) { + break; + } else if (errno == ERANGE) { + return false; + } else { upb_sink_putuint64(&p->top->sink, parser_getsel(p), val); - break; + return true; + } } - case UPB_TYPE_DOUBLE: { - double val = strtod(p->accumulated, &end); - if (errno == ERANGE || end != myend) - goto err; - else - upb_sink_putdouble(&p->top->sink, parser_getsel(p), val); + default: break; + } + + if (type != UPB_TYPE_DOUBLE && type != UPB_TYPE_FLOAT && is_quoted) { + /* Quoted numbers for integer types are not allowed to be in double form. */ + return false; + } + + if (len == strlen("Infinity") && strcmp(buf, "Infinity") == 0) { + /* C89 does not have an INFINITY macro. */ + val = inf; + } else if (len == strlen("-Infinity") && strcmp(buf, "-Infinity") == 0) { + val = -inf; + } else { + val = strtod(buf, &end); + if (errno == ERANGE || end != bufend) { + return false; } - case UPB_TYPE_FLOAT: { - float val = strtod(p->accumulated, &end); - if (errno == ERANGE || end != myend) - goto err; - else - upb_sink_putfloat(&p->top->sink, parser_getsel(p), val); - break; + } + + switch (type) { +#define CASE(capitaltype, smalltype, ctype, min, max) \ + case UPB_TYPE_ ## capitaltype: { \ + if (modf(val, &dummy) != 0 || val > max || val < min) { \ + return false; \ + } else { \ + upb_sink_put ## smalltype(&p->top->sink, parser_getsel(p), \ + (ctype)val); \ + return true; \ + } \ + break; \ } + case UPB_TYPE_ENUM: + CASE(INT32, int32, int32_t, INT32_MIN, INT32_MAX); + CASE(INT64, int64, int64_t, INT64_MIN, INT64_MAX); + CASE(UINT32, uint32, uint32_t, 0, UINT32_MAX); + CASE(UINT64, uint64, uint64_t, 0, UINT64_MAX); +#undef CASE + + case UPB_TYPE_DOUBLE: + upb_sink_putdouble(&p->top->sink, parser_getsel(p), val); + return true; + case UPB_TYPE_FLOAT: + if ((val > FLT_MAX || val < -FLT_MAX) && val != inf && val != -inf) { + return false; + } else { + upb_sink_putfloat(&p->top->sink, parser_getsel(p), val); + return true; + } default: - UPB_ASSERT(false); + return false; } +} - multipart_end(p); +static bool parse_number(upb_json_parser *p, bool is_quoted) { + size_t len; + const char *buf; - return true; + /* strtol() and friends unfortunately do not support specifying the length of + * the input string, so we need to force a copy into a NULL-terminated buffer. */ + if (!multipart_text(p, "\0", 1, false)) { + return false; + } -err: - upb_status_seterrf(&p->status, "error parsing number: %s", buf); - upb_env_reporterror(p->env, &p->status); - multipart_end(p); - return false; + buf = accumulate_getptr(p, &len); + + if (parse_number_from_buffer(p, buf, is_quoted)) { + multipart_end(p); + return true; + } else { + upb_status_seterrf(&p->status, "error parsing number: %s", buf); + upb_env_reporterror(p->env, &p->status); + multipart_end(p); + return false; + } } static bool parser_putbool(upb_json_parser *p, bool val) { @@ -12085,17 +13124,16 @@ static bool start_stringval(upb_json_parser *p) { multipart_startaccum(p); return true; } - } else if (upb_fielddef_type(p->top->f) == UPB_TYPE_ENUM) { - /* No need to push a frame -- symbolic enum names in quotes remain in the - * current parser frame. - * - * Enum string values must accumulate so we can look up the value in a table - * once it is complete. */ + } else if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL && + upb_fielddef_type(p->top->f) != UPB_TYPE_MESSAGE) { + /* No need to push a frame -- numeric values in quotes remain in the + * current parser frame. These values must accmulate so we can convert + * them all at once at the end. */ multipart_startaccum(p); return true; } else { upb_status_seterrf(&p->status, - "String specified for non-string/non-enum field: %s", + "String specified for bool or submessage field: %s", upb_fielddef_name(p->top->f)); upb_env_reporterror(p->env, &p->status); return false; @@ -12142,6 +13180,15 @@ static bool end_stringval(upb_json_parser *p) { break; } + case UPB_TYPE_INT32: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT32: + case UPB_TYPE_UINT64: + case UPB_TYPE_DOUBLE: + case UPB_TYPE_FLOAT: + ok = parse_number(p, true); + break; + default: UPB_ASSERT(false); upb_status_seterrmsg(&p->status, "Internal error in JSON decoder"); @@ -12185,7 +13232,7 @@ static bool parse_mapentry_key(upb_json_parser *p) { case UPB_TYPE_UINT32: case UPB_TYPE_UINT64: /* Invoke end_number. The accum buffer has the number's text already. */ - if (!parse_number(p)) { + if (!parse_number(p, true)) { return false; } break; @@ -12476,11 +13523,11 @@ static void end_object(upb_json_parser *p) { * final state once, when the closing '"' is seen. */ -#line 1244 "upb/json/parser.rl" +#line 1310 "upb/json/parser.rl" -#line 1156 "upb/json/parser.c" +#line 1222 "upb/json/parser.c" static const char _json_actions[] = { 0, 1, 0, 1, 2, 1, 3, 1, 5, 1, 6, 1, 7, 1, 8, 1, @@ -12629,7 +13676,7 @@ static const int json_en_value_machine = 27; static const int json_en_main = 1; -#line 1247 "upb/json/parser.rl" +#line 1313 "upb/json/parser.rl" size_t parse(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { @@ -12651,7 +13698,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, capture_resume(parser, buf); -#line 1327 "upb/json/parser.c" +#line 1393 "upb/json/parser.c" { int _klen; unsigned int _trans; @@ -12726,118 +13773,118 @@ _match: switch ( *_acts++ ) { case 0: -#line 1159 "upb/json/parser.rl" +#line 1225 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 1: -#line 1160 "upb/json/parser.rl" +#line 1226 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 10; goto _again;} } break; case 2: -#line 1164 "upb/json/parser.rl" +#line 1230 "upb/json/parser.rl" { start_text(parser, p); } break; case 3: -#line 1165 "upb/json/parser.rl" +#line 1231 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_text(parser, p)); } break; case 4: -#line 1171 "upb/json/parser.rl" +#line 1237 "upb/json/parser.rl" { start_hex(parser); } break; case 5: -#line 1172 "upb/json/parser.rl" +#line 1238 "upb/json/parser.rl" { hexdigit(parser, p); } break; case 6: -#line 1173 "upb/json/parser.rl" +#line 1239 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_hex(parser)); } break; case 7: -#line 1179 "upb/json/parser.rl" +#line 1245 "upb/json/parser.rl" { CHECK_RETURN_TOP(escape(parser, p)); } break; case 8: -#line 1185 "upb/json/parser.rl" +#line 1251 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 9: -#line 1188 "upb/json/parser.rl" +#line 1254 "upb/json/parser.rl" { {stack[top++] = cs; cs = 19; goto _again;} } break; case 10: -#line 1190 "upb/json/parser.rl" +#line 1256 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 27; goto _again;} } break; case 11: -#line 1195 "upb/json/parser.rl" +#line 1261 "upb/json/parser.rl" { start_member(parser); } break; case 12: -#line 1196 "upb/json/parser.rl" +#line 1262 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_membername(parser)); } break; case 13: -#line 1199 "upb/json/parser.rl" +#line 1265 "upb/json/parser.rl" { end_member(parser); } break; case 14: -#line 1205 "upb/json/parser.rl" +#line 1271 "upb/json/parser.rl" { start_object(parser); } break; case 15: -#line 1208 "upb/json/parser.rl" +#line 1274 "upb/json/parser.rl" { end_object(parser); } break; case 16: -#line 1214 "upb/json/parser.rl" +#line 1280 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_array(parser)); } break; case 17: -#line 1218 "upb/json/parser.rl" +#line 1284 "upb/json/parser.rl" { end_array(parser); } break; case 18: -#line 1223 "upb/json/parser.rl" +#line 1289 "upb/json/parser.rl" { start_number(parser, p); } break; case 19: -#line 1224 "upb/json/parser.rl" +#line 1290 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 20: -#line 1226 "upb/json/parser.rl" +#line 1292 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_stringval(parser)); } break; case 21: -#line 1227 "upb/json/parser.rl" +#line 1293 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_stringval(parser)); } break; case 22: -#line 1229 "upb/json/parser.rl" +#line 1295 "upb/json/parser.rl" { CHECK_RETURN_TOP(parser_putbool(parser, true)); } break; case 23: -#line 1231 "upb/json/parser.rl" +#line 1297 "upb/json/parser.rl" { CHECK_RETURN_TOP(parser_putbool(parser, false)); } break; case 24: -#line 1233 "upb/json/parser.rl" +#line 1299 "upb/json/parser.rl" { /* null value */ } break; case 25: -#line 1235 "upb/json/parser.rl" +#line 1301 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_subobject(parser)); } break; case 26: -#line 1236 "upb/json/parser.rl" +#line 1302 "upb/json/parser.rl" { end_subobject(parser); } break; case 27: -#line 1241 "upb/json/parser.rl" +#line 1307 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; -#line 1513 "upb/json/parser.c" +#line 1579 "upb/json/parser.c" } } @@ -12850,7 +13897,7 @@ _again: _out: {} } -#line 1268 "upb/json/parser.rl" +#line 1334 "upb/json/parser.rl" if (p != pe) { upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p); @@ -12891,13 +13938,13 @@ static void json_parser_reset(upb_json_parser *p) { /* Emit Ragel initialization of the parser. */ -#line 1567 "upb/json/parser.c" +#line 1633 "upb/json/parser.c" { cs = json_start; top = 0; } -#line 1308 "upb/json/parser.rl" +#line 1374 "upb/json/parser.rl" p->current_state = cs; p->parser_top = top; accumulate_clear(p); @@ -13194,10 +14241,23 @@ static void putstring(upb_json_printer *p, const char *buf, unsigned int len) { * Right now we use %.8g and %.17g for float/double, respectively, to match * proto2::util::JsonFormat's defaults. May want to change this later. */ +const char neginf[] = "\"-Infinity\""; +const char inf[] = "\"Infinity\""; + static size_t fmt_double(double val, char* buf, size_t length) { - size_t n = _upb_snprintf(buf, length, "%.17g", val); - CHKLENGTH(n > 0 && n < length); - return n; + if (val == (1.0 / 0.0)) { + CHKLENGTH(length >= strlen(inf)); + strcpy(buf, inf); + return strlen(inf); + } else if (val == (-1.0 / 0.0)) { + CHKLENGTH(length >= strlen(neginf)); + strcpy(buf, neginf); + return strlen(neginf); + } else { + size_t n = _upb_snprintf(buf, length, "%.17g", val); + CHKLENGTH(n > 0 && n < length); + return n; + } } static size_t fmt_float(float val, char* buf, size_t length) { diff --git a/php/ext/google/protobuf/upb.h b/php/ext/google/protobuf/upb.h index 4b51275d..10371e8b 100644 --- a/php/ext/google/protobuf/upb.h +++ b/php/ext/google/protobuf/upb.h @@ -1,66 +1,13 @@ // Amalgamated source file /* -** Defs are upb's internal representation of the constructs that can appear -** in a .proto file: -** -** - upb::MessageDef (upb_msgdef): describes a "message" construct. -** - upb::FieldDef (upb_fielddef): describes a message field. -** - upb::FileDef (upb_filedef): describes a .proto file and its defs. -** - upb::EnumDef (upb_enumdef): describes an enum. -** - upb::OneofDef (upb_oneofdef): describes a oneof. -** - upb::Def (upb_def): base class of all the others. -** -** TODO: definitions of services. -** -** Like upb_refcounted objects, defs are mutable only until frozen, and are -** only thread-safe once frozen. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. -*/ - -#ifndef UPB_DEF_H_ -#define UPB_DEF_H_ - -/* -** upb::RefCounted (upb_refcounted) -** -** A refcounting scheme that supports circular refs. It accomplishes this by -** partitioning the set of objects into groups such that no cycle spans groups; -** we can then reference-count the group as a whole and ignore refs within the -** group. When objects are mutable, these groups are computed very -** conservatively; we group any objects that have ever had a link between them. -** When objects are frozen, we compute strongly-connected components which -** allows us to be precise and only group objects that are actually cyclic. +** This file contains shared definitions that are widely used across upb. ** ** This is a mixed C/C++ interface that offers a full API to both languages. ** See the top-level README for more information. */ -#ifndef UPB_REFCOUNTED_H_ -#define UPB_REFCOUNTED_H_ - -/* -** upb_table -** -** This header is INTERNAL-ONLY! Its interfaces are not public or stable! -** This file defines very fast int->upb_value (inttable) and string->upb_value -** (strtable) hash tables. -** -** The table uses chained scatter with Brent's variation (inspired by the Lua -** implementation of hash tables). The hash function for strings is Austin -** Appleby's "MurmurHash." -** -** The inttable uses uintptr_t as its key, which guarantees it can be used to -** store pointers or integers of at least 32 bits (upb isn't really useful on -** systems where sizeof(void*) < 4). -** -** The table must be homogenous (all values of the same type). In debug -** mode, we check this on insert and lookup. -*/ - -#ifndef UPB_TABLE_H_ -#define UPB_TABLE_H_ +#ifndef UPB_H_ +#define UPB_H_ // php.h intentionally defined NDEBUG. We have to define this macro in order to // be used together with php.h @@ -68,18 +15,6 @@ #define NDEBUG #endif -#include <stdint.h> -#include <string.h> -/* -** This file contains shared definitions that are widely used across upb. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. -*/ - -#ifndef UPB_H_ -#define UPB_H_ - #include <assert.h> #include <stdarg.h> #include <stdbool.h> @@ -106,6 +41,9 @@ template <int N> class InlinedEnvironment; #define UPB_INLINE static #endif +/* Hints to the compiler about likely/unlikely branches. */ +#define UPB_LIKELY(x) __builtin_expect((x),1) + /* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler * doesn't provide these preprocessor symbols. */ #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) @@ -367,6 +305,16 @@ class PointerBase2 : public PointerBase<T, Base> { #endif +/* A list of types as they are encoded on-the-wire. */ +typedef enum { + UPB_WIRE_TYPE_VARINT = 0, + UPB_WIRE_TYPE_64BIT = 1, + UPB_WIRE_TYPE_DELIMITED = 2, + UPB_WIRE_TYPE_START_GROUP = 3, + UPB_WIRE_TYPE_END_GROUP = 4, + UPB_WIRE_TYPE_32BIT = 5 +} upb_wiretype_t; + /* upb::ErrorSpace ************************************************************/ @@ -695,7 +643,7 @@ void upb_env_uninit(upb_env *e); void upb_env_initonly(upb_env *e); -upb_arena *upb_env_arena(upb_env *e); +UPB_INLINE upb_arena *upb_env_arena(upb_env *e) { return (upb_arena*)e; } bool upb_env_ok(const upb_env *e); void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud); @@ -795,6 +743,106 @@ template <int N> class upb::InlinedEnvironment : public upb::Environment { #endif /* UPB_H_ */ +/* +** upb_decode: parsing into a upb_msg using a upb_msglayout. +*/ + +#ifndef UPB_DECODE_H_ +#define UPB_DECODE_H_ + +/* +** upb::Message is a representation for protobuf messages. +** +** However it differs from other common representations like +** google::protobuf::Message in one key way: it does not prescribe any +** ownership between messages and submessages, and it relies on the +** client to delete each message/submessage/array/map at the appropriate +** time. +** +** A client can access a upb::Message without knowing anything about +** ownership semantics, but to create or mutate a message a user needs +** to implement the memory management themselves. +** +** Currently all messages, arrays, and maps store a upb_alloc* internally. +** Mutating operations use this when they require dynamically-allocated +** memory. We could potentially eliminate this size overhead later by +** letting the user flip a bit on the factory that prevents this from +** being stored. The user would then need to use separate functions where +** the upb_alloc* is passed explicitly. However for handlers to populate +** such structures, they would need a place to store this upb_alloc* during +** parsing; upb_handlers don't currently have a good way to accommodate this. +** +** TODO: UTF-8 checking? +**/ + +#ifndef UPB_MSG_H_ +#define UPB_MSG_H_ + +/* +** Defs are upb's internal representation of the constructs that can appear +** in a .proto file: +** +** - upb::MessageDef (upb_msgdef): describes a "message" construct. +** - upb::FieldDef (upb_fielddef): describes a message field. +** - upb::FileDef (upb_filedef): describes a .proto file and its defs. +** - upb::EnumDef (upb_enumdef): describes an enum. +** - upb::OneofDef (upb_oneofdef): describes a oneof. +** - upb::Def (upb_def): base class of all the others. +** +** TODO: definitions of services. +** +** Like upb_refcounted objects, defs are mutable only until frozen, and are +** only thread-safe once frozen. +** +** This is a mixed C/C++ interface that offers a full API to both languages. +** See the top-level README for more information. +*/ + +#ifndef UPB_DEF_H_ +#define UPB_DEF_H_ + +/* +** upb::RefCounted (upb_refcounted) +** +** A refcounting scheme that supports circular refs. It accomplishes this by +** partitioning the set of objects into groups such that no cycle spans groups; +** we can then reference-count the group as a whole and ignore refs within the +** group. When objects are mutable, these groups are computed very +** conservatively; we group any objects that have ever had a link between them. +** When objects are frozen, we compute strongly-connected components which +** allows us to be precise and only group objects that are actually cyclic. +** +** This is a mixed C/C++ interface that offers a full API to both languages. +** See the top-level README for more information. +*/ + +#ifndef UPB_REFCOUNTED_H_ +#define UPB_REFCOUNTED_H_ + +/* +** upb_table +** +** This header is INTERNAL-ONLY! Its interfaces are not public or stable! +** This file defines very fast int->upb_value (inttable) and string->upb_value +** (strtable) hash tables. +** +** The table uses chained scatter with Brent's variation (inspired by the Lua +** implementation of hash tables). The hash function for strings is Austin +** Appleby's "MurmurHash." +** +** The inttable uses uintptr_t as its key, which guarantees it can be used to +** store pointers or integers of at least 32 bits (upb isn't really useful on +** systems where sizeof(void*) < 4). +** +** The table must be homogenous (all values of the same type). In debug +** mode, we check this on insert and lookup. +*/ + +#ifndef UPB_TABLE_H_ +#define UPB_TABLE_H_ + +#include <stdint.h> +#include <string.h> #ifdef __cplusplus extern "C" { @@ -3857,196 +3905,6 @@ inline bool FileDef::AddDependency(const FileDef* file) { #endif /* UPB_DEF_H_ */ /* -** This file contains definitions of structs that should be considered private -** and NOT stable across versions of upb. -** -** The only reason they are declared here and not in .c files is to allow upb -** and the application (if desired) to embed statically-initialized instances -** of structures like defs. -** -** If you include this file, all guarantees of ABI compatibility go out the -** window! Any code that includes this file needs to recompile against the -** exact same version of upb that they are linking against. -** -** You also need to recompile if you change the value of the UPB_DEBUG_REFS -** flag. -*/ - - -#ifndef UPB_STATICINIT_H_ -#define UPB_STATICINIT_H_ - -#ifdef __cplusplus -/* Because of how we do our typedefs, this header can't be included from C++. */ -#error This file cannot be included from C++ -#endif - -/* upb_refcounted *************************************************************/ - - -/* upb_def ********************************************************************/ - -struct upb_def { - upb_refcounted base; - - const char *fullname; - const upb_filedef* file; - char type; /* A upb_deftype_t (char to save space) */ - - /* Used as a flag during the def's mutable stage. Must be false unless - * it is currently being used by a function on the stack. This allows - * us to easily determine which defs were passed into the function's - * current invocation. */ - bool came_from_user; -}; - -#define UPB_DEF_INIT(name, type, vtbl, refs, ref2s) \ - { UPB_REFCOUNT_INIT(vtbl, refs, ref2s), name, NULL, type, false } - - -/* upb_fielddef ***************************************************************/ - -struct upb_fielddef { - upb_def base; - - union { - int64_t sint; - uint64_t uint; - double dbl; - float flt; - void *bytes; - } defaultval; - union { - const upb_msgdef *def; /* If !msg_is_symbolic. */ - char *name; /* If msg_is_symbolic. */ - } msg; - union { - const upb_def *def; /* If !subdef_is_symbolic. */ - char *name; /* If subdef_is_symbolic. */ - } sub; /* The msgdef or enumdef for this field, if upb_hassubdef(f). */ - bool subdef_is_symbolic; - bool msg_is_symbolic; - const upb_oneofdef *oneof; - bool default_is_string; - bool type_is_set_; /* False until type is explicitly set. */ - bool is_extension_; - bool lazy_; - bool packed_; - upb_intfmt_t intfmt; - bool tagdelim; - upb_fieldtype_t type_; - upb_label_t label_; - uint32_t number_; - uint32_t selector_base; /* Used to index into a upb::Handlers table. */ - uint32_t index_; -}; - -extern const struct upb_refcounted_vtbl upb_fielddef_vtbl; - -#define UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, lazy, \ - packed, name, num, msgdef, subdef, selector_base, \ - index, defaultval, refs, ref2s) \ - { \ - UPB_DEF_INIT(name, UPB_DEF_FIELD, &upb_fielddef_vtbl, refs, ref2s), \ - defaultval, {msgdef}, {subdef}, NULL, false, false, \ - type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES, true, is_extension, \ - lazy, packed, intfmt, tagdelim, type, label, num, selector_base, index \ - } - - -/* upb_msgdef *****************************************************************/ - -struct upb_msgdef { - upb_def base; - - size_t selector_count; - uint32_t submsg_field_count; - - /* Tables for looking up fields by number and name. */ - upb_inttable itof; /* int to field */ - upb_strtable ntof; /* name to field/oneof */ - - /* Is this a map-entry message? */ - bool map_entry; - - /* Whether this message has proto2 or proto3 semantics. */ - upb_syntax_t syntax; - - /* TODO(haberman): proper extension ranges (there can be multiple). */ -}; - -extern const struct upb_refcounted_vtbl upb_msgdef_vtbl; - -/* TODO: also support static initialization of the oneofs table. This will be - * needed if we compile in descriptors that contain oneofs. */ -#define UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof, \ - map_entry, syntax, refs, ref2s) \ - { \ - UPB_DEF_INIT(name, UPB_DEF_MSG, &upb_fielddef_vtbl, refs, ref2s), \ - selector_count, submsg_field_count, itof, ntof, map_entry, syntax \ - } - - -/* upb_enumdef ****************************************************************/ - -struct upb_enumdef { - upb_def base; - - upb_strtable ntoi; - upb_inttable iton; - int32_t defaultval; -}; - -extern const struct upb_refcounted_vtbl upb_enumdef_vtbl; - -#define UPB_ENUMDEF_INIT(name, ntoi, iton, defaultval, refs, ref2s) \ - { UPB_DEF_INIT(name, UPB_DEF_ENUM, &upb_enumdef_vtbl, refs, ref2s), ntoi, \ - iton, defaultval } - - -/* upb_oneofdef ***************************************************************/ - -struct upb_oneofdef { - upb_refcounted base; - - uint32_t index; /* Index within oneofs. */ - const char *name; - upb_strtable ntof; - upb_inttable itof; - const upb_msgdef *parent; -}; - -extern const struct upb_refcounted_vtbl upb_oneofdef_vtbl; - -#define UPB_ONEOFDEF_INIT(name, ntof, itof, refs, ref2s) \ - { UPB_REFCOUNT_INIT(&upb_oneofdef_vtbl, refs, ref2s), 0, name, ntof, itof } - - -/* upb_symtab *****************************************************************/ - -struct upb_symtab { - upb_refcounted base; - - upb_strtable symtab; -}; - -struct upb_filedef { - upb_refcounted base; - - const char *name; - const char *package; - const char *phpprefix; - const char *phpnamespace; - upb_syntax_t syntax; - - upb_inttable defs; - upb_inttable deps; -}; - -extern const struct upb_refcounted_vtbl upb_filedef_vtbl; - -#endif /* UPB_STATICINIT_H_ */ -/* ** upb::Handlers (upb_handlers) ** ** A upb_handlers is like a virtual table for a upb_msgdef. Each field of the @@ -4150,7 +4008,8 @@ UPB_END_EXTERN_C /* Static selectors for upb::Handlers. */ #define UPB_STARTMSG_SELECTOR 0 #define UPB_ENDMSG_SELECTOR 1 -#define UPB_STATIC_SELECTOR_COUNT 2 +#define UPB_UNKNOWN_SELECTOR 2 +#define UPB_STATIC_SELECTOR_COUNT 3 /* Static selectors for upb::BytesHandler. */ #define UPB_STARTSTR_SELECTOR 0 @@ -4679,6 +4538,8 @@ UPB_BEGIN_EXTERN_C /* Native C API. */ /* Handler function typedefs. */ +typedef bool upb_unknown_handlerfunc(void *c, const void *hd, const char *buf, + size_t n); typedef bool upb_startmsg_handlerfunc(void *c, const void*); typedef bool upb_endmsg_handlerfunc(void *c, const void *, upb_status *status); typedef void* upb_startfield_handlerfunc(void *c, const void *hd); @@ -4732,6 +4593,8 @@ const upb_status *upb_handlers_status(upb_handlers *h); void upb_handlers_clearerr(upb_handlers *h); const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h); bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *hfree); +bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func, + upb_handlerattr *attr); bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func, upb_handlerattr *attr); @@ -6301,6 +6164,18 @@ UPB_INLINE size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel, return handler(s->closure, hd, buf, n, handle); } +UPB_INLINE bool upb_sink_putunknown(upb_sink *s, const char *buf, size_t n) { + typedef upb_unknown_handlerfunc func; + func *handler; + const void *hd; + if (!s->handlers) return true; + handler = (func *)upb_handlers_gethandler(s->handlers, UPB_UNKNOWN_SELECTOR); + + if (!handler) return n; + hd = upb_handlers_gethandlerdata(s->handlers, UPB_UNKNOWN_SELECTOR); + return handler(s->closure, hd, buf, n); +} + UPB_INLINE bool upb_sink_startmsg(upb_sink *s) { typedef upb_startmsg_handlerfunc func; func *startmsg; @@ -6505,34 +6380,6 @@ inline bool BufferSource::PutBuffer(const char *buf, size_t len, #endif #endif -/* -** upb::Message is a representation for protobuf messages. -** -** However it differs from other common representations like -** google::protobuf::Message in one key way: it does not prescribe any -** ownership between messages and submessages, and it relies on the -** client to delete each message/submessage/array/map at the appropriate -** time. -** -** A client can access a upb::Message without knowing anything about -** ownership semantics, but to create or mutate a message a user needs -** to implement the memory management themselves. -** -** Currently all messages, arrays, and maps store a upb_alloc* internally. -** Mutating operations use this when they require dynamically-allocated -** memory. We could potentially eliminate this size overhead later by -** letting the user flip a bit on the factory that prevents this from -** being stored. The user would then need to use separate functions where -** the upb_alloc* is passed explicitly. However for handlers to populate -** such structures, they would need a place to store this upb_alloc* during -** parsing; upb_handlers don't currently have a good way to accommodate this. -** -** TODO: UTF-8 checking? -**/ - -#ifndef UPB_MSG_H_ -#define UPB_MSG_H_ - #ifdef __cplusplus @@ -6569,21 +6416,6 @@ typedef void upb_msg; * instances of this from a upb_msgfactory, and the factory always owns the * msglayout. */ -/* Gets the factory for this layout */ -upb_msgfactory *upb_msglayout_factory(const upb_msglayout *l); - -/* Get the msglayout for a submessage. This requires that this field is a - * submessage, ie. upb_fielddef_issubmsg(upb_msglayout_msgdef(l)) == true. - * - * Since map entry messages don't have layouts, if upb_fielddef_ismap(f) == true - * then this function will return the layout for the map's value. It requires - * that the value type of the map field is a submessage. */ -const upb_msglayout *upb_msglayout_sublayout(const upb_msglayout *l, - const upb_fielddef *f); - -/* Returns the msgdef for this msglayout. */ -const upb_msgdef *upb_msglayout_msgdef(const upb_msglayout *l); - /** upb_visitor ***************************************************************/ @@ -6629,6 +6461,23 @@ const upb_visitorplan *upb_msgfactory_getvisitorplan(upb_msgfactory *f, const upb_handlers *h); +/** upb_stringview ************************************************************/ + +typedef struct { + const char *data; + size_t size; +} upb_stringview; + +UPB_INLINE upb_stringview upb_stringview_make(const char *data, size_t size) { + upb_stringview ret; + ret.data = data; + ret.size = size; + return ret; +} + +#define UPB_STRINGVIEW_INIT(ptr, len) {ptr, len} + + /** upb_msgval ****************************************************************/ /* A union representing all possible protobuf values. Used for generic get/set @@ -6646,10 +6495,7 @@ typedef union { const upb_msg* msg; const upb_array* arr; const void* ptr; - struct { - const char *ptr; - size_t len; - } str; + upb_stringview str; } upb_msgval; #define ACCESSORS(name, membername, ctype) \ @@ -6676,22 +6522,12 @@ ACCESSORS(map, map, const upb_map*) ACCESSORS(msg, msg, const upb_msg*) ACCESSORS(ptr, ptr, const void*) ACCESSORS(arr, arr, const upb_array*) +ACCESSORS(str, str, upb_stringview) #undef ACCESSORS -UPB_INLINE upb_msgval upb_msgval_str(const char *ptr, size_t len) { - upb_msgval ret; - ret.str.ptr = ptr; - ret.str.len = len; - return ret; -} - -UPB_INLINE const char* upb_msgval_getstr(upb_msgval val) { - return val.str.ptr; -} - -UPB_INLINE size_t upb_msgval_getstrlen(upb_msgval val) { - return val.str.len; +UPB_INLINE upb_msgval upb_msgval_makestr(const char *data, size_t size) { + return upb_msgval_str(upb_stringview_make(data, size)); } @@ -6716,19 +6552,29 @@ size_t upb_msg_sizeof(const upb_msglayout *l); * upb_msg_uninit() must be called to release internally-allocated memory * unless the allocator is an arena that does not require freeing. * + * Please note that upb_msg_init() may return a value that is different than + * |msg|, so you must assign the return value and not cast your memory block + * to upb_msg* directly! + * * Please note that upb_msg_uninit() does *not* free any submessages, maps, * or arrays referred to by this message's fields. You must free them manually - * yourself. */ -void upb_msg_init(upb_msg *msg, const upb_msglayout *l, upb_alloc *a); -void upb_msg_uninit(upb_msg *msg, const upb_msglayout *l); + * yourself. + * + * upb_msg_uninit returns the original memory block, which may be useful if + * you dynamically allocated it (though upb_msg_new() would normally be more + * appropriate in this case). */ +upb_msg *upb_msg_init(void *msg, const upb_msglayout *l, upb_alloc *a); +void *upb_msg_uninit(upb_msg *msg, const upb_msglayout *l); /* Like upb_msg_init() / upb_msg_uninit(), except the message's memory is * allocated / freed from the given upb_alloc. */ upb_msg *upb_msg_new(const upb_msglayout *l, upb_alloc *a); void upb_msg_free(upb_msg *msg, const upb_msglayout *l); -/* Returns the upb_alloc for the given message. */ -upb_alloc *upb_msg_alloc(const upb_msg *msg, const upb_msglayout *l); +/* Returns the upb_alloc for the given message. + * TODO(haberman): get rid of this? Not sure we want to be storing this + * for every message. */ +upb_alloc *upb_msg_alloc(const upb_msg *msg); /* Packs the tree of messages rooted at "msg" into a single hunk of memory, * allocated from the given allocator. */ @@ -6748,25 +6594,14 @@ void *upb_msg_pack(const upb_msg *msg, const upb_msglayout *l, * arenas). */ upb_msgval upb_msg_get(const upb_msg *msg, - const upb_fielddef *f, + int field_index, const upb_msglayout *l); /* May only be called for fields where upb_fielddef_haspresence(f) == true. */ bool upb_msg_has(const upb_msg *msg, - const upb_fielddef *f, + int field_index, const upb_msglayout *l); -/* Returns NULL if no field in the oneof is set. */ -const upb_fielddef *upb_msg_getoneofcase(const upb_msg *msg, - const upb_oneofdef *o, - const upb_msglayout *l); - -/* Returns true if any field in the oneof is set. */ -bool upb_msg_hasoneof(const upb_msg *msg, - const upb_oneofdef *o, - const upb_msglayout *l); - - /* Mutable message API. May only be called by the owner of the message who * knows its ownership scheme and how to keep it consistent. */ @@ -6774,8 +6609,8 @@ bool upb_msg_hasoneof(const upb_msg *msg, * management: if you overwrite a pointer to a msg/array/map/string without * cleaning it up (or using an arena) it will leak. */ -bool upb_msg_set(upb_msg *msg, - const upb_fielddef *f, +void upb_msg_set(upb_msg *msg, + int field_index, upb_msgval val, const upb_msglayout *l); @@ -6786,12 +6621,7 @@ bool upb_msg_set(upb_msg *msg, * arrays/maps/strings/msgs that this field may have pointed to. */ bool upb_msg_clearfield(upb_msg *msg, - const upb_fielddef *f, - const upb_msglayout *l); - -/* Clears all fields in the oneof such that none of them are set. */ -bool upb_msg_clearoneof(upb_msg *msg, - const upb_oneofdef *o, + int field_index, const upb_msglayout *l); /* TODO(haberman): copyfrom()/mergefrom()? */ @@ -6904,9 +6734,288 @@ bool upb_msg_getscalarhandlerdata(const upb_handlers *h, size_t *offset, int32_t *hasbit); + +/** Interfaces for generated code *********************************************/ + +#define UPB_NOT_IN_ONEOF UINT16_MAX +#define UPB_NO_HASBIT UINT16_MAX +#define UPB_NO_SUBMSG UINT16_MAX + +typedef struct { + uint32_t number; + uint32_t offset; /* If in a oneof, offset of default in default_msg below. */ + uint16_t hasbit; /* UPB_NO_HASBIT if no hasbit. */ + uint16_t oneof_index; /* UPB_NOT_IN_ONEOF if not in a oneof. */ + uint16_t submsg_index; /* UPB_NO_SUBMSG if no submsg. */ + uint8_t type; + uint8_t label; +} upb_msglayout_fieldinit_v1; + +typedef struct { + uint32_t data_offset; + uint32_t case_offset; +} upb_msglayout_oneofinit_v1; + +typedef struct upb_msglayout_msginit_v1 { + const struct upb_msglayout_msginit_v1 *const* submsgs; + const upb_msglayout_fieldinit_v1 *fields; + const upb_msglayout_oneofinit_v1 *oneofs; + void *default_msg; + /* Must be aligned to sizeof(void*). Doesn't include internal members like + * unknown fields, extension dict, pointer to msglayout, etc. */ + uint32_t size; + uint16_t field_count; + uint16_t oneof_count; + bool extendable; + bool is_proto2; +} upb_msglayout_msginit_v1; + +#define UPB_ALIGN_UP_TO(val, align) ((val + (align - 1)) & -align) +#define UPB_ALIGNED_SIZEOF(type) UPB_ALIGN_UP_TO(sizeof(type), sizeof(void*)) + +/* Initialize/uninitialize a msglayout from a msginit. If upb uses v1 + * internally, this will not allocate any memory. Should only be used by + * generated code. */ +upb_msglayout *upb_msglayout_frominit_v1( + const upb_msglayout_msginit_v1 *init, upb_alloc *a); +void upb_msglayout_uninit_v1(upb_msglayout *layout, upb_alloc *a); + UPB_END_EXTERN_C #endif /* UPB_MSG_H_ */ + +UPB_BEGIN_EXTERN_C + +bool upb_decode(upb_stringview buf, void *msg, + const upb_msglayout_msginit_v1 *l, upb_env *env); + +UPB_END_EXTERN_C + +#endif /* UPB_DECODE_H_ */ +/* +** structs.int.h: structures definitions that are internal to upb. +*/ + +#ifndef UPB_STRUCTS_H_ +#define UPB_STRUCTS_H_ + +struct upb_array { + upb_fieldtype_t type; + uint8_t element_size; + void *data; /* Each element is element_size. */ + size_t len; /* Measured in elements. */ + size_t size; /* Measured in elements. */ + upb_alloc *alloc; +}; + +#endif /* UPB_STRUCTS_H_ */ + +/* +** This file contains definitions of structs that should be considered private +** and NOT stable across versions of upb. +** +** The only reason they are declared here and not in .c files is to allow upb +** and the application (if desired) to embed statically-initialized instances +** of structures like defs. +** +** If you include this file, all guarantees of ABI compatibility go out the +** window! Any code that includes this file needs to recompile against the +** exact same version of upb that they are linking against. +** +** You also need to recompile if you change the value of the UPB_DEBUG_REFS +** flag. +*/ + + +#ifndef UPB_STATICINIT_H_ +#define UPB_STATICINIT_H_ + +#ifdef __cplusplus +/* Because of how we do our typedefs, this header can't be included from C++. */ +#error This file cannot be included from C++ +#endif + +/* upb_refcounted *************************************************************/ + + +/* upb_def ********************************************************************/ + +struct upb_def { + upb_refcounted base; + + const char *fullname; + const upb_filedef* file; + char type; /* A upb_deftype_t (char to save space) */ + + /* Used as a flag during the def's mutable stage. Must be false unless + * it is currently being used by a function on the stack. This allows + * us to easily determine which defs were passed into the function's + * current invocation. */ + bool came_from_user; +}; + +#define UPB_DEF_INIT(name, type, vtbl, refs, ref2s) \ + { UPB_REFCOUNT_INIT(vtbl, refs, ref2s), name, NULL, type, false } + + +/* upb_fielddef ***************************************************************/ + +struct upb_fielddef { + upb_def base; + + union { + int64_t sint; + uint64_t uint; + double dbl; + float flt; + void *bytes; + } defaultval; + union { + const upb_msgdef *def; /* If !msg_is_symbolic. */ + char *name; /* If msg_is_symbolic. */ + } msg; + union { + const upb_def *def; /* If !subdef_is_symbolic. */ + char *name; /* If subdef_is_symbolic. */ + } sub; /* The msgdef or enumdef for this field, if upb_hassubdef(f). */ + bool subdef_is_symbolic; + bool msg_is_symbolic; + const upb_oneofdef *oneof; + bool default_is_string; + bool type_is_set_; /* False until type is explicitly set. */ + bool is_extension_; + bool lazy_; + bool packed_; + upb_intfmt_t intfmt; + bool tagdelim; + upb_fieldtype_t type_; + upb_label_t label_; + uint32_t number_; + uint32_t selector_base; /* Used to index into a upb::Handlers table. */ + uint32_t index_; +}; + +extern const struct upb_refcounted_vtbl upb_fielddef_vtbl; + +#define UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, lazy, \ + packed, name, num, msgdef, subdef, selector_base, \ + index, defaultval, refs, ref2s) \ + { \ + UPB_DEF_INIT(name, UPB_DEF_FIELD, &upb_fielddef_vtbl, refs, ref2s), \ + defaultval, {msgdef}, {subdef}, NULL, false, false, \ + type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES, true, is_extension, \ + lazy, packed, intfmt, tagdelim, type, label, num, selector_base, index \ + } + + +/* upb_msgdef *****************************************************************/ + +struct upb_msgdef { + upb_def base; + + size_t selector_count; + uint32_t submsg_field_count; + + /* Tables for looking up fields by number and name. */ + upb_inttable itof; /* int to field */ + upb_strtable ntof; /* name to field/oneof */ + + /* Is this a map-entry message? */ + bool map_entry; + + /* Whether this message has proto2 or proto3 semantics. */ + upb_syntax_t syntax; + + /* TODO(haberman): proper extension ranges (there can be multiple). */ +}; + +extern const struct upb_refcounted_vtbl upb_msgdef_vtbl; + +/* TODO: also support static initialization of the oneofs table. This will be + * needed if we compile in descriptors that contain oneofs. */ +#define UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof, \ + map_entry, syntax, refs, ref2s) \ + { \ + UPB_DEF_INIT(name, UPB_DEF_MSG, &upb_fielddef_vtbl, refs, ref2s), \ + selector_count, submsg_field_count, itof, ntof, map_entry, syntax \ + } + + +/* upb_enumdef ****************************************************************/ + +struct upb_enumdef { + upb_def base; + + upb_strtable ntoi; + upb_inttable iton; + int32_t defaultval; +}; + +extern const struct upb_refcounted_vtbl upb_enumdef_vtbl; + +#define UPB_ENUMDEF_INIT(name, ntoi, iton, defaultval, refs, ref2s) \ + { UPB_DEF_INIT(name, UPB_DEF_ENUM, &upb_enumdef_vtbl, refs, ref2s), ntoi, \ + iton, defaultval } + + +/* upb_oneofdef ***************************************************************/ + +struct upb_oneofdef { + upb_refcounted base; + + uint32_t index; /* Index within oneofs. */ + const char *name; + upb_strtable ntof; + upb_inttable itof; + const upb_msgdef *parent; +}; + +extern const struct upb_refcounted_vtbl upb_oneofdef_vtbl; + +#define UPB_ONEOFDEF_INIT(name, ntof, itof, refs, ref2s) \ + { UPB_REFCOUNT_INIT(&upb_oneofdef_vtbl, refs, ref2s), 0, name, ntof, itof } + + +/* upb_symtab *****************************************************************/ + +struct upb_symtab { + upb_refcounted base; + + upb_strtable symtab; +}; + +struct upb_filedef { + upb_refcounted base; + + const char *name; + const char *package; + const char *phpprefix; + const char *phpnamespace; + upb_syntax_t syntax; + + upb_inttable defs; + upb_inttable deps; +}; + +extern const struct upb_refcounted_vtbl upb_filedef_vtbl; + +#endif /* UPB_STATICINIT_H_ */ +/* +** upb_encode: parsing into a upb_msg using a upb_msglayout. +*/ + +#ifndef UPB_ENCODE_H_ +#define UPB_ENCODE_H_ + + +UPB_BEGIN_EXTERN_C + +char *upb_encode(const void *msg, const upb_msglayout_msginit_v1 *l, + upb_env *env, size_t *size); + +UPB_END_EXTERN_C + +#endif /* UPB_ENCODE_H_ */ /* ** upb::descriptor::Reader (upb_descreader) ** @@ -8296,21 +8405,9 @@ UPB_INLINE void upb_pbdecoder_unpackdispatch(uint64_t dispatch, uint64_t *ofs, extern "C" { #endif -/* A list of types as they are encoded on-the-wire. */ -typedef enum { - UPB_WIRE_TYPE_VARINT = 0, - UPB_WIRE_TYPE_64BIT = 1, - UPB_WIRE_TYPE_DELIMITED = 2, - UPB_WIRE_TYPE_START_GROUP = 3, - UPB_WIRE_TYPE_END_GROUP = 4, - UPB_WIRE_TYPE_32BIT = 5 -} upb_wiretype_t; - #define UPB_MAX_WIRE_TYPE 5 -/* The maximum number of bytes that it takes to encode a 64-bit varint. - * Note that with a better encoding this could be 9 (TODO: write up a - * wiki document about this). */ +/* The maximum number of bytes that it takes to encode a 64-bit varint. */ #define UPB_PB_VARINT_MAX_LEN 10 /* Array of the "native" (ie. non-packed-repeated) wire type for the given a |