aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Yang <TeBoring@users.noreply.github.com>2016-09-15 11:09:01 -0700
committerGitHub <noreply@github.com>2016-09-15 11:09:01 -0700
commite0e54661f76183684dca66694967a60cbb10f04e (patch)
tree0a2a20f984705fdf6ef13de8829901b80f88efb5
parent86fcd879b38505446799b2f2a2929415ddad620a (diff)
downloadprotobuf-e0e54661f76183684dca66694967a60cbb10f04e.tar.gz
protobuf-e0e54661f76183684dca66694967a60cbb10f04e.tar.bz2
protobuf-e0e54661f76183684dca66694967a60cbb10f04e.zip
Check in php implementation. (#2052)
This pull request includes two implementation: C extension and PHP package. Both implementations support encode/decode of singular, repeated and map fields.
-rw-r--r--.gitignore15
-rw-r--r--README.md2
-rw-r--r--cmake/extract_includes.bat.in1
-rw-r--r--cmake/libprotoc.cmake1
-rw-r--r--composer.json24
-rw-r--r--php/README.md99
-rw-r--r--php/ext/google/protobuf/array.c388
-rw-r--r--php/ext/google/protobuf/config.m48
-rw-r--r--php/ext/google/protobuf/def.c609
-rw-r--r--php/ext/google/protobuf/encode_decode.c1245
-rw-r--r--php/ext/google/protobuf/map.c470
-rw-r--r--php/ext/google/protobuf/message.c326
-rw-r--r--php/ext/google/protobuf/package.xml74
-rw-r--r--php/ext/google/protobuf/protobuf.c150
-rw-r--r--php/ext/google/protobuf/protobuf.h505
-rw-r--r--php/ext/google/protobuf/storage.c644
-rw-r--r--php/ext/google/protobuf/test.php15
-rw-r--r--php/ext/google/protobuf/type_check.c310
-rw-r--r--php/ext/google/protobuf/upb.c3797
-rw-r--r--php/ext/google/protobuf/upb.h3036
-rw-r--r--php/ext/google/protobuf/utf8.c68
-rw-r--r--php/ext/google/protobuf/utf8.h36
-rw-r--r--php/src/Google/Protobuf/Internal/DescriptorPool.php162
-rw-r--r--php/src/Google/Protobuf/Internal/EnumBuilderContext.php63
-rw-r--r--php/src/Google/Protobuf/Internal/GPBLabel.php40
-rw-r--r--php/src/Google/Protobuf/Internal/GPBType.php55
-rw-r--r--php/src/Google/Protobuf/Internal/GPBUtil.php161
-rw-r--r--php/src/Google/Protobuf/Internal/GPBWire.php583
-rw-r--r--php/src/Google/Protobuf/Internal/InputStream.php323
-rw-r--r--php/src/Google/Protobuf/Internal/MapEntry.php57
-rw-r--r--php/src/Google/Protobuf/Internal/MapField.php321
-rw-r--r--php/src/Google/Protobuf/Internal/Message.php671
-rw-r--r--php/src/Google/Protobuf/Internal/MessageBuilderContext.php120
-rw-r--r--php/src/Google/Protobuf/Internal/OneofField.php77
-rw-r--r--php/src/Google/Protobuf/Internal/OutputStream.php143
-rw-r--r--php/src/Google/Protobuf/Internal/RepeatedField.php303
-rw-r--r--php/src/Google/Protobuf/Internal/Type.php175
-rw-r--r--php/src/Google/Protobuf/descriptor.php541
-rw-r--r--php/src/Google/Protobuf/descriptor_internal.pb.php2532
-rw-r--r--php/src/phpdoc.dist.xml15
-rw-r--r--php/tests/array_test.php888
-rw-r--r--php/tests/autoload.php4
-rw-r--r--php/tests/encode_decode_test.php136
-rw-r--r--php/tests/generated_class_test.php557
-rw-r--r--php/tests/map_field_test.php648
-rw-r--r--php/tests/memory_leak_test.php73
-rw-r--r--php/tests/php_implementation_test.php443
-rw-r--r--php/tests/test.pb.php1385
-rw-r--r--php/tests/test.proto136
-rwxr-xr-xphp/tests/test.sh23
-rw-r--r--php/tests/test_base.php92
-rw-r--r--php/tests/test_include.pb.php36
-rw-r--r--php/tests/test_util.php393
-rw-r--r--phpunit.xml13
-rw-r--r--src/Makefile.am2
-rw-r--r--src/google/protobuf/compiler/main.cc10
-rw-r--r--src/google/protobuf/compiler/php/php_generator.cc781
-rw-r--r--src/google/protobuf/compiler/php/php_generator.h57
58 files changed, 20086 insertions, 3756 deletions
diff --git a/.gitignore b/.gitignore
index 052dd14d..980f7407 100644
--- a/.gitignore
+++ b/.gitignore
@@ -118,3 +118,18 @@ conformance/lite/
conformance/nonexistent_tests.txt
conformance/protoc_middleman
conformance/succeeding_tests.txt
+
+# php test output
+composer.lock
+php/ext/google/protobuf/.libs/
+php/ext/google/protobuf/Makefile.fragments
+php/ext/google/protobuf/Makefile.global
+php/ext/google/protobuf/Makefile.objects
+php/ext/google/protobuf/acinclude.m4
+php/ext/google/protobuf/build/
+php/ext/google/protobuf/config.h
+php/ext/google/protobuf/config.nice
+php/ext/google/protobuf/configure.in
+php/ext/google/protobuf/mkinstalldirs
+php/ext/google/protobuf/run-tests.php
+vendor/
diff --git a/README.md b/README.md
index 67be3e9b..32c1992d 100644
--- a/README.md
+++ b/README.md
@@ -65,7 +65,7 @@ how to install protobuf runtime for that specific language:
| JavaScript | [js](js) |
| Ruby | [ruby](ruby) |
| Go | [golang/protobuf](https://github.com/golang/protobuf) |
-| PHP | TBD |
+| PHP | [php](php) |
Usage
diff --git a/cmake/extract_includes.bat.in b/cmake/extract_includes.bat.in
index 9edafca8..7481f0cf 100644
--- a/cmake/extract_includes.bat.in
+++ b/cmake/extract_includes.bat.in
@@ -32,6 +32,7 @@ copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\js\js_generat
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_generator.h include\google\protobuf\compiler\objectivec\objectivec_generator.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_helpers.h include\google\protobuf\compiler\objectivec\objectivec_helpers.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\parser.h include\google\protobuf\compiler\parser.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\php\php_generator.h include\google\protobuf\compiler\php\php_generator.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.h include\google\protobuf\compiler\plugin.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.pb.h include\google\protobuf\compiler\plugin.pb.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\python_generator.h include\google\protobuf\compiler\python\python_generator.h
diff --git a/cmake/libprotoc.cmake b/cmake/libprotoc.cmake
index 8df8986a..71c3494c 100644
--- a/cmake/libprotoc.cmake
+++ b/cmake/libprotoc.cmake
@@ -84,6 +84,7 @@ set(libprotoc_files
${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
+ ${protobuf_source_dir}/src/google/protobuf/compiler/php/php_generator.cc
${protobuf_source_dir}/src/google/protobuf/compiler/plugin.cc
${protobuf_source_dir}/src/google/protobuf/compiler/plugin.pb.cc
${protobuf_source_dir}/src/google/protobuf/compiler/python/python_generator.cc
diff --git a/composer.json b/composer.json
new file mode 100644
index 00000000..8b73a2b9
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,24 @@
+{
+ "name": "google/protobuf",
+ "type": "library",
+ "description": "proto library for PHP",
+ "keywords": ["proto"],
+ "homepage": "https://developers.google.com/protocol-buffers/",
+ "license": "BSD-3-Clause",
+ "require": {
+ "php": ">=5.5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": ">=4.8.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Google\\": "php/src/Google"
+ },
+ "files": [
+ "php/src/Google/Protobuf/descriptor.php",
+ "php/src/Google/Protobuf/descriptor_internal.pb.php",
+ "php/src/Google/Protobuf/Internal/Type.php"
+ ]
+ }
+}
diff --git a/php/README.md b/php/README.md
new file mode 100644
index 00000000..2f5380f5
--- /dev/null
+++ b/php/README.md
@@ -0,0 +1,99 @@
+This directory contains the Protocol Buffers runtime implementation via both a
+pure PHP package and a native c extension. The pure PHP package is intended to
+provide usability to wider range of PHP platforms, while the c extension is
+intended to provide higher performance. Both implementations provide the same
+runtime APIs and share the same generated code. Users don’t need to re-generate
+code for the same proto definition when they want to switch the implementation
+later.
+
+Both implementations make use of generated PHP code that defines message and
+enum types in PHP. We strongly recommend using protoc's PHP generation support
+with .proto files. The build process in this directory only installs the
+extension/package; you need to install protoc as well to have PHP code
+generation functionality.
+
+## Requirements
+
+To use PHP runtime library requires:
+
+- PHP 5.5 or above.
+
+## Installation
+
+### C Extension
+
+#### Prerequirements
+
+To install the c extension, the following tools are needed:
+* autoconf
+* automake
+* libtool
+* make
+* gcc
+* pear
+* pecl
+
+On Ubuntu, you can install them with:
+```
+sudo apt-get install php-pear php5-dev autoconf automake libtool make gcc
+```
+On other platforms, please use the corresponding package managing tool to
+install them before proceeding.
+
+#### Installation from Source (Building extension)
+
+To build the c extension, run the following command:
+```
+cd ext/google/protobuf
+pear package
+sudo pecl install protobuf-{VERSION}.tgz
+```
+
+#### Installation from PECL
+
+When we release a version of Protocol Buffers, we will upload the extension to
+[PECL](https://pecl.php.net/). To use this pre-packaged extension, simply
+install it as you would any other extension:
+
+```
+sudo pecl install protobuf-{VERSION}
+```
+
+### PHP Package
+
+#### Installation from composer
+
+Simply add "google/protobuf" to the 'require' section of composer.json in your
+project.
+
+### Protoc
+
+Once the extension or package is installed, if you wish to generate PHP code
+from a `.proto` file, you will also want to install the Protocol Buffers
+compiler (protoc), as described in this repository's main `README` file. The
+version of `protoc` included in the latest release supports the `--php_out`
+option to generate PHP code:
+```
+protoc --php_out=out_dir test.proto
+```
+
+## Usage
+
+For general guide:
+ https://developers.google.com/protocol-buffers/phptutorial/
+For generated code:
+ https://developers.google.com/protocol-buffers/docs/reference/php-generated
+
+Known Issues
+------------
+
+* Missing native support for well known types.
+* Missing support for proto2.
+* No API provided for clear/copy messages.
+* No API provided for encoding/decoding with stream.
+* Map fields may not be garbage-collected if there is cycle reference.
+* No debug information for messages in c extension.
+* HHVM not tested.
+* PHP 7.0 not tested.
+* C extension not tested on windows.
+* Message name cannot be Empty.
diff --git a/php/ext/google/protobuf/array.c b/php/ext/google/protobuf/array.c
new file mode 100644
index 00000000..fde4f726
--- /dev/null
+++ b/php/ext/google/protobuf/array.c
@@ -0,0 +1,388 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <ext/spl/spl_iterators.h>
+#include <Zend/zend_API.h>
+#include <Zend/zend_interfaces.h>
+
+#include "protobuf.h"
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
+ ZEND_ARG_INFO(0, index)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, newval)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry repeated_field_methods[] = {
+ PHP_ME(RepeatedField, __construct, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedField, append, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedField, count, arginfo_void, ZEND_ACC_PUBLIC)
+ ZEND_FE_END
+};
+
+// Forward declare static functions.
+
+static zend_object_value repeated_field_create(zend_class_entry *ce TSRMLS_DC);
+static void repeated_field_free(void *object TSRMLS_DC);
+static int repeated_field_array_init(zval *array, upb_fieldtype_t type,
+ uint size ZEND_FILE_LINE_DC);
+static void repeated_field_free_element(void *object);
+static void repeated_field_write_dimension(zval *object, zval *offset,
+ zval *value TSRMLS_DC);
+static int repeated_field_has_dimension(zval *object, zval *offset TSRMLS_DC);
+static HashTable *repeated_field_get_gc(zval *object, zval ***table,
+ int *n TSRMLS_DC);
+
+// -----------------------------------------------------------------------------
+// RepeatedField creation/desctruction
+// -----------------------------------------------------------------------------
+
+zend_class_entry* repeated_field_type;
+zend_object_handlers* repeated_field_handlers;
+
+void repeated_field_init(TSRMLS_D) {
+ zend_class_entry class_type;
+ const char* class_name = "Google\\Protobuf\\Internal\\RepeatedField";
+ INIT_CLASS_ENTRY_EX(class_type, class_name, strlen(class_name),
+ repeated_field_methods);
+
+ repeated_field_type = zend_register_internal_class(&class_type TSRMLS_CC);
+ repeated_field_type->create_object = repeated_field_create;
+
+ zend_class_implements(repeated_field_type TSRMLS_CC, 2, spl_ce_ArrayAccess,
+ spl_ce_Countable);
+
+ repeated_field_handlers = PEMALLOC(zend_object_handlers);
+ memcpy(repeated_field_handlers, zend_get_std_object_handlers(),
+ sizeof(zend_object_handlers));
+ repeated_field_handlers->get_gc = repeated_field_get_gc;
+}
+
+static zend_object_value repeated_field_create(zend_class_entry *ce TSRMLS_DC) {
+ zend_object_value retval = {0};
+ RepeatedField *intern;
+
+ intern = emalloc(sizeof(RepeatedField));
+ memset(intern, 0, sizeof(RepeatedField));
+
+ zend_object_std_init(&intern->std, ce TSRMLS_CC);
+ object_properties_init(&intern->std, ce);
+
+ intern->array = NULL;
+ intern->type = 0;
+ intern->msg_ce = NULL;
+
+ retval.handle = zend_objects_store_put(
+ intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
+ (zend_objects_free_object_storage_t)repeated_field_free, NULL TSRMLS_CC);
+ retval.handlers = repeated_field_handlers;
+
+ return retval;
+}
+
+static void repeated_field_free(void *object TSRMLS_DC) {
+ RepeatedField *intern = object;
+ zend_object_std_dtor(&intern->std TSRMLS_CC);
+ zval_ptr_dtor(&intern->array);
+ efree(object);
+}
+
+static int repeated_field_array_init(zval *array, upb_fieldtype_t type,
+ uint size ZEND_FILE_LINE_DC) {
+ ALLOC_HASHTABLE(Z_ARRVAL_P(array));
+
+ switch (type) {
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_MESSAGE:
+ zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
+ break;
+ default:
+ zend_hash_init(Z_ARRVAL_P(array), size, NULL, repeated_field_free_element,
+ 0);
+ }
+ Z_TYPE_P(array) = IS_ARRAY;
+ return SUCCESS;
+}
+
+static void repeated_field_free_element(void *object) {
+}
+
+// -----------------------------------------------------------------------------
+// RepeatedField Handlers
+// -----------------------------------------------------------------------------
+
+static void repeated_field_write_dimension(zval *object, zval *offset,
+ zval *value TSRMLS_DC) {
+ uint64_t index;
+
+ RepeatedField *intern = zend_object_store_get_object(object TSRMLS_CC);
+ HashTable *ht = HASH_OF(intern->array);
+ int size = native_slot_size(intern->type);
+
+ unsigned char memory[NATIVE_SLOT_MAX_SIZE];
+ memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
+
+ if (!native_slot_set(intern->type, intern->msg_ce, memory, value)) {
+ return;
+ }
+
+ if (!offset || Z_TYPE_P(offset) == IS_NULL) {
+ index = zend_hash_num_elements(HASH_OF(intern->array));
+ } else {
+ if (protobuf_convert_to_uint64(offset, &index)) {
+ if (!zend_hash_index_exists(ht, index)) {
+ zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index);
+ return;
+ }
+ } else {
+ return;
+ }
+ }
+
+ zend_hash_index_update(ht, index, memory, size, NULL);
+}
+
+static HashTable *repeated_field_get_gc(zval *object, zval ***table,
+ int *n TSRMLS_DC) {
+ *table = NULL;
+ *n = 0;
+ RepeatedField *intern = zend_object_store_get_object(object TSRMLS_CC);
+ return HASH_OF(intern->array);
+}
+
+// -----------------------------------------------------------------------------
+// C RepeatedField Utilities
+// -----------------------------------------------------------------------------
+
+void *repeated_field_index_native(RepeatedField *intern, int index) {
+ HashTable *ht = HASH_OF(intern->array);
+ void *value;
+
+ if (zend_hash_index_find(ht, index, (void **)&value) == FAILURE) {
+ zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index);
+ return NULL;
+ }
+
+ return value;
+}
+
+void repeated_field_push_native(RepeatedField *intern, void *value TSRMLS_DC) {
+ HashTable *ht = HASH_OF(intern->array);
+ int size = native_slot_size(intern->type);
+ zend_hash_next_index_insert(ht, (void **)value, size, NULL);
+}
+
+void repeated_field_create_with_type(zend_class_entry *ce,
+ const upb_fielddef *field,
+ zval **repeated_field TSRMLS_DC) {
+ MAKE_STD_ZVAL(*repeated_field);
+ Z_TYPE_PP(repeated_field) = IS_OBJECT;
+ Z_OBJVAL_PP(repeated_field) =
+ repeated_field_type->create_object(repeated_field_type TSRMLS_CC);
+
+ RepeatedField *intern =
+ zend_object_store_get_object(*repeated_field TSRMLS_CC);
+ intern->type = upb_fielddef_type(field);
+ if (intern->type == UPB_TYPE_MESSAGE) {
+ upb_msgdef *msg = upb_fielddef_msgsubdef(field);
+ zval *desc_php = get_def_obj(msg);
+ Descriptor *desc = zend_object_store_get_object(desc_php TSRMLS_CC);
+ intern->msg_ce = desc->klass;
+ }
+ MAKE_STD_ZVAL(intern->array);
+ repeated_field_array_init(intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
+
+ // TODO(teboring): Link class entry for message and enum
+}
+
+
+// -----------------------------------------------------------------------------
+// PHP RepeatedField Methods
+// -----------------------------------------------------------------------------
+
+/**
+ * Constructs an instance of RepeatedField.
+ * @param long Type of the stored element.
+ * @param string Message/Enum class name (message/enum fields only).
+ */
+PHP_METHOD(RepeatedField, __construct) {
+ long type;
+ zend_class_entry* klass = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|C", &type, &klass) ==
+ FAILURE) {
+ return;
+ }
+
+ RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
+ intern->type = to_fieldtype(type);
+ intern->msg_ce = klass;
+
+ MAKE_STD_ZVAL(intern->array);
+ repeated_field_array_init(intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
+
+ if (intern->type == UPB_TYPE_MESSAGE && klass == NULL) {
+ zend_error(E_USER_ERROR, "Message type must have concrete class.");
+ return;
+ }
+
+ // TODO(teboring): Consider enum.
+}
+
+/**
+ * Append element to the end of the repeated field.
+ * @param object The element to be added.
+ */
+PHP_METHOD(RepeatedField, append) {
+ zval *value;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) ==
+ FAILURE) {
+ return;
+ }
+ repeated_field_write_dimension(getThis(), NULL, value TSRMLS_CC);
+}
+
+/**
+ * Check whether the element at given index exists.
+ * @param long The index to be checked.
+ * @return bool True if the element at the given index exists.
+ */
+PHP_METHOD(RepeatedField, offsetExists) {
+ long index;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
+ FAILURE) {
+ return;
+ }
+
+ RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ RETURN_BOOL(index >= 0 &&
+ index < zend_hash_num_elements(HASH_OF(intern->array)));
+}
+
+/**
+ * Return the element at the given index.
+ * This will also be called for: $ele = $arr[0]
+ * @param long The index of the element to be fetched.
+ * @return object The stored element at given index.
+ * @exception Invalid type for index.
+ * @exception Non-existing index.
+ */
+PHP_METHOD(RepeatedField, offsetGet) {
+ long index;
+ void *memory;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
+ FAILURE) {
+ return;
+ }
+
+ RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
+ HashTable *table = HASH_OF(intern->array);
+
+ if (zend_hash_index_find(table, index, (void **)&memory) == FAILURE) {
+ zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index);
+ return;
+ }
+
+ native_slot_get(intern->type, memory, return_value_ptr TSRMLS_CC);
+}
+
+/**
+ * Assign the element at the given index.
+ * This will also be called for: $arr []= $ele and $arr[0] = ele
+ * @param long The index of the element to be assigned.
+ * @param object The element to be assigned.
+ * @exception Invalid type for index.
+ * @exception Non-existing index.
+ * @exception Incorrect type of the element.
+ */
+PHP_METHOD(RepeatedField, offsetSet) {
+ zval *index, *value;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &index, &value) ==
+ FAILURE) {
+ return;
+ }
+ repeated_field_write_dimension(getThis(), index, value TSRMLS_CC);
+}
+
+/**
+ * Remove the element at the given index.
+ * This will also be called for: unset($arr)
+ * @param long The index of the element to be removed.
+ * @exception Invalid type for index.
+ * @exception The element to be removed is not at the end of the RepeatedField.
+ */
+PHP_METHOD(RepeatedField, offsetUnset) {
+ long index;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
+ FAILURE) {
+ return;
+ }
+
+ RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ // Only the element at the end of the array can be removed.
+ if (index == -1 ||
+ index != (zend_hash_num_elements(HASH_OF(intern->array)) - 1)) {
+ zend_error(E_USER_ERROR, "Cannot remove element at %d.\n", index);
+ return;
+ }
+
+ zend_hash_index_del(HASH_OF(intern->array), index);
+}
+
+/**
+ * Return the number of stored elements.
+ * This will also be called for: count($arr)
+ * @return long The number of stored elements.
+ */
+PHP_METHOD(RepeatedField, count) {
+ RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ RETURN_LONG(zend_hash_num_elements(HASH_OF(intern->array)));
+}
diff --git a/php/ext/google/protobuf/config.m4 b/php/ext/google/protobuf/config.m4
index b5946f74..ab032e46 100644
--- a/php/ext/google/protobuf/config.m4
+++ b/php/ext/google/protobuf/config.m4
@@ -1,10 +1,10 @@
-dnl lines starting with "dnl" are comments
-
PHP_ARG_ENABLE(protobuf, whether to enable Protobuf extension, [ --enable-protobuf Enable Protobuf extension])
if test "$PHP_PROTOBUF" != "no"; then
- dnl this defines the extension
- PHP_NEW_EXTENSION(protobuf, upb.c protobuf.c def.c message.c storage.c, $ext_shared)
+ PHP_NEW_EXTENSION(
+ protobuf,
+ array.c def.c encode_decode.c map.c message.c protobuf.c storage.c type_check.c upb.c utf8.c,
+ $ext_shared)
fi
diff --git a/php/ext/google/protobuf/def.c b/php/ext/google/protobuf/def.c
index fc188069..cbd0ec62 100644
--- a/php/ext/google/protobuf/def.c
+++ b/php/ext/google/protobuf/def.c
@@ -1,115 +1,213 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
#include "protobuf.h"
+// Forward declare.
+static zend_object_value descriptor_create(zend_class_entry *ce TSRMLS_DC);
+static void descriptor_init_c_instance(Descriptor* intern TSRMLS_DC);
+static void descriptor_free_c(Descriptor* object TSRMLS_DC);
+static void descriptor_free(void* object TSRMLS_DC);
+
+static zend_object_value enum_descriptor_create(zend_class_entry *ce TSRMLS_DC);
+static void enum_descriptor_init_c_instance(EnumDescriptor* intern TSRMLS_DC);
+static void enum_descriptor_free_c(EnumDescriptor* object TSRMLS_DC);
+static void enum_descriptor_free(void* object TSRMLS_DC);
+
+static zend_object_value descriptor_pool_create(zend_class_entry *ce TSRMLS_DC);
+static void descriptor_pool_free_c(DescriptorPool* object TSRMLS_DC);
+static void descriptor_pool_free(void* object TSRMLS_DC);
+static void descriptor_pool_init_c_instance(DescriptorPool* pool TSRMLS_DC);
+
// -----------------------------------------------------------------------------
// Common Utilities
// -----------------------------------------------------------------------------
-void check_upb_status(const upb_status* status, const char* msg) {
+static void check_upb_status(const upb_status* status, const char* msg) {
if (!upb_ok(status)) {
- zend_error("%s: %s\n", msg, upb_status_errmsg(status));
+ zend_error(E_ERROR, "%s: %s\n", msg, upb_status_errmsg(status));
}
}
+static void upb_filedef_free(void *r) {
+ upb_filedef *f = *(upb_filedef **)r;
+ size_t i;
-static upb_def *check_notfrozen(const upb_def *def) {
- if (upb_def_isfrozen(def)) {
- zend_error(E_ERROR,
- "Attempt to modify a frozen descriptor. Once descriptors are "
- "added to the descriptor pool, they may not be modified.");
+ for (i = 0; i < upb_filedef_depcount(f); i++) {
+ upb_filedef_unref(upb_filedef_dep(f, i), f);
}
- return (upb_def *)def;
-}
-static upb_msgdef *check_msgdef_notfrozen(const upb_msgdef *def) {
- return upb_downcast_msgdef_mutable(check_notfrozen((const upb_def *)def));
+ upb_inttable_uninit(&f->defs);
+ upb_inttable_uninit(&f->deps);
+ upb_gfree((void *)f->name);
+ upb_gfree((void *)f->package);
+ upb_gfree(f);
}
-static upb_fielddef *check_fielddef_notfrozen(const upb_fielddef *def) {
- return upb_downcast_fielddef_mutable(check_notfrozen((const upb_def *)def));
+// Camel-case the field name and append "Entry" for generated map entry name.
+// e.g. map<KeyType, ValueType> foo_map => FooMapEntry
+static void append_map_entry_name(char *result, const char *field_name,
+ int pos) {
+ bool cap_next = true;
+ int i;
+
+ for (i = 0; i < strlen(field_name); ++i) {
+ if (field_name[i] == '_') {
+ cap_next = true;
+ } else if (cap_next) {
+ // Note: Do not use ctype.h due to locales.
+ if ('a' <= field_name[i] && field_name[i] <= 'z') {
+ result[pos++] = field_name[i] - 'a' + 'A';
+ } else {
+ result[pos++] = field_name[i];
+ }
+ cap_next = false;
+ } else {
+ result[pos++] = field_name[i];
+ }
+ }
+ strcat(result, "Entry");
}
-#define PROTOBUF_WRAP_INTERN(wrapper, intern, intern_dtor) \
- Z_TYPE_P(wrapper) = IS_OBJECT; \
- Z_OBJVAL_P(wrapper) \
- .handle = zend_objects_store_put( \
- intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, \
- intern_dtor, NULL TSRMLS_CC); \
- Z_OBJVAL_P(wrapper).handlers = zend_get_std_object_handlers();
-
-#define PROTOBUF_SETUP_ZEND_WRAPPER(class_name, class_name_lower, wrapper, \
- intern) \
- Z_TYPE_P(wrapper) = IS_OBJECT; \
- class_name *intern = ALLOC(class_name); \
- memset(intern, 0, sizeof(class_name)); \
- class_name_lower##_init_c_instance(intern TSRMLS_CC); \
- Z_OBJVAL_P(wrapper) \
- .handle = zend_objects_store_put(intern, NULL, class_name_lower##_free, \
- NULL TSRMLS_CC); \
- Z_OBJVAL_P(wrapper).handlers = zend_get_std_object_handlers();
-
-#define PROTOBUF_CREATE_ZEND_WRAPPER(class_name, class_name_lower, wrapper, \
- intern) \
- MAKE_STD_ZVAL(wrapper); \
- PROTOBUF_SETUP_ZEND_WRAPPER(class_name, class_name_lower, wrapper, intern);
-
-#define DEFINE_CLASS(name, name_lower, string_name) \
- zend_class_entry *name_lower##_type; \
+#define CHECK_UPB(code, msg) \
+ do { \
+ upb_status status = UPB_STATUS_INIT; \
+ code; \
+ check_upb_status(&status, msg); \
+ } while (0)
+
+// Define PHP class
+#define DEFINE_PROTOBUF_INIT_CLASS(name_lower, string_name) \
void name_lower##_init(TSRMLS_D) { \
zend_class_entry class_type; \
INIT_CLASS_ENTRY(class_type, string_name, name_lower##_methods); \
name_lower##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
name_lower##_type->create_object = name_lower##_create; \
- } \
- name *php_to_##name_lower(zval *val TSRMLS_DC) { \
- return (name *)zend_object_store_get_object(val TSRMLS_CC); \
- } \
- void name_lower##_free(void *object TSRMLS_DC) { \
- name *intern = (name *)object; \
- name_lower##_free_c(intern TSRMLS_CC); \
- efree(object); \
- } \
- zend_object_value name_lower##_create(zend_class_entry *ce TSRMLS_DC) { \
- zend_object_value return_value; \
- name *intern = (name *)emalloc(sizeof(name)); \
- memset(intern, 0, sizeof(name)); \
- name_lower##_init_c_instance(intern TSRMLS_CC); \
- return_value.handle = zend_objects_store_put( \
- intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, \
- name_lower##_free, NULL TSRMLS_CC); \
- return_value.handlers = zend_get_std_object_handlers(); \
- return return_value; \
}
+#define DEFINE_PROTOBUF_CREATE(name, name_lower) \
+ static zend_object_value name_lower##_create( \
+ zend_class_entry* ce TSRMLS_DC) { \
+ zend_object_value return_value; \
+ name* intern = (name*)emalloc(sizeof(name)); \
+ memset(intern, 0, sizeof(name)); \
+ name_lower##_init_c_instance(intern TSRMLS_CC); \
+ return_value.handle = zend_objects_store_put( \
+ intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, \
+ name_lower##_free, NULL TSRMLS_CC); \
+ return_value.handlers = zend_get_std_object_handlers(); \
+ return return_value; \
+ }
+
+#define DEFINE_PROTOBUF_FREE(name, name_lower) \
+ static void name_lower##_free(void* object TSRMLS_DC) { \
+ name* intern = (name*)object; \
+ name_lower##_free_c(intern TSRMLS_CC); \
+ efree(object); \
+ }
+
+#define DEFINE_CLASS(name, name_lower, string_name) \
+ zend_class_entry* name_lower##_type; \
+ DEFINE_PROTOBUF_FREE(name, name_lower) \
+ DEFINE_PROTOBUF_CREATE(name, name_lower) \
+ DEFINE_PROTOBUF_INIT_CLASS(name_lower, string_name)
+
+// -----------------------------------------------------------------------------
+// GPBType
+// -----------------------------------------------------------------------------
+
+zend_class_entry* gpb_type_type;
+
+static zend_function_entry gpb_type_methods[] = {
+ ZEND_FE_END
+};
+
+void gpb_type_init(TSRMLS_D) {
+ zend_class_entry class_type;
+ INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBType",
+ gpb_type_methods);
+ gpb_type_type = zend_register_internal_class(&class_type TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("DOUBLE"), 1 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("FLOAT"), 2 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("INT64"), 3 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("UINT64"), 4 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("INT32"), 5 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("FIXED64"), 6 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("FIXED32"), 7 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("BOOL"), 8 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("STRING"), 9 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("GROUP"), 10 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("MESSAGE"), 11 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("BYTES"), 12 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("UINT32"), 13 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("ENUM"), 14 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("SFIXED32"),
+ 15 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("SFIXED64"),
+ 16 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("SINT32"), 17 TSRMLS_CC);
+ zend_declare_class_constant_long(gpb_type_type, STR("SINT64"), 18 TSRMLS_CC);
+}
+
// -----------------------------------------------------------------------------
// DescriptorPool
// -----------------------------------------------------------------------------
static zend_function_entry descriptor_pool_methods[] = {
- PHP_ME(DescriptorPool, addMessage, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(DescriptorPool, finalize, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(DescriptorPool, getGeneratedPool, NULL,
+ ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ PHP_ME(DescriptorPool, internalAddGeneratedFile, NULL, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
DEFINE_CLASS(DescriptorPool, descriptor_pool,
- "Google\\Protobuf\\DescriptorPool");
+ "Google\\Protobuf\\Internal\\DescriptorPool");
+zval* generated_pool_php; // wrapper of generated pool
DescriptorPool *generated_pool; // The actual generated pool
-ZEND_FUNCTION(get_generated_pool) {
- if (PROTOBUF_G(generated_pool) == NULL) {
- MAKE_STD_ZVAL(PROTOBUF_G(generated_pool));
- Z_TYPE_P(PROTOBUF_G(generated_pool)) = IS_OBJECT;
+static void init_generated_pool_once(TSRMLS_D) {
+ if (generated_pool_php == NULL) {
+ MAKE_STD_ZVAL(generated_pool_php);
+ Z_TYPE_P(generated_pool_php) = IS_OBJECT;
generated_pool = ALLOC(DescriptorPool);
descriptor_pool_init_c_instance(generated_pool TSRMLS_CC);
- Z_OBJ_HANDLE_P(PROTOBUF_G(generated_pool)) = zend_objects_store_put(
+ Z_OBJ_HANDLE_P(generated_pool_php) = zend_objects_store_put(
generated_pool, NULL,
- (zend_objects_free_object_storage_t)descriptor_pool_free, NULL TSRMLS_CC);
- Z_OBJ_HT_P(PROTOBUF_G(generated_pool)) = zend_get_std_object_handlers();
+ (zend_objects_free_object_storage_t)descriptor_pool_free,
+ NULL TSRMLS_CC);
+ Z_OBJ_HT_P(generated_pool_php) = zend_get_std_object_handlers();
}
- RETURN_ZVAL(PROTOBUF_G(generated_pool), 1, 0);
}
-void descriptor_pool_init_c_instance(DescriptorPool* pool TSRMLS_DC) {
+static void descriptor_pool_init_c_instance(DescriptorPool *pool TSRMLS_DC) {
zend_object_std_init(&pool->std, descriptor_pool_type TSRMLS_CC);
pool->symtab = upb_symtab_new(&pool->symtab);
@@ -117,31 +215,21 @@ void descriptor_pool_init_c_instance(DescriptorPool* pool TSRMLS_DC) {
zend_hash_init(pool->pending_list, 1, NULL, ZVAL_PTR_DTOR, 0);
}
-void descriptor_pool_free_c(DescriptorPool *pool TSRMLS_DC) {
+static void descriptor_pool_free_c(DescriptorPool *pool TSRMLS_DC) {
upb_symtab_unref(pool->symtab, &pool->symtab);
+
zend_hash_destroy(pool->pending_list);
FREE_HASHTABLE(pool->pending_list);
}
-PHP_METHOD(DescriptorPool, addMessage) {
- char *name = NULL;
- int str_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &str_len) ==
- FAILURE) {
- return;
+static void validate_enumdef(const upb_enumdef *enumdef) {
+ // Verify that an entry exists with integer value 0. (This is the default
+ // value.)
+ const char *lookup = upb_enumdef_iton(enumdef, 0);
+ if (lookup == NULL) {
+ zend_error(E_USER_ERROR,
+ "Enum definition does not contain a value for '0'.");
}
-
- zval* retval = NULL;
- PROTOBUF_CREATE_ZEND_WRAPPER(MessageBuilderContext, message_builder_context,
- retval, context);
-
- MAKE_STD_ZVAL(context->pool);
- ZVAL_ZVAL(context->pool, getThis(), 1, 0);
-
- Descriptor *desc = php_to_descriptor(context->descriptor TSRMLS_CC);
- Descriptor_name_set(desc, name);
-
- RETURN_ZVAL(retval, 0, 1);
}
static void validate_msgdef(const upb_msgdef* msgdef) {
@@ -157,35 +245,123 @@ static void validate_msgdef(const upb_msgdef* msgdef) {
}
}
-PHP_METHOD(DescriptorPool, finalize) {
- DescriptorPool *self = php_to_descriptor_pool(getThis() TSRMLS_CC);
- Bucket *temp;
- int i, num;
+PHP_METHOD(DescriptorPool, getGeneratedPool) {
+ init_generated_pool_once(TSRMLS_C);
+ RETURN_ZVAL(generated_pool_php, 1, 0);
+}
+
+static void convert_to_class_name_inplace(char *proto_name,
+ size_t pkg_name_len) {
+ size_t i;
+ bool first_char = false;
- num = zend_hash_num_elements(self->pending_list);
- upb_def **defs = emalloc(sizeof(upb_def *) * num);
+ for (i = 0; i <= pkg_name_len + 1; i++) {
+ // PHP package uses camel case.
+ if (!first_char && proto_name[i] != '.') {
+ first_char = true;
+ proto_name[i] += 'A' - 'a';
+ }
+ // php packages are divided by '\'.
+ if (proto_name[i] == '.') {
+ first_char = false;
+ proto_name[i] = '\\';
+ }
+ }
+
+ // Submessage is concatenated with its containing messages by '_'.
+ for (i = pkg_name_len; i < strlen(proto_name); i++) {
+ if (proto_name[i] == '.') {
+ proto_name[i] = '_';
+ }
+ }
+}
+
+PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {
+ char *data = NULL;
+ int data_len;
+ upb_filedef **files;
+ size_t i;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) ==
+ FAILURE) {
+ return;
+ }
- for (i = 0, temp = self->pending_list->pListHead; temp != NULL;
- temp = temp->pListNext) {
- zval *def_php = *(zval **)temp->pData;
- Descriptor* desc = php_to_descriptor(def_php TSRMLS_CC);
- defs[i] = (upb_def *)desc->msgdef;
- validate_msgdef((const upb_msgdef *)defs[i++]);
+ DescriptorPool *pool = UNBOX(DescriptorPool, getThis());
+ CHECK_UPB(files = upb_loaddescriptor(data, data_len, &pool, &status),
+ "Parse binary descriptors to internal descriptors failed");
+
+ // This method is called only once in each file.
+ assert(files[0] != NULL);
+ assert(files[1] == NULL);
+
+ CHECK_UPB(upb_symtab_addfile(pool->symtab, files[0], &status),
+ "Unable to add file to DescriptorPool");
+
+ // For each enum/message, we need its PHP class, upb descriptor and its PHP
+ // wrapper. These information are needed later for encoding, decoding and type
+ // checking. However, sometimes we just have one of them. In order to find
+ // them quickly, here, we store the mapping for them.
+ for (i = 0; i < upb_filedef_defcount(files[0]); i++) {
+ const upb_def *def = upb_filedef_def(files[0], i);
+ switch (upb_def_type(def)) {
+#define CASE_TYPE(def_type, def_type_lower, desc_type, desc_type_lower) \
+ case UPB_DEF_##def_type: { \
+ desc_type *desc; \
+ zval *desc_php; \
+ CREATE(desc_type, desc, desc_type_lower##_init_c_instance); \
+ BOX(desc_type, desc_php, desc, desc_type_lower##_free); \
+ Z_DELREF_P(desc_php); \
+ const upb_##def_type_lower *def_type_lower = \
+ upb_downcast_##def_type_lower(def); \
+ desc->def_type_lower = def_type_lower; \
+ add_def_obj(desc->def_type_lower, desc_php); \
+ /* Unlike other messages, MapEntry is shared by all map fields and doesn't \
+ * have generated PHP class.*/ \
+ if (upb_def_type(def) == UPB_DEF_MSG && upb_msgdef_mapentry(def)) { \
+ break; \
+ } \
+ /* Prepend '.' to package name to make it absolute. */ \
+ const char *fullname = upb_##def_type_lower##_fullname(def_type_lower); \
+ char *klass_name = ecalloc(sizeof(char), 2 + strlen(fullname)); \
+ klass_name[0] = '.'; \
+ strcpy(&klass_name[1], fullname); \
+ size_t pkg_name_len = strlen(upb_filedef_package(files[0])); \
+ convert_to_class_name_inplace(klass_name, pkg_name_len); \
+ zend_class_entry **pce; \
+ if (zend_lookup_class(klass_name, strlen(klass_name), &pce TSRMLS_CC) == \
+ FAILURE) { \
+ zend_error(E_ERROR, "Generated message class %s hasn't been defined", \
+ klass_name); \
+ return; \
+ } else { \
+ desc->klass = *pce; \
+ } \
+ add_ce_obj(desc->klass, desc_php); \
+ efree(klass_name); \
+ break; \
}
- CHECK_UPB(upb_symtab_add(self->symtab, (upb_def **)defs, num, NULL, &status),
- "Unable to add defs to DescriptorPool");
+ CASE_TYPE(MSG, msgdef, Descriptor, descriptor)
+ CASE_TYPE(ENUM, enumdef, EnumDescriptor, enum_descriptor)
+#undef CASE_TYPE
- for (temp = self->pending_list->pListHead; temp != NULL;
- temp = temp->pListNext) {
- // zval *def_php = *(zval **)temp->pData;
- // Descriptor* desc = php_to_descriptor(def_php TSRMLS_CC);
- build_class_from_descriptor((zval *)temp->pDataPtr TSRMLS_CC);
+ default:
+ break;
+ }
+ }
+
+ for (i = 0; i < upb_filedef_defcount(files[0]); i++) {
+ const upb_def *def = upb_filedef_def(files[0], i);
+ if (upb_def_type(def) == UPB_DEF_MSG) {
+ const upb_msgdef *msgdef = upb_downcast_msgdef(def);
+ zval *desc_php = get_def_obj(msgdef);
+ build_class_from_descriptor(desc_php TSRMLS_CC);
+ }
}
- FREE(defs);
- zend_hash_destroy(self->pending_list);
- zend_hash_init(self->pending_list, 1, NULL, ZVAL_PTR_DTOR, 0);
+ upb_filedef_unref(files[0], &pool);
+ upb_gfree(files);
}
// -----------------------------------------------------------------------------
@@ -196,186 +372,87 @@ static zend_function_entry descriptor_methods[] = {
ZEND_FE_END
};
-DEFINE_CLASS(Descriptor, descriptor, "Google\\Protobuf\\Descriptor");
+DEFINE_CLASS(Descriptor, descriptor, "Google\\Protobuf\\Internal\\Descriptor");
-void descriptor_free_c(Descriptor *self TSRMLS_DC) {
- upb_msg_field_iter iter;
- upb_msg_field_begin(&iter, self->msgdef);
- while (!upb_msg_field_done(&iter)) {
- upb_fielddef *fielddef = upb_msg_iter_field(&iter);
- upb_fielddef_unref(fielddef, &fielddef);
- upb_msg_field_next(&iter);
- }
- upb_msgdef_unref(self->msgdef, &self->msgdef);
+static void descriptor_free_c(Descriptor *self TSRMLS_DC) {
if (self->layout) {
free_layout(self->layout);
}
+ if (self->fill_handlers) {
+ upb_handlers_unref(self->fill_handlers, &self->fill_handlers);
+ }
+ if (self->fill_method) {
+ upb_pbdecodermethod_unref(self->fill_method, &self->fill_method);
+ }
+ if (self->pb_serialize_handlers) {
+ upb_handlers_unref(self->pb_serialize_handlers,
+ &self->pb_serialize_handlers);
+ }
}
-static void descriptor_add_field(Descriptor *desc,
- const upb_fielddef *fielddef) {
- upb_msgdef *mut_def = check_msgdef_notfrozen(desc->msgdef);
- upb_fielddef *mut_field_def = check_fielddef_notfrozen(fielddef);
- CHECK_UPB(upb_msgdef_addfield(mut_def, mut_field_def, NULL, &status),
- "Adding field to Descriptor failed");
- // add_def_obj(fielddef, obj);
-}
-
-void descriptor_init_c_instance(Descriptor* desc TSRMLS_DC) {
+static void descriptor_init_c_instance(Descriptor *desc TSRMLS_DC) {
zend_object_std_init(&desc->std, descriptor_type TSRMLS_CC);
- desc->msgdef = upb_msgdef_new(&desc->msgdef);
+ desc->msgdef = NULL;
desc->layout = NULL;
- // MAKE_STD_ZVAL(intern->klass);
- // ZVAL_NULL(intern->klass);
+ desc->klass = NULL;
+ desc->fill_handlers = NULL;
+ desc->fill_method = NULL;
desc->pb_serialize_handlers = NULL;
}
-void Descriptor_name_set(Descriptor *desc, const char *name) {
- upb_msgdef *mut_def = check_msgdef_notfrozen(desc->msgdef);
- CHECK_UPB(upb_msgdef_setfullname(mut_def, name, &status),
- "Error setting Descriptor name");
-}
-
// -----------------------------------------------------------------------------
-// FieldDescriptor
+// EnumDescriptor
// -----------------------------------------------------------------------------
-static void field_descriptor_name_set(const upb_fielddef* fielddef,
- const char *name) {
- upb_fielddef *mut_def = check_fielddef_notfrozen(fielddef);
- CHECK_UPB(upb_fielddef_setname(mut_def, name, &status),
- "Error setting FieldDescriptor name");
-}
-
-static void field_descriptor_label_set(const upb_fielddef* fielddef,
- upb_label_t upb_label) {
- upb_fielddef *mut_def = check_fielddef_notfrozen(fielddef);
- upb_fielddef_setlabel(mut_def, upb_label);
-}
-
-upb_fieldtype_t string_to_descriptortype(const char *type) {
-#define CONVERT(upb, str) \
- if (!strcmp(type, str)) { \
- return UPB_DESCRIPTOR_TYPE_##upb; \
- }
-
- CONVERT(FLOAT, "float");
- CONVERT(DOUBLE, "double");
- CONVERT(BOOL, "bool");
- CONVERT(STRING, "string");
- CONVERT(BYTES, "bytes");
- CONVERT(MESSAGE, "message");
- CONVERT(GROUP, "group");
- CONVERT(ENUM, "enum");
- CONVERT(INT32, "int32");
- CONVERT(INT64, "int64");
- CONVERT(UINT32, "uint32");
- CONVERT(UINT64, "uint64");
- CONVERT(SINT32, "sint32");
- CONVERT(SINT64, "sint64");
- CONVERT(FIXED32, "fixed32");
- CONVERT(FIXED64, "fixed64");
- CONVERT(SFIXED32, "sfixed32");
- CONVERT(SFIXED64, "sfixed64");
-
-#undef CONVERT
+static zend_function_entry enum_descriptor_methods[] = {
+ ZEND_FE_END
+};
- zend_error(E_ERROR, "Unknown field type.");
- return 0;
-}
+DEFINE_CLASS(EnumDescriptor, enum_descriptor,
+ "Google\\Protobuf\\Internal\\EnumDescriptor");
-static void field_descriptor_type_set(const upb_fielddef* fielddef,
- const char *type) {
- upb_fielddef *mut_def = check_fielddef_notfrozen(fielddef);
- upb_fielddef_setdescriptortype(mut_def, string_to_descriptortype(type));
+static void enum_descriptor_free_c(EnumDescriptor *self TSRMLS_DC) {
}
-static void field_descriptor_number_set(const upb_fielddef* fielddef,
- int number) {
- upb_fielddef *mut_def = check_fielddef_notfrozen(fielddef);
- CHECK_UPB(upb_fielddef_setnumber(mut_def, number, &status),
- "Error setting field number");
+static void enum_descriptor_init_c_instance(EnumDescriptor *self TSRMLS_DC) {
+ zend_object_std_init(&self->std, enum_descriptor_type TSRMLS_CC);
+ self->enumdef = NULL;
+ self->klass = NULL;
}
// -----------------------------------------------------------------------------
-// MessageBuilderContext
+// FieldDescriptor
// -----------------------------------------------------------------------------
-static zend_function_entry message_builder_context_methods[] = {
- PHP_ME(MessageBuilderContext, finalizeToPool, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(MessageBuilderContext, optional, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-DEFINE_CLASS(MessageBuilderContext, message_builder_context,
- "Google\\Protobuf\\Internal\\MessageBuilderContext");
-
-void message_builder_context_free_c(MessageBuilderContext *context TSRMLS_DC) {
- zval_ptr_dtor(&context->descriptor);
- zval_ptr_dtor(&context->pool);
-}
-
-void message_builder_context_init_c_instance(
- MessageBuilderContext *context TSRMLS_DC) {
- zend_object_std_init(&context->std, message_builder_context_type TSRMLS_CC);
- PROTOBUF_CREATE_ZEND_WRAPPER(Descriptor, descriptor, context->descriptor,
- desc);
-}
+upb_fieldtype_t to_fieldtype(upb_descriptortype_t type) {
+ switch (type) {
+#define CASE(descriptor_type, type) \
+ case UPB_DESCRIPTOR_TYPE_##descriptor_type: \
+ return UPB_TYPE_##type;
+
+ CASE(FLOAT, FLOAT);
+ CASE(DOUBLE, DOUBLE);
+ CASE(BOOL, BOOL);
+ CASE(STRING, STRING);
+ CASE(BYTES, BYTES);
+ CASE(MESSAGE, MESSAGE);
+ CASE(GROUP, MESSAGE);
+ CASE(ENUM, ENUM);
+ CASE(INT32, INT32);
+ CASE(INT64, INT64);
+ CASE(UINT32, UINT32);
+ CASE(UINT64, UINT64);
+ CASE(SINT32, INT32);
+ CASE(SINT64, INT64);
+ CASE(FIXED32, UINT32);
+ CASE(FIXED64, UINT64);
+ CASE(SFIXED32, INT32);
+ CASE(SFIXED64, INT64);
-static void msgdef_add_field(Descriptor *desc, upb_label_t upb_label,
- const char *name, const char *type, int number,
- const char *type_class) {
- upb_fielddef *fielddef = upb_fielddef_new(&fielddef);
- upb_fielddef_setpacked(fielddef, false);
-
- field_descriptor_label_set(fielddef, upb_label);
- field_descriptor_name_set(fielddef, name);
- field_descriptor_type_set(fielddef, type);
- field_descriptor_number_set(fielddef, number);
-
-// // if (type_class != Qnil) {
-// // if (TYPE(type_class) != T_STRING) {
-// // rb_raise(rb_eArgError, "Expected string for type class");
-// // }
-// // // Make it an absolute type name by prepending a dot.
-// // type_class = rb_str_append(rb_str_new2("."), type_class);
-// // rb_funcall(fielddef, rb_intern("submsg_name="), 1, type_class);
-// // }
- descriptor_add_field(desc, fielddef);
-}
+#undef CONVERT
-PHP_METHOD(MessageBuilderContext, optional) {
- MessageBuilderContext *self = php_to_message_builder_context(getThis() TSRMLS_CC);
- Descriptor *desc = php_to_descriptor(self->descriptor TSRMLS_CC);
- // VALUE name, type, number, type_class;
- const char *name, *type, *type_class;
- int number, name_str_len, type_str_len, type_class_str_len;
- if (ZEND_NUM_ARGS() == 3) {
- if (zend_parse_parameters(3 TSRMLS_CC, "ssl", &name,
- &name_str_len, &type, &type_str_len, &number) == FAILURE) {
- return;
- }
- } else {
- if (zend_parse_parameters(4 TSRMLS_CC, "ssls", &name,
- &name_str_len, &type, &type_str_len, &number, &type_class,
- &type_class_str_len) == FAILURE) {
- return;
- }
}
- msgdef_add_field(desc, UPB_LABEL_OPTIONAL, name, type, number, type_class);
-
- zval_copy_ctor(getThis());
- RETURN_ZVAL(getThis(), 1, 0);
-}
-
-PHP_METHOD(MessageBuilderContext, finalizeToPool) {
- MessageBuilderContext *self = php_to_message_builder_context(getThis() TSRMLS_CC);
- DescriptorPool *pool = php_to_descriptor_pool(self->pool TSRMLS_CC);
- Descriptor* desc = php_to_descriptor(self->descriptor TSRMLS_CC);
-
- Z_ADDREF_P(self->descriptor);
- zend_hash_next_index_insert(pool->pending_list, &self->descriptor,
- sizeof(zval *), NULL);
- RETURN_ZVAL(self->pool, 1, 0);
+ zend_error(E_ERROR, "Unknown field type.");
+ return 0;
}
diff --git a/php/ext/google/protobuf/encode_decode.c b/php/ext/google/protobuf/encode_decode.c
new file mode 100644
index 00000000..4b51dabe
--- /dev/null
+++ b/php/ext/google/protobuf/encode_decode.c
@@ -0,0 +1,1245 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "protobuf.h"
+
+/* stringsink *****************************************************************/
+
+typedef struct {
+ upb_byteshandler handler;
+ upb_bytessink sink;
+ char *ptr;
+ size_t len, size;
+} stringsink;
+
+
+static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
+ stringsink *sink = _sink;
+ sink->len = 0;
+ return sink;
+}
+
+static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
+ size_t len, const upb_bufhandle *handle) {
+ stringsink *sink = _sink;
+ size_t new_size = sink->size;
+
+ UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
+
+ while (sink->len + len > new_size) {
+ new_size *= 2;
+ }
+
+ if (new_size != sink->size) {
+ sink->ptr = realloc(sink->ptr, new_size);
+ sink->size = new_size;
+ }
+
+ memcpy(sink->ptr + sink->len, ptr, len);
+ sink->len += len;
+
+ return len;
+}
+
+void stringsink_init(stringsink *sink) {
+ upb_byteshandler_init(&sink->handler);
+ upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
+ upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
+
+ upb_bytessink_reset(&sink->sink, &sink->handler, sink);
+
+ sink->size = 32;
+ sink->ptr = malloc(sink->size);
+ sink->len = 0;
+}
+
+void stringsink_uninit(stringsink *sink) { free(sink->ptr); }
+
+/* stackenv *****************************************************************/
+
+// Stack-allocated context during an encode/decode operation. Contains the upb
+// environment and its stack-based allocator, an initial buffer for allocations
+// to avoid malloc() when possible, and a template for PHP exception messages
+// if any error occurs.
+#define STACK_ENV_STACKBYTES 4096
+typedef struct {
+ upb_env env;
+ const char *php_error_template;
+ char allocbuf[STACK_ENV_STACKBYTES];
+} stackenv;
+
+
+static void stackenv_init(stackenv* se, const char* errmsg);
+static void stackenv_uninit(stackenv* se);
+
+// Callback invoked by upb if any error occurs during parsing or serialization.
+static bool env_error_func(void* ud, const upb_status* status) {
+ stackenv* se = ud;
+ // Free the env -- zend_error will longjmp up the stack past the
+ // encode/decode function so it would not otherwise have been freed.
+ stackenv_uninit(se);
+
+ // TODO(teboring): have a way to verify that this is actually a parse error,
+ // instead of just throwing "parse error" unconditionally.
+ zend_error(E_ERROR, se->php_error_template, upb_status_errmsg(status));
+ // Never reached.
+ return false;
+}
+
+static void stackenv_init(stackenv* se, const char* errmsg) {
+ se->php_error_template = errmsg;
+ upb_env_init2(&se->env, se->allocbuf, sizeof(se->allocbuf), NULL);
+ upb_env_seterrorfunc(&se->env, env_error_func, se);
+}
+
+static void stackenv_uninit(stackenv* se) {
+ upb_env_uninit(&se->env);
+}
+
+// -----------------------------------------------------------------------------
+// Parsing.
+// -----------------------------------------------------------------------------
+
+#define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs)
+
+// Creates a handlerdata that simply contains the offset for this field.
+static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) {
+ size_t* hd_ofs = (size_t*)malloc(sizeof(size_t));
+ *hd_ofs = ofs;
+ upb_handlers_addcleanup(h, hd_ofs, free);
+ return hd_ofs;
+}
+
+typedef struct {
+ size_t ofs;
+ const upb_msgdef *md;
+} submsg_handlerdata_t;
+
+// Creates a handlerdata that contains offset and submessage type information.
+static const void *newsubmsghandlerdata(upb_handlers* h, uint32_t ofs,
+ const upb_fielddef* f) {
+ submsg_handlerdata_t* hd =
+ (submsg_handlerdata_t*)malloc(sizeof(submsg_handlerdata_t));
+ hd->ofs = ofs;
+ hd->md = upb_fielddef_msgsubdef(f);
+ upb_handlers_addcleanup(h, hd, free);
+ return hd;
+}
+
+typedef struct {
+ size_t ofs; // union data slot
+ size_t case_ofs; // oneof_case field
+ int property_ofs; // properties table cache
+ uint32_t oneof_case_num; // oneof-case number to place in oneof_case field
+ const upb_msgdef *md; // msgdef, for oneof submessage handler
+} oneof_handlerdata_t;
+
+static const void *newoneofhandlerdata(upb_handlers *h,
+ uint32_t ofs,
+ uint32_t case_ofs,
+ int property_ofs,
+ const upb_fielddef *f) {
+ oneof_handlerdata_t* hd =
+ (oneof_handlerdata_t*)malloc(sizeof(oneof_handlerdata_t));
+ hd->ofs = ofs;
+ hd->case_ofs = case_ofs;
+ hd->property_ofs = property_ofs;
+ // We reuse the field tag number as a oneof union discriminant tag. Note that
+ // we don't expose these numbers to the user, so the only requirement is that
+ // we have some unique ID for each union case/possibility. The field tag
+ // numbers are already present and are easy to use so there's no reason to
+ // create a separate ID space. In addition, using the field tag number here
+ // lets us easily look up the field in the oneof accessor.
+ hd->oneof_case_num = upb_fielddef_number(f);
+ if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) {
+ hd->md = upb_fielddef_msgsubdef(f);
+ } else {
+ hd->md = NULL;
+ }
+ upb_handlers_addcleanup(h, hd, free);
+ return hd;
+}
+
+// A handler that starts a repeated field. Gets the Repeated*Field instance for
+// this field (such an instance always exists even in an empty message).
+static void *startseq_handler(void* closure, const void* hd) {
+ MessageHeader* msg = closure;
+ const size_t *ofs = hd;
+ return (void*)(*DEREF(msg, *ofs, zval**));
+}
+
+// Handlers that append primitive values to a repeated field.
+#define DEFINE_APPEND_HANDLER(type, ctype) \
+ static bool append##type##_handler(void* closure, const void* hd, \
+ ctype val) { \
+ zval* array = (zval*)closure; \
+ RepeatedField* intern = \
+ (RepeatedField*)zend_object_store_get_object(array TSRMLS_CC); \
+ repeated_field_push_native(intern, &val); \
+ return true; \
+ }
+
+DEFINE_APPEND_HANDLER(bool, bool)
+DEFINE_APPEND_HANDLER(int32, int32_t)
+DEFINE_APPEND_HANDLER(uint32, uint32_t)
+DEFINE_APPEND_HANDLER(float, float)
+DEFINE_APPEND_HANDLER(int64, int64_t)
+DEFINE_APPEND_HANDLER(uint64, uint64_t)
+DEFINE_APPEND_HANDLER(double, double)
+
+// Appends a string to a repeated field.
+static void* appendstr_handler(void *closure,
+ const void *hd,
+ size_t size_hint) {
+ zval* array = (zval*)closure;
+ RepeatedField* intern =
+ (RepeatedField*)zend_object_store_get_object(array TSRMLS_CC);
+
+ zval* str;
+ MAKE_STD_ZVAL(str);
+ ZVAL_STRING(str, "", 1);
+
+ repeated_field_push_native(intern, &str TSRMLS_CC);
+ return (void*)str;
+}
+
+// Appends a 'bytes' string to a repeated field.
+static void* appendbytes_handler(void *closure,
+ const void *hd,
+ size_t size_hint) {
+ zval* array = (zval*)closure;
+ RepeatedField* intern =
+ (RepeatedField*)zend_object_store_get_object(array TSRMLS_CC);
+
+ zval* str;
+ MAKE_STD_ZVAL(str);
+ ZVAL_STRING(str, "", 1);
+
+ repeated_field_push_native(intern, &str TSRMLS_CC);
+ return (void*)str;
+}
+
+static void *empty_php_string(zval** value_ptr) {
+ SEPARATE_ZVAL_IF_NOT_REF(value_ptr);
+ zval* str = *value_ptr;
+ zval_dtor(str);
+ ZVAL_STRINGL(str, "", 0, 1);
+ return (void*)str;
+}
+
+// Sets a non-repeated string field in a message.
+static void* str_handler(void *closure,
+ const void *hd,
+ size_t size_hint) {
+ MessageHeader* msg = closure;
+ const size_t *ofs = hd;
+ return empty_php_string(DEREF(msg, *ofs, zval**));
+}
+
+// Sets a non-repeated 'bytes' field in a message.
+static void* bytes_handler(void *closure,
+ const void *hd,
+ size_t size_hint) {
+ MessageHeader* msg = closure;
+ const size_t *ofs = hd;
+ return empty_php_string(DEREF(msg, *ofs, zval**));
+}
+
+static size_t stringdata_handler(void* closure, const void* hd,
+ const char* str, size_t len,
+ const upb_bufhandle* handle) {
+ zval* php_str = (zval*)closure;
+
+ char* old_str = Z_STRVAL_P(php_str);
+ size_t old_len = Z_STRLEN_P(php_str);
+ assert(old_str != NULL);
+
+ char* new_str = emalloc(old_len + len + 1);
+
+ memcpy(new_str, old_str, old_len);
+ memcpy(new_str + old_len, str, len);
+ new_str[old_len + len] = 0;
+ FREE(old_str);
+
+ Z_STRVAL_P(php_str) = new_str;
+ Z_STRLEN_P(php_str) = old_len + len;
+
+ return len;
+}
+
+// Appends a submessage to a repeated field.
+static void *appendsubmsg_handler(void *closure, const void *hd) {
+ zval* array = (zval*)closure;
+ RepeatedField* intern =
+ (RepeatedField*)zend_object_store_get_object(array TSRMLS_CC);
+
+ const submsg_handlerdata_t *submsgdata = hd;
+ zval* subdesc_php = get_def_obj((void*)submsgdata->md);
+ Descriptor* subdesc = zend_object_store_get_object(subdesc_php TSRMLS_CC);
+ zend_class_entry* subklass = subdesc->klass;
+ MessageHeader* submsg;
+
+ zval* val = NULL;
+ MAKE_STD_ZVAL(val);
+ Z_TYPE_P(val) = IS_OBJECT;
+ Z_OBJVAL_P(val) = subklass->create_object(subklass TSRMLS_CC);
+
+ repeated_field_push_native(intern, &val TSRMLS_CC);
+
+ submsg = zend_object_store_get_object(val TSRMLS_CC);
+ return submsg;
+}
+
+// Sets a non-repeated submessage field in a message.
+static void *submsg_handler(void *closure, const void *hd) {
+ MessageHeader* msg = closure;
+ const submsg_handlerdata_t* submsgdata = hd;
+ zval* subdesc_php = get_def_obj((void*)submsgdata->md);
+ Descriptor* subdesc = zend_object_store_get_object(subdesc_php TSRMLS_CC);
+ zend_class_entry* subklass = subdesc->klass;
+ zval* submsg_php;
+ MessageHeader* submsg;
+
+ if (Z_TYPE_P(*DEREF(msg, submsgdata->ofs, zval**)) == IS_NULL) {
+ zval* val = NULL;
+ MAKE_STD_ZVAL(val);
+ Z_TYPE_P(val) = IS_OBJECT;
+ Z_OBJVAL_P(val) = subklass->create_object(subklass TSRMLS_CC);
+
+ zval_ptr_dtor(DEREF(msg, submsgdata->ofs, zval**));
+ *DEREF(msg, submsgdata->ofs, zval**) = val;
+ }
+
+ submsg_php = *DEREF(msg, submsgdata->ofs, zval**);
+
+ submsg = zend_object_store_get_object(submsg_php TSRMLS_CC);
+ return submsg;
+}
+
+// Handler data for startmap/endmap handlers.
+typedef struct {
+ size_t ofs;
+ upb_fieldtype_t key_field_type;
+ upb_fieldtype_t value_field_type;
+
+ // We know that we can hold this reference because the handlerdata has the
+ // same lifetime as the upb_handlers struct, and the upb_handlers struct holds
+ // a reference to the upb_msgdef, which in turn has references to its subdefs.
+ const upb_def* value_field_subdef;
+} map_handlerdata_t;
+
+// Temporary frame for map parsing: at the beginning of a map entry message, a
+// submsg handler allocates a frame to hold (i) a reference to the Map object
+// into which this message will be inserted and (ii) storage slots to
+// temporarily hold the key and value for this map entry until the end of the
+// submessage. When the submessage ends, another handler is called to insert the
+// value into the map.
+typedef struct {
+ zval* map;
+ char key_storage[NATIVE_SLOT_MAX_SIZE];
+ char value_storage[NATIVE_SLOT_MAX_SIZE];
+} map_parse_frame_t;
+
+static void map_slot_init(void* memory, upb_fieldtype_t type) {
+ switch (type) {
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES: {
+ // Store zval** in memory in order to be consistent with the layout of
+ // singular fields.
+ zval** holder = ALLOC(zval*);
+ zval* tmp;
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_STRINGL(tmp, "", 0, 1);
+ *holder = tmp;
+ *(zval***)memory = holder;
+ break;
+ }
+ case UPB_TYPE_MESSAGE: {
+ zval** holder = ALLOC(zval*);
+ zval* tmp;
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_NULL(tmp);
+ *holder = tmp;
+ *(zval***)memory = holder;
+ break;
+ }
+ default:
+ native_slot_init(type, memory, NULL);
+ }
+}
+
+static void map_slot_uninit(void* memory, upb_fieldtype_t type) {
+ switch (type) {
+ case UPB_TYPE_MESSAGE:
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES: {
+ zval** holder = *(zval***)memory;
+ zval_ptr_dtor(holder);
+ FREE(holder);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static void map_slot_key(upb_fieldtype_t type, const void* from, char** keyval,
+ size_t* length) {
+ if (type == UPB_TYPE_STRING) {
+ zval* key_php = **(zval***)from;
+ *keyval = Z_STRVAL_P(key_php);
+ *length = Z_STRLEN_P(key_php);
+ } else {
+ *keyval = from;
+ *length = native_slot_size(type);
+ }
+}
+
+static void map_slot_value(upb_fieldtype_t type, const void* from, upb_value* v) {
+ size_t len;
+ void* to = upb_value_memory(v);
+#ifndef NDEBUG
+ v->ctype = UPB_CTYPE_UINT64;
+#endif
+
+ memset(to, 0, native_slot_size(type));
+
+ switch (type) {
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_MESSAGE: {
+ *(zval**)to = **(zval***)from;
+ Z_ADDREF_PP((zval**)to);
+ break;
+ }
+ default:
+ len = native_slot_size(type);
+ memcpy(to, from, len);
+ }
+}
+
+// Handler to begin a map entry: allocates a temporary frame. This is the
+// 'startsubmsg' handler on the msgdef that contains the map field.
+static void *startmapentry_handler(void *closure, const void *hd) {
+ MessageHeader* msg = closure;
+ const map_handlerdata_t* mapdata = hd;
+ zval* map = *DEREF(msg, mapdata->ofs, zval**);
+
+ map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
+ frame->map = map;
+
+ map_slot_init(&frame->key_storage, mapdata->key_field_type);
+ map_slot_init(&frame->value_storage, mapdata->value_field_type);
+
+ return frame;
+}
+
+// Handler to end a map entry: inserts the value defined during the message into
+// the map. This is the 'endmsg' handler on the map entry msgdef.
+static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
+ map_parse_frame_t* frame = closure;
+ const map_handlerdata_t* mapdata = hd;
+
+ Map *map = (Map *)zend_object_store_get_object(frame->map TSRMLS_CC);
+
+ const char* keyval = NULL;
+ upb_value v;
+ size_t length;
+
+ map_slot_key(map->key_type, &frame->key_storage, &keyval, &length);
+ map_slot_value(map->value_type, &frame->value_storage, &v);
+
+ map_index_set(map, keyval, length, v);
+
+ map_slot_uninit(&frame->key_storage, mapdata->key_field_type);
+ map_slot_uninit(&frame->value_storage, mapdata->value_field_type);
+ FREE(frame);
+
+ return true;
+}
+
+// Allocates a new map_handlerdata_t given the map entry message definition. If
+// the offset of the field within the parent message is also given, that is
+// added to the handler data as well. Note that this is called *twice* per map
+// field: once in the parent message handler setup when setting the startsubmsg
+// handler and once in the map entry message handler setup when setting the
+// key/value and endmsg handlers. The reason is that there is no easy way to
+// pass the handlerdata down to the sub-message handler setup.
+static map_handlerdata_t* new_map_handlerdata(
+ size_t ofs,
+ const upb_msgdef* mapentry_def,
+ Descriptor* desc) {
+ const upb_fielddef* key_field;
+ const upb_fielddef* value_field;
+ // TODO(teboring): Use emalloc and efree.
+ map_handlerdata_t* hd =
+ (map_handlerdata_t*)malloc(sizeof(map_handlerdata_t));
+
+ hd->ofs = ofs;
+ key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD);
+ assert(key_field != NULL);
+ hd->key_field_type = upb_fielddef_type(key_field);
+ value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD);
+ assert(value_field != NULL);
+ hd->value_field_type = upb_fielddef_type(value_field);
+ hd->value_field_subdef = upb_fielddef_subdef(value_field);
+
+ return hd;
+}
+
+// Handlers that set primitive values in oneofs.
+#define DEFINE_ONEOF_HANDLER(type, ctype) \
+ static bool oneof##type##_handler(void *closure, const void *hd, \
+ ctype val) { \
+ const oneof_handlerdata_t *oneofdata = hd; \
+ DEREF(closure, oneofdata->case_ofs, uint32_t) = \
+ oneofdata->oneof_case_num; \
+ DEREF(closure, oneofdata->ofs, ctype) = val; \
+ return true; \
+ }
+
+DEFINE_ONEOF_HANDLER(bool, bool)
+DEFINE_ONEOF_HANDLER(int32, int32_t)
+DEFINE_ONEOF_HANDLER(uint32, uint32_t)
+DEFINE_ONEOF_HANDLER(float, float)
+DEFINE_ONEOF_HANDLER(int64, int64_t)
+DEFINE_ONEOF_HANDLER(uint64, uint64_t)
+DEFINE_ONEOF_HANDLER(double, double)
+
+#undef DEFINE_ONEOF_HANDLER
+
+// Handlers for strings in a oneof.
+static void *oneofstr_handler(void *closure,
+ const void *hd,
+ size_t size_hint) {
+ MessageHeader* msg = closure;
+ const oneof_handlerdata_t *oneofdata = hd;
+
+ DEREF(msg, oneofdata->case_ofs, uint32_t) =
+ oneofdata->oneof_case_num;
+ DEREF(msg, oneofdata->ofs, zval**) =
+ &(msg->std.properties_table)[oneofdata->property_ofs];
+
+ return empty_php_string(DEREF(msg, oneofdata->ofs, zval**));
+}
+
+static void *oneofbytes_handler(void *closure,
+ const void *hd,
+ size_t size_hint) {
+ MessageHeader* msg = closure;
+ const oneof_handlerdata_t *oneofdata = hd;
+
+ DEREF(msg, oneofdata->case_ofs, uint32_t) =
+ oneofdata->oneof_case_num;
+ DEREF(msg, oneofdata->ofs, zval**) =
+ &(msg->std.properties_table)[oneofdata->property_ofs];
+
+ // TODO(teboring): Add it back.
+ // rb_enc_associate(str, kRubyString8bitEncoding);
+
+ SEPARATE_ZVAL_IF_NOT_REF(DEREF(msg, oneofdata->ofs, zval**));
+ zval* str = *DEREF(msg, oneofdata->ofs, zval**);
+ zval_dtor(str);
+ ZVAL_STRINGL(str, "", 0, 1);
+ return (void*)str;
+}
+
+// Handler for a submessage field in a oneof.
+static void *oneofsubmsg_handler(void *closure,
+ const void *hd) {
+ MessageHeader* msg = closure;
+ const oneof_handlerdata_t *oneofdata = hd;
+ uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t);
+ zval* subdesc_php = get_def_obj((void*)oneofdata->md);
+ Descriptor* subdesc = zend_object_store_get_object(subdesc_php TSRMLS_CC);
+ zend_class_entry* subklass = subdesc->klass;
+ zval* submsg_php;
+ MessageHeader* submsg;
+
+ if (oldcase != oneofdata->oneof_case_num) {
+ DEREF(msg, oneofdata->ofs, zval**) =
+ &(msg->std.properties_table)[oneofdata->property_ofs];
+ }
+
+ if (Z_TYPE_P(*DEREF(msg, oneofdata->ofs, zval**)) == IS_NULL) {
+ zval* val = NULL;
+ MAKE_STD_ZVAL(val);
+ Z_TYPE_P(val) = IS_OBJECT;
+ Z_OBJVAL_P(val) = subklass->create_object(subklass TSRMLS_CC);
+
+ zval_ptr_dtor(DEREF(msg, oneofdata->ofs, zval**));
+ *DEREF(msg, oneofdata->ofs, zval**) = val;
+ }
+
+ DEREF(msg, oneofdata->case_ofs, uint32_t) =
+ oneofdata->oneof_case_num;
+
+ submsg_php = *DEREF(msg, oneofdata->ofs, zval**);
+ submsg = zend_object_store_get_object(submsg_php TSRMLS_CC);
+ return submsg;
+}
+
+// Set up handlers for a repeated field.
+static void add_handlers_for_repeated_field(upb_handlers *h,
+ const upb_fielddef *f,
+ size_t offset) {
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
+ upb_handlers_setstartseq(h, f, startseq_handler, &attr);
+ upb_handlerattr_uninit(&attr);
+
+ switch (upb_fielddef_type(f)) {
+
+#define SET_HANDLER(utype, ltype) \
+ case utype: \
+ upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \
+ break;
+
+ SET_HANDLER(UPB_TYPE_BOOL, bool);
+ SET_HANDLER(UPB_TYPE_INT32, int32);
+ SET_HANDLER(UPB_TYPE_UINT32, uint32);
+ SET_HANDLER(UPB_TYPE_ENUM, int32);
+ SET_HANDLER(UPB_TYPE_FLOAT, float);
+ SET_HANDLER(UPB_TYPE_INT64, int64);
+ SET_HANDLER(UPB_TYPE_UINT64, uint64);
+ SET_HANDLER(UPB_TYPE_DOUBLE, double);
+
+#undef SET_HANDLER
+
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES: {
+ bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
+ upb_handlers_setstartstr(h, f, is_bytes ?
+ appendbytes_handler : appendstr_handler,
+ NULL);
+ upb_handlers_setstring(h, f, stringdata_handler, NULL);
+ break;
+ }
+ case UPB_TYPE_MESSAGE: {
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, 0, f));
+ upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
+ upb_handlerattr_uninit(&attr);
+ break;
+ }
+ }
+}
+
+// Set up handlers for a singular field.
+static void add_handlers_for_singular_field(upb_handlers *h,
+ const upb_fielddef *f,
+ size_t offset) {
+ switch (upb_fielddef_type(f)) {
+ case UPB_TYPE_BOOL:
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_UINT32:
+ case UPB_TYPE_ENUM:
+ case UPB_TYPE_FLOAT:
+ case UPB_TYPE_INT64:
+ case UPB_TYPE_UINT64:
+ case UPB_TYPE_DOUBLE:
+ upb_shim_set(h, f, offset, -1);
+ break;
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES: {
+ bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
+ upb_handlers_setstartstr(h, f,
+ is_bytes ? bytes_handler : str_handler,
+ &attr);
+ upb_handlers_setstring(h, f, stringdata_handler, &attr);
+ upb_handlerattr_uninit(&attr);
+ break;
+ }
+ case UPB_TYPE_MESSAGE: {
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, offset, f));
+ upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
+ upb_handlerattr_uninit(&attr);
+ break;
+ }
+ }
+}
+
+// Adds handlers to a map field.
+static void add_handlers_for_mapfield(upb_handlers* h,
+ const upb_fielddef* fielddef,
+ size_t offset,
+ Descriptor* desc) {
+ const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef);
+ map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc);
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+
+ upb_handlers_addcleanup(h, hd, free);
+ upb_handlerattr_sethandlerdata(&attr, hd);
+ upb_handlers_setstartsubmsg(h, fielddef, startmapentry_handler, &attr);
+ upb_handlerattr_uninit(&attr);
+}
+
+// Adds handlers to a map-entry msgdef.
+static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h,
+ Descriptor* desc) {
+ const upb_fielddef* key_field = map_entry_key(msgdef);
+ const upb_fielddef* value_field = map_entry_value(msgdef);
+ map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc);
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+
+ upb_handlers_addcleanup(h, hd, free);
+ upb_handlerattr_sethandlerdata(&attr, hd);
+ upb_handlers_setendmsg(h, endmap_handler, &attr);
+
+ add_handlers_for_singular_field(h, key_field,
+ offsetof(map_parse_frame_t, key_storage));
+ add_handlers_for_singular_field(h, value_field,
+ offsetof(map_parse_frame_t, value_storage));
+}
+
+// Set up handlers for a oneof field.
+static void add_handlers_for_oneof_field(upb_handlers *h,
+ const upb_fielddef *f,
+ size_t offset,
+ size_t oneof_case_offset,
+ int property_cache_offset) {
+
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr_sethandlerdata(
+ &attr, newoneofhandlerdata(h, offset, oneof_case_offset,
+ property_cache_offset, f));
+
+ switch (upb_fielddef_type(f)) {
+
+#define SET_HANDLER(utype, ltype) \
+ case utype: \
+ upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \
+ break;
+
+ SET_HANDLER(UPB_TYPE_BOOL, bool);
+ SET_HANDLER(UPB_TYPE_INT32, int32);
+ SET_HANDLER(UPB_TYPE_UINT32, uint32);
+ SET_HANDLER(UPB_TYPE_ENUM, int32);
+ SET_HANDLER(UPB_TYPE_FLOAT, float);
+ SET_HANDLER(UPB_TYPE_INT64, int64);
+ SET_HANDLER(UPB_TYPE_UINT64, uint64);
+ SET_HANDLER(UPB_TYPE_DOUBLE, double);
+
+#undef SET_HANDLER
+
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES: {
+ bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
+ upb_handlers_setstartstr(h, f, is_bytes ?
+ oneofbytes_handler : oneofstr_handler,
+ &attr);
+ upb_handlers_setstring(h, f, stringdata_handler, NULL);
+ break;
+ }
+ case UPB_TYPE_MESSAGE: {
+ upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr);
+ break;
+ }
+ }
+
+ upb_handlerattr_uninit(&attr);
+}
+
+static void add_handlers_for_message(const void *closure, upb_handlers *h) {
+ const upb_msgdef* msgdef = upb_handlers_msgdef(h);
+ Descriptor* desc = (Descriptor*)zend_object_store_get_object(
+ get_def_obj((void*)msgdef) TSRMLS_CC);
+ upb_msg_field_iter i;
+
+ // If this is a mapentry message type, set up a special set of handlers and
+ // bail out of the normal (user-defined) message type handling.
+ if (upb_msgdef_mapentry(msgdef)) {
+ add_handlers_for_mapentry(msgdef, h, desc);
+ return;
+ }
+
+ // Ensure layout exists. We may be invoked to create handlers for a given
+ // message if we are included as a submsg of another message type before our
+ // class is actually built, so to work around this, we just create the layout
+ // (and handlers, in the class-building function) on-demand.
+ if (desc->layout == NULL) {
+ desc->layout = create_layout(desc->msgdef);
+ }
+
+ for (upb_msg_field_begin(&i, desc->msgdef);
+ !upb_msg_field_done(&i);
+ upb_msg_field_next(&i)) {
+ const upb_fielddef *f = upb_msg_iter_field(&i);
+ size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset +
+ sizeof(MessageHeader);
+
+ if (upb_fielddef_containingoneof(f)) {
+ size_t oneof_case_offset =
+ desc->layout->fields[upb_fielddef_index(f)].case_offset +
+ sizeof(MessageHeader);
+ int property_cache_index =
+ desc->layout->fields[upb_fielddef_index(f)].cache_index;
+ add_handlers_for_oneof_field(h, f, offset, oneof_case_offset,
+ property_cache_index);
+ } else if (is_map_field(f)) {
+ add_handlers_for_mapfield(h, f, offset, desc);
+ } else if (upb_fielddef_isseq(f)) {
+ add_handlers_for_repeated_field(h, f, offset);
+ } else {
+ add_handlers_for_singular_field(h, f, offset);
+ }
+ }
+}
+
+// Creates upb handlers for populating a message.
+static const upb_handlers *new_fill_handlers(Descriptor* desc,
+ const void* owner) {
+ // TODO(cfallin, haberman): once upb gets a caching/memoization layer for
+ // handlers, reuse subdef handlers so that e.g. if we already parse
+ // B-with-field-of-type-C, we don't have to rebuild the whole hierarchy to
+ // parse A-with-field-of-type-B-with-field-of-type-C.
+ return upb_handlers_newfrozen(desc->msgdef, owner,
+ add_handlers_for_message, NULL);
+}
+
+// Constructs the handlers for filling a message's data into an in-memory
+// object.
+const upb_handlers* get_fill_handlers(Descriptor* desc) {
+ if (!desc->fill_handlers) {
+ desc->fill_handlers =
+ new_fill_handlers(desc, &desc->fill_handlers);
+ }
+ return desc->fill_handlers;
+}
+
+const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor* desc,
+ const void* owner) {
+ const upb_handlers* handlers = get_fill_handlers(desc);
+ upb_pbdecodermethodopts opts;
+ upb_pbdecodermethodopts_init(&opts, handlers);
+
+ return upb_pbdecodermethod_new(&opts, owner);
+}
+
+static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) {
+ if (desc->fill_method == NULL) {
+ desc->fill_method = new_fillmsg_decodermethod(
+ desc, &desc->fill_method);
+ }
+ return desc->fill_method;
+}
+
+// -----------------------------------------------------------------------------
+// Serializing.
+// -----------------------------------------------------------------------------
+
+static void putmsg(zval* msg, const Descriptor* desc, upb_sink* sink,
+ int depth);
+
+static void putstr(zval* str, const upb_fielddef* f, upb_sink* sink);
+
+static void putrawstr(const char* str, int len, const upb_fielddef* f,
+ upb_sink* sink);
+
+static void putsubmsg(zval* submsg, const upb_fielddef* f, upb_sink* sink,
+ int depth);
+
+static void putarray(zval* array, const upb_fielddef* f, upb_sink* sink,
+ int depth);
+static void putmap(zval* map, const upb_fielddef* f, upb_sink* sink, int depth);
+
+static upb_selector_t getsel(const upb_fielddef* f, upb_handlertype_t type) {
+ upb_selector_t ret;
+ bool ok = upb_handlers_getselector(f, type, &ret);
+ UPB_ASSERT(ok);
+ return ret;
+}
+
+static void put_optional_value(void* memory, int len, const upb_fielddef* f,
+ int depth, upb_sink* sink) {
+ assert(upb_fielddef_label(f) == UPB_LABEL_OPTIONAL);
+
+ switch (upb_fielddef_type(f)) {
+#define T(upbtypeconst, upbtype, ctype, default_value) \
+ case upbtypeconst: { \
+ ctype value = DEREF(memory, 0, ctype); \
+ if (value != default_value) { \
+ upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); \
+ upb_sink_put##upbtype(sink, sel, value); \
+ } \
+ } break;
+
+ T(UPB_TYPE_FLOAT, float, float, 0.0)
+ T(UPB_TYPE_DOUBLE, double, double, 0.0)
+ T(UPB_TYPE_BOOL, bool, uint8_t, 0)
+ T(UPB_TYPE_ENUM, int32, int32_t, 0)
+ T(UPB_TYPE_INT32, int32, int32_t, 0)
+ T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
+ T(UPB_TYPE_INT64, int64, int64_t, 0)
+ T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
+
+#undef T
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ putrawstr(memory, len, f, sink);
+ break;
+ case UPB_TYPE_MESSAGE: {
+ zval* submsg = *(zval**)memory;
+ putsubmsg(submsg, f, sink, depth);
+ break;
+ }
+ default:
+ assert(false);
+ }
+}
+
+// Only string/bytes fields are stored as zval.
+static const char* raw_value(void* memory, const upb_fielddef* f) {
+ switch (upb_fielddef_type(f)) {
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ return Z_STRVAL_PP((zval**)memory);
+ break;
+ default:
+ return memory;
+ }
+}
+
+static int raw_value_len(void* memory, int len, const upb_fielddef* f) {
+ switch (upb_fielddef_type(f)) {
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ return Z_STRLEN_PP((zval**)memory);
+ break;
+ default:
+ return len;
+ }
+}
+
+static void putmap(zval* map, const upb_fielddef* f, upb_sink* sink,
+ int depth) {
+ Map* self;
+ upb_sink subsink;
+ const upb_fielddef* key_field;
+ const upb_fielddef* value_field;
+ MapIter it;
+ int len;
+
+ if (map == NULL) return;
+ self = UNBOX(Map, map);
+
+ upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
+
+ assert(upb_fielddef_type(f) == UPB_TYPE_MESSAGE);
+ key_field = map_field_key(f);
+ value_field = map_field_value(f);
+
+ for (map_begin(map, &it); !map_done(&it); map_next(&it)) {
+ upb_status status;
+
+ upb_sink entry_sink;
+ upb_sink_startsubmsg(&subsink, getsel(f, UPB_HANDLER_STARTSUBMSG),
+ &entry_sink);
+ upb_sink_startmsg(&entry_sink);
+
+ // Serialize key.
+ const char *key = map_iter_key(&it, &len);
+ put_optional_value(key, len, key_field, depth + 1, &entry_sink);
+
+ // Serialize value.
+ upb_value value = map_iter_value(&it, &len);
+ put_optional_value(raw_value(upb_value_memory(&value), value_field),
+ raw_value_len(upb_value_memory(&value), len, value_field),
+ value_field, depth + 1, &entry_sink);
+
+ upb_sink_endmsg(&entry_sink, &status);
+ upb_sink_endsubmsg(&subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
+ }
+
+ upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
+}
+
+static void putmsg(zval* msg_php, const Descriptor* desc, upb_sink* sink,
+ int depth) {
+ upb_msg_field_iter i;
+ upb_status status;
+
+ upb_sink_startmsg(sink);
+
+ // Protect against cycles (possible because users may freely reassign message
+ // and repeated fields) by imposing a maximum recursion depth.
+ if (depth > ENCODE_MAX_NESTING) {
+ zend_error(E_ERROR,
+ "Maximum recursion depth exceeded during encoding.");
+ }
+
+ MessageHeader* msg = zend_object_store_get_object(msg_php TSRMLS_CC);
+
+ for (upb_msg_field_begin(&i, desc->msgdef); !upb_msg_field_done(&i);
+ upb_msg_field_next(&i)) {
+ upb_fielddef* f = upb_msg_iter_field(&i);
+ uint32_t offset = desc->layout->fields[upb_fielddef_index(f)].offset +
+ sizeof(MessageHeader);
+
+ if (upb_fielddef_containingoneof(f)) {
+ uint32_t oneof_case_offset =
+ desc->layout->fields[upb_fielddef_index(f)].case_offset +
+ sizeof(MessageHeader);
+ // For a oneof, check that this field is actually present -- skip all the
+ // below if not.
+ if (DEREF(msg, oneof_case_offset, uint32_t) != upb_fielddef_number(f)) {
+ continue;
+ }
+ // Otherwise, fall through to the appropriate singular-field handler
+ // below.
+ }
+
+ if (is_map_field(f)) {
+ zval* map = *DEREF(msg, offset, zval**);
+ if (map != NULL) {
+ putmap(map, f, sink, depth);
+ }
+ } else if (upb_fielddef_isseq(f)) {
+ zval* array = *DEREF(msg, offset, zval**);
+ if (array != NULL) {
+ putarray(array, f, sink, depth);
+ }
+ } else if (upb_fielddef_isstring(f)) {
+ zval* str = *DEREF(msg, offset, zval**);
+ if (Z_STRLEN_P(str) > 0) {
+ putstr(str, f, sink);
+ }
+ } else if (upb_fielddef_issubmsg(f)) {
+ putsubmsg(*DEREF(msg, offset, zval**), f, sink, depth);
+ } else {
+ upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
+
+#define T(upbtypeconst, upbtype, ctype, default_value) \
+ case upbtypeconst: { \
+ ctype value = DEREF(msg, offset, ctype); \
+ if (value != default_value) { \
+ upb_sink_put##upbtype(sink, sel, value); \
+ } \
+ } break;
+
+ switch (upb_fielddef_type(f)) {
+ T(UPB_TYPE_FLOAT, float, float, 0.0)
+ T(UPB_TYPE_DOUBLE, double, double, 0.0)
+ T(UPB_TYPE_BOOL, bool, uint8_t, 0)
+ case UPB_TYPE_ENUM:
+ T(UPB_TYPE_INT32, int32, int32_t, 0)
+ T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
+ T(UPB_TYPE_INT64, int64, int64_t, 0)
+ T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
+
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_MESSAGE:
+ zend_error(E_ERROR, "Internal error.");
+ }
+
+#undef T
+ }
+ }
+
+ upb_sink_endmsg(sink, &status);
+}
+
+static void putstr(zval* str, const upb_fielddef *f, upb_sink *sink) {
+ upb_sink subsink;
+
+ if (ZVAL_IS_NULL(str)) return;
+
+ assert(Z_TYPE_P(str) == IS_STRING);
+
+ // Ensure that the string has the correct encoding. We also check at field-set
+ // time, but the user may have mutated the string object since then.
+ if (upb_fielddef_type(f) == UPB_TYPE_STRING &&
+ !is_structurally_valid_utf8(Z_STRVAL_P(str), Z_STRLEN_P(str))) {
+ zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
+ return;
+ }
+
+ upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), Z_STRLEN_P(str),
+ &subsink);
+ upb_sink_putstring(&subsink, getsel(f, UPB_HANDLER_STRING), Z_STRVAL_P(str),
+ Z_STRLEN_P(str), NULL);
+ upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
+}
+
+static void putrawstr(const char* str, int len, const upb_fielddef* f,
+ upb_sink* sink) {
+ upb_sink subsink;
+
+ if (len == 0) return;
+
+ // Ensure that the string has the correct encoding. We also check at field-set
+ // time, but the user may have mutated the string object since then.
+ if (upb_fielddef_type(f) == UPB_TYPE_STRING &&
+ !is_structurally_valid_utf8(str, len)) {
+ zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
+ return;
+ }
+
+ upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), len, &subsink);
+ upb_sink_putstring(&subsink, getsel(f, UPB_HANDLER_STRING), str, len, NULL);
+ upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
+}
+
+static void putsubmsg(zval* submsg, const upb_fielddef* f, upb_sink* sink,
+ int depth) {
+ upb_sink subsink;
+
+ if (Z_TYPE_P(submsg) == IS_NULL) return;
+
+ zval* php_descriptor = get_def_obj(upb_fielddef_msgsubdef(f));
+ Descriptor* subdesc =
+ (Descriptor*)zend_object_store_get_object(php_descriptor TSRMLS_CC);
+
+ upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
+ putmsg(submsg, subdesc, &subsink, depth + 1);
+ upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
+}
+
+static void putarray(zval* array, const upb_fielddef* f, upb_sink* sink,
+ int depth) {
+ upb_sink subsink;
+ upb_fieldtype_t type = upb_fielddef_type(f);
+ upb_selector_t sel = 0;
+ int size, i;
+
+ assert(array != NULL);
+ RepeatedField* intern =
+ (RepeatedField*)zend_object_store_get_object(array TSRMLS_CC);
+ size = zend_hash_num_elements(HASH_OF(intern->array));
+ if (size == 0) return;
+
+ upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
+
+ if (upb_fielddef_isprimitive(f)) {
+ sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
+ }
+
+ for (i = 0; i < size; i++) {
+ void* memory = repeated_field_index_native(intern, i);
+ switch (type) {
+#define T(upbtypeconst, upbtype, ctype) \
+ case upbtypeconst: \
+ upb_sink_put##upbtype(&subsink, sel, *((ctype*)memory)); \
+ break;
+
+ T(UPB_TYPE_FLOAT, float, float)
+ T(UPB_TYPE_DOUBLE, double, double)
+ T(UPB_TYPE_BOOL, bool, int8_t)
+ case UPB_TYPE_ENUM:
+ T(UPB_TYPE_INT32, int32, int32_t)
+ T(UPB_TYPE_UINT32, uint32, uint32_t)
+ T(UPB_TYPE_INT64, int64, int64_t)
+ T(UPB_TYPE_UINT64, uint64, uint64_t)
+
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ putstr(*((zval**)memory), f, &subsink);
+ break;
+ case UPB_TYPE_MESSAGE:
+ putsubmsg(*((zval**)memory), f, &subsink, depth);
+ break;
+
+#undef T
+ }
+ }
+ upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
+}
+
+static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
+ if (desc->pb_serialize_handlers == NULL) {
+ desc->pb_serialize_handlers =
+ upb_pb_encoder_newhandlers(desc->msgdef, &desc->pb_serialize_handlers);
+ }
+ return desc->pb_serialize_handlers;
+}
+
+// -----------------------------------------------------------------------------
+// PHP encode/decode methods
+// -----------------------------------------------------------------------------
+
+PHP_METHOD(Message, encode) {
+ zval* php_descriptor = get_ce_obj(Z_OBJCE_P(getThis()));
+ Descriptor* desc =
+ (Descriptor*)zend_object_store_get_object(php_descriptor TSRMLS_CC);
+
+ stringsink sink;
+ stringsink_init(&sink);
+
+ {
+ const upb_handlers* serialize_handlers = msgdef_pb_serialize_handlers(desc);
+
+ stackenv se;
+ upb_pb_encoder* encoder;
+
+ 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);
+
+ RETVAL_STRINGL(sink.ptr, sink.len, 1);
+
+ stackenv_uninit(&se);
+ stringsink_uninit(&sink);
+ }
+}
+
+PHP_METHOD(Message, decode) {
+ zval* php_descriptor = get_ce_obj(Z_OBJCE_P(getThis()));
+ Descriptor* desc =
+ (Descriptor*)zend_object_store_get_object(php_descriptor TSRMLS_CC);
+ MessageHeader* msg = zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ char *data = NULL;
+ int data_len;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) ==
+ FAILURE) {
+ 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);
+ }
+}
diff --git a/php/ext/google/protobuf/map.c b/php/ext/google/protobuf/map.c
new file mode 100644
index 00000000..6d822fff
--- /dev/null
+++ b/php/ext/google/protobuf/map.c
@@ -0,0 +1,470 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <ext/spl/spl_iterators.h>
+#include <Zend/zend_API.h>
+#include <Zend/zend_interfaces.h>
+
+#include "protobuf.h"
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
+ ZEND_ARG_INFO(0, index)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, newval)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
+ZEND_END_ARG_INFO()
+
+// Utilities
+
+void* upb_value_memory(upb_value* v) {
+ return (void*)(&v->val);
+}
+
+// -----------------------------------------------------------------------------
+// Basic map operations on top of upb's strtable.
+//
+// Note that we roll our own `Map` container here because, as for
+// `RepeatedField`, we want a strongly-typed container. This is so that any user
+// errors due to incorrect map key or value types are raised as close as
+// possible to the error site, rather than at some deferred point (e.g.,
+// serialization).
+//
+// We build our `Map` on top of upb_strtable so that we're able to take
+// advantage of the native_slot storage abstraction, as RepeatedField does.
+// (This is not quite a perfect mapping -- see the key conversions below -- but
+// gives us full support and error-checking for all value types for free.)
+// -----------------------------------------------------------------------------
+
+// Map values are stored using the native_slot abstraction (as with repeated
+// field values), but keys are a bit special. Since we use a strtable, we need
+// to store keys as sequences of bytes such that equality of those bytes maps
+// one-to-one to equality of keys. We store strings directly (i.e., they map to
+// their own bytes) and integers as native integers (using the native_slot
+// abstraction).
+
+// Note that there is another tradeoff here in keeping string keys as native
+// strings rather than PHP strings: traversing the Map requires conversion to
+// PHP string values on every traversal, potentially creating more garbage. We
+// should consider ways to cache a PHP version of the key if this becomes an
+// issue later.
+
+// Forms a key to use with the underlying strtable from a PHP key value. |buf|
+// must point to TABLE_KEY_BUF_LENGTH bytes of temporary space, used to
+// construct a key byte sequence if needed. |out_key| and |out_length| provide
+// the resulting key data/length.
+#define TABLE_KEY_BUF_LENGTH 8 // sizeof(uint64_t)
+static bool table_key(Map* self, zval* key,
+ char* buf,
+ const char** out_key,
+ size_t* out_length) {
+ switch (self->key_type) {
+ case UPB_TYPE_STRING:
+ if (!protobuf_convert_to_string(key)) {
+ return false;
+ }
+ if (!is_structurally_valid_utf8(Z_STRVAL_P(key), Z_STRLEN_P(key))) {
+ zend_error(E_USER_ERROR, "Given key is not UTF8 encoded.");
+ return false;
+ }
+ *out_key = Z_STRVAL_P(key);
+ *out_length = Z_STRLEN_P(key);
+ break;
+
+#define CASE_TYPE(upb_type, type, c_type, php_type) \
+ case UPB_TYPE_##upb_type: { \
+ c_type type##_value; \
+ if (!protobuf_convert_to_##type(key, &type##_value)) { \
+ return false; \
+ } \
+ native_slot_set(self->key_type, NULL, buf, key); \
+ *out_key = buf; \
+ *out_length = native_slot_size(self->key_type); \
+ break; \
+ }
+ CASE_TYPE(BOOL, bool, int8_t, BOOL)
+ CASE_TYPE(INT32, int32, int32_t, LONG)
+ CASE_TYPE(INT64, int64, int64_t, LONG)
+ CASE_TYPE(UINT32, uint32, uint32_t, LONG)
+ CASE_TYPE(UINT64, uint64, uint64_t, LONG)
+
+#undef CASE_TYPE
+
+ default:
+ // Map constructor should not allow a Map with another key type to be
+ // constructed.
+ assert(false);
+ break;
+ }
+
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+// MapField methods
+// -----------------------------------------------------------------------------
+
+static zend_function_entry map_field_methods[] = {
+ PHP_ME(MapField, __construct, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(MapField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
+ PHP_ME(MapField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC)
+ PHP_ME(MapField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC)
+ PHP_ME(MapField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC)
+ PHP_ME(MapField, count, arginfo_void, ZEND_ACC_PUBLIC)
+ ZEND_FE_END
+};
+
+// -----------------------------------------------------------------------------
+// MapField creation/desctruction
+// -----------------------------------------------------------------------------
+
+zend_class_entry* map_field_type;
+zend_object_handlers* map_field_handlers;
+
+static map_begin_internal(Map *map, MapIter *iter) {
+ iter->self = map;
+ upb_strtable_begin(&iter->it, &map->table);
+}
+
+static HashTable *map_field_get_gc(zval *object, zval ***table,
+ int *n TSRMLS_DC) {
+ // TODO(teboring): Unfortunately, zend engine does not support garbage
+ // collection for custom array. We have to use zend engine's native array
+ // instead.
+ *table = NULL;
+ *n = 0;
+ return NULL;
+}
+
+void map_field_init(TSRMLS_D) {
+ zend_class_entry class_type;
+ const char* class_name = "Google\\Protobuf\\Internal\\MapField";
+ INIT_CLASS_ENTRY_EX(class_type, class_name, strlen(class_name),
+ map_field_methods);
+
+ map_field_type = zend_register_internal_class(&class_type TSRMLS_CC);
+ map_field_type->create_object = map_field_create;
+
+ zend_class_implements(map_field_type TSRMLS_CC, 2, spl_ce_ArrayAccess,
+ spl_ce_Countable);
+
+ map_field_handlers = PEMALLOC(zend_object_handlers);
+ memcpy(map_field_handlers, zend_get_std_object_handlers(),
+ sizeof(zend_object_handlers));
+ map_field_handlers->get_gc = map_field_get_gc;
+}
+
+zend_object_value map_field_create(zend_class_entry *ce TSRMLS_DC) {
+ zend_object_value retval = {0};
+ Map *intern;
+
+ intern = emalloc(sizeof(Map));
+ memset(intern, 0, sizeof(Map));
+
+ zend_object_std_init(&intern->std, ce TSRMLS_CC);
+ object_properties_init(&intern->std, ce);
+
+ // Table value type is always UINT64: this ensures enough space to store the
+ // native_slot value.
+ if (!upb_strtable_init(&intern->table, UPB_CTYPE_UINT64)) {
+ zend_error(E_USER_ERROR, "Could not allocate table.");
+ }
+
+ retval.handle = zend_objects_store_put(
+ intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
+ (zend_objects_free_object_storage_t)map_field_free, NULL TSRMLS_CC);
+ retval.handlers = map_field_handlers;
+
+ return retval;
+}
+
+void map_field_free(void *object TSRMLS_DC) {
+ Map *map = (Map *)object;
+
+ switch (map->value_type) {
+ case UPB_TYPE_MESSAGE:
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES: {
+ MapIter it;
+ int len;
+ for (map_begin_internal(map, &it); !map_done(&it); map_next(&it)) {
+ upb_value value = map_iter_value(&it, &len);
+ void *mem = upb_value_memory(&value);
+ zval_ptr_dtor(mem);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ upb_strtable_uninit(&map->table);
+ zend_object_std_dtor(&map->std TSRMLS_CC);
+ efree(object);
+}
+
+void map_field_create_with_type(zend_class_entry *ce, const upb_fielddef *field,
+ zval **map_field TSRMLS_DC) {
+ MAKE_STD_ZVAL(*map_field);
+ Z_TYPE_PP(map_field) = IS_OBJECT;
+ Z_OBJVAL_PP(map_field) =
+ map_field_type->create_object(map_field_type TSRMLS_CC);
+
+ Map* intern =
+ (Map*)zend_object_store_get_object(*map_field TSRMLS_CC);
+
+ const upb_fielddef *key_field = map_field_key(field);
+ const upb_fielddef *value_field = map_field_value(field);
+ intern->key_type = upb_fielddef_type(key_field);
+ intern->value_type = upb_fielddef_type(value_field);
+ intern->msg_ce = field_type_class(value_field);
+}
+
+static void map_field_free_element(void *object) {
+}
+
+// -----------------------------------------------------------------------------
+// MapField Handlers
+// -----------------------------------------------------------------------------
+
+static bool *map_field_read_dimension(zval *object, zval *key, int type,
+ zval **retval TSRMLS_DC) {
+ Map *intern =
+ (Map *)zend_object_store_get_object(object TSRMLS_CC);
+
+ char keybuf[TABLE_KEY_BUF_LENGTH];
+ const char* keyval = NULL;
+ size_t length = 0;
+ upb_value v;
+#ifndef NDEBUG
+ v.ctype = UPB_CTYPE_UINT64;
+#endif
+ if (!table_key(intern, key, keybuf, &keyval, &length)) {
+ return false;
+ }
+
+ if (upb_strtable_lookup2(&intern->table, keyval, length, &v)) {
+ void* mem = upb_value_memory(&v);
+ native_slot_get(intern->value_type, mem, retval TSRMLS_CC);
+ return true;
+ } else {
+ zend_error(E_USER_ERROR, "Given key doesn't exist.");
+ return false;
+ }
+}
+
+bool map_index_set(Map *intern, const char* keyval, int length, upb_value v) {
+ // Replace any existing value by issuing a 'remove' operation first.
+ upb_strtable_remove2(&intern->table, keyval, length, NULL);
+ if (!upb_strtable_insert2(&intern->table, keyval, length, v)) {
+ zend_error(E_USER_ERROR, "Could not insert into table");
+ return false;
+ }
+ return true;
+}
+
+static bool map_field_write_dimension(zval *object, zval *key,
+ zval *value TSRMLS_DC) {
+ Map *intern = (Map *)zend_object_store_get_object(object TSRMLS_CC);
+
+ char keybuf[TABLE_KEY_BUF_LENGTH];
+ const char* keyval = NULL;
+ size_t length = 0;
+ upb_value v;
+ void* mem;
+ if (!table_key(intern, key, keybuf, &keyval, &length)) {
+ return false;
+ }
+
+ mem = upb_value_memory(&v);
+ memset(mem, 0, native_slot_size(intern->value_type));
+ if(!native_slot_set(intern->value_type, intern->msg_ce, mem, value)) {
+ return false;
+ }
+#ifndef NDEBUG
+ v.ctype = UPB_CTYPE_UINT64;
+#endif
+
+ // Replace any existing value by issuing a 'remove' operation first.
+ upb_strtable_remove2(&intern->table, keyval, length, NULL);
+ if (!upb_strtable_insert2(&intern->table, keyval, length, v)) {
+ zend_error(E_USER_ERROR, "Could not insert into table");
+ return false;
+ }
+
+ return true;
+}
+
+static bool map_field_unset_dimension(zval *object, zval *key TSRMLS_DC) {
+ Map *intern = (Map *)zend_object_store_get_object(object TSRMLS_CC);
+
+ char keybuf[TABLE_KEY_BUF_LENGTH];
+ const char* keyval = NULL;
+ size_t length = 0;
+ upb_value v;
+ if (!table_key(intern, key, keybuf, &keyval, &length)) {
+ return false;
+ }
+#ifndef NDEBUG
+ v.ctype = UPB_CTYPE_UINT64;
+#endif
+
+ upb_strtable_remove2(&intern->table, keyval, length, &v);
+
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+// PHP MapField Methods
+// -----------------------------------------------------------------------------
+
+PHP_METHOD(MapField, __construct) {
+ long key_type, value_type;
+ zend_class_entry* klass = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|C", &key_type,
+ &value_type, &klass) == FAILURE) {
+ return;
+ }
+
+ Map* intern =
+ (Map*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ intern->key_type = to_fieldtype(key_type);
+ intern->value_type = to_fieldtype(value_type);
+ intern->msg_ce = klass;
+
+ // Check that the key type is an allowed type.
+ switch (intern->key_type) {
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_INT64:
+ case UPB_TYPE_UINT32:
+ case UPB_TYPE_UINT64:
+ case UPB_TYPE_BOOL:
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ // These are OK.
+ break;
+ default:
+ zend_error(E_USER_ERROR, "Invalid key type for map.");
+ }
+}
+
+PHP_METHOD(MapField, offsetExists) {
+ zval *key;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) ==
+ FAILURE) {
+ return;
+ }
+
+ Map *intern = (Map *)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ char keybuf[TABLE_KEY_BUF_LENGTH];
+ const char* keyval = NULL;
+ size_t length = 0;
+ upb_value v;
+#ifndef NDEBUG
+ v.ctype = UPB_CTYPE_UINT64;
+#endif
+ if (!table_key(intern, key, keybuf, &keyval, &length)) {
+ return false;
+ }
+
+ RETURN_BOOL(upb_strtable_lookup2(&intern->table, keyval, length, &v));
+}
+
+PHP_METHOD(MapField, offsetGet) {
+ zval *index, *value;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) ==
+ FAILURE) {
+ return;
+ }
+ map_field_read_dimension(getThis(), index, BP_VAR_R,
+ return_value_ptr TSRMLS_CC);
+}
+
+PHP_METHOD(MapField, offsetSet) {
+ zval *index, *value;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &index, &value) ==
+ FAILURE) {
+ return;
+ }
+ map_field_write_dimension(getThis(), index, value TSRMLS_CC);
+}
+
+PHP_METHOD(MapField, offsetUnset) {
+ zval *index;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) ==
+ FAILURE) {
+ return;
+ }
+ map_field_unset_dimension(getThis(), index TSRMLS_CC);
+}
+
+PHP_METHOD(MapField, count) {
+ Map *intern =
+ (MapField *)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ RETURN_LONG(upb_strtable_count(&intern->table));
+}
+
+// -----------------------------------------------------------------------------
+// Map Iterator
+// -----------------------------------------------------------------------------
+
+void map_begin(zval *map_php, MapIter *iter) {
+ Map *self = UNBOX(Map, map_php);
+ map_begin_internal(self, iter);
+}
+
+void map_next(MapIter *iter) {
+ upb_strtable_next(&iter->it);
+}
+
+bool map_done(MapIter *iter) {
+ return upb_strtable_done(&iter->it);
+}
+
+const char *map_iter_key(MapIter *iter, int *len) {
+ *len = upb_strtable_iter_keylength(&iter->it);
+ return upb_strtable_iter_key(&iter->it);
+}
+
+upb_value map_iter_value(MapIter *iter, int *len) {
+ *len = native_slot_size(iter->self->value_type);
+ return upb_strtable_iter_value(&iter->it);
+}
diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c
index c062d665..537cd1c4 100644
--- a/php/ext/google/protobuf/message.c
+++ b/php/ext/google/protobuf/message.c
@@ -29,245 +29,219 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <php.h>
+#include <stdlib.h>
#include "protobuf.h"
-// -----------------------------------------------------------------------------
-// Class/module creation from msgdefs and enumdefs, respectively.
-// -----------------------------------------------------------------------------
-
-void* message_data(void* msg) {
- return ((uint8_t *)msg) + sizeof(MessageHeader);
-}
-
-void message_set_property(zval* object, zval* field_name, zval* value,
- const zend_literal* key TSRMLS_DC) {
- const upb_fielddef* field;
-
- MessageHeader* self = zend_object_store_get_object(object TSRMLS_CC);
-
- CHECK_TYPE(field_name, IS_STRING);
- field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(field_name));
- if (field == NULL) {
- zend_error(E_ERROR, "Unknown field: %s", Z_STRVAL_P(field_name));
- }
- layout_set(self->descriptor->layout, message_data(self), field, value);
-}
-
-zval* message_get_property(zval* object, zval* member, int type,
- const zend_literal* key TSRMLS_DC) {
- MessageHeader* self =
- (MessageHeader*)zend_object_store_get_object(object TSRMLS_CC);
- CHECK_TYPE(member, IS_STRING);
-
- const upb_fielddef* field;
- field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member));
- if (field == NULL) {
- return EG(uninitialized_zval_ptr);
- }
- zval* retval = layout_get(self->descriptor->layout, message_data(self), field TSRMLS_CC);
- return retval;
-}
+static zend_class_entry* message_type;
+zend_object_handlers* message_handlers;
static zend_function_entry message_methods[] = {
PHP_ME(Message, encode, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Message, decode, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Message, readOneof, NULL, ZEND_ACC_PROTECTED)
+ PHP_ME(Message, writeOneof, NULL, ZEND_ACC_PROTECTED)
{NULL, NULL, NULL}
};
-/* stringsink *****************************************************************/
+// Forward declare static functions.
-// This should probably be factored into a common upb component.
+static void message_set_property(zval* object, zval* member, zval* value,
+ const zend_literal* key TSRMLS_DC);
+static zval* message_get_property(zval* object, zval* member, int type,
+ const zend_literal* key TSRMLS_DC);
+static zval** message_get_property_ptr_ptr(zval* object, zval* member, int type,
+ const zend_literal* key TSRMLS_DC);
-typedef struct {
- upb_byteshandler handler;
- upb_bytessink sink;
- char *ptr;
- size_t len, size;
-} stringsink;
-
-static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
- stringsink *sink = _sink;
- sink->len = 0;
- return sink;
-}
+static zend_object_value message_create(zend_class_entry* ce TSRMLS_DC);
+static void message_free(void* object TSRMLS_DC);
-static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
- size_t len, const upb_bufhandle *handle) {
- stringsink *sink = _sink;
- size_t new_size = sink->size;
+// -----------------------------------------------------------------------------
+// PHP Message Handlers
+// -----------------------------------------------------------------------------
- UPB_UNUSED(hd);
- UPB_UNUSED(handle);
+void message_init(TSRMLS_D) {
+ zend_class_entry class_type;
+ INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\Message",
+ message_methods);
+ message_type = zend_register_internal_class(&class_type TSRMLS_CC);
+
+ message_handlers = PEMALLOC(zend_object_handlers);
+ memcpy(message_handlers, zend_get_std_object_handlers(),
+ sizeof(zend_object_handlers));
+ message_handlers->write_property = message_set_property;
+ message_handlers->read_property = message_get_property;
+ message_handlers->get_property_ptr_ptr = message_get_property_ptr_ptr;
+}
- while (sink->len + len > new_size) {
- new_size *= 2;
+static void message_set_property(zval* object, zval* member, zval* value,
+ const zend_literal* key TSRMLS_DC) {
+ if (Z_TYPE_P(member) != IS_STRING) {
+ zend_error(E_USER_ERROR, "Unexpected type for field name");
+ return;
}
- if (new_size != sink->size) {
- sink->ptr = realloc(sink->ptr, new_size);
- sink->size = new_size;
+ if (Z_OBJCE_P(object) != EG(scope)) {
+ // User cannot set property directly (e.g., $m->a = 1)
+ zend_error(E_USER_ERROR, "Cannot access private property.");
+ return;
}
- memcpy(sink->ptr + sink->len, ptr, len);
- sink->len += len;
+ const upb_fielddef* field;
+
+ MessageHeader* self = zend_object_store_get_object(object TSRMLS_CC);
+
+ 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 len;
+ layout_set(self->descriptor->layout, self, field, value);
}
-void stringsink_init(stringsink *sink) {
- upb_byteshandler_init(&sink->handler);
- upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
- upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
+static zval* message_get_property(zval* object, zval* member, int type,
+ const zend_literal* key TSRMLS_DC) {
+ if (Z_TYPE_P(member) != IS_STRING) {
+ zend_error(E_USER_ERROR, "Property name has to be a string.");
+ return EG(uninitialized_zval_ptr);
+ }
- upb_bytessink_reset(&sink->sink, &sink->handler, sink);
+ if (Z_OBJCE_P(object) != EG(scope)) {
+ // User cannot get property directly (e.g., $a = $m->a)
+ zend_error(E_USER_ERROR, "Cannot access private property.");
+ return EG(uninitialized_zval_ptr);
+ }
- sink->size = 32;
- sink->ptr = malloc(sink->size);
- sink->len = 0;
-}
+ zend_property_info* property_info = NULL;
-void stringsink_uninit(stringsink *sink) { free(sink->ptr); }
-
-// Stack-allocated context during an encode/decode operation. Contains the upb
-// environment and its stack-based allocator, an initial buffer for allocations
-// to avoid malloc() when possible, and a template for PHP exception messages
-// if any error occurs.
-#define STACK_ENV_STACKBYTES 4096
-typedef struct {
- upb_env env;
- upb_seededalloc alloc;
- const char *php_error_template;
- char allocbuf[STACK_ENV_STACKBYTES];
-} stackenv;
-
-static void stackenv_init(stackenv* se, const char* errmsg);
-static void stackenv_uninit(stackenv* se);
-
-// Callback invoked by upb if any error occurs during parsing or serialization.
-static bool env_error_func(void* ud, const upb_status* status) {
- stackenv* se = ud;
- // Free the env -- rb_raise will longjmp up the stack past the encode/decode
- // function so it would not otherwise have been freed.
- stackenv_uninit(se);
-
- // TODO(teboring): have a way to verify that this is actually a parse error,
- // instead of just throwing "parse error" unconditionally.
- zend_error(E_ERROR, se->php_error_template);
- // Never reached.
- return false;
-}
+ // All properties should have been declared in the generated code and have
+ // corresponding zvals in properties_table.
+ ulong h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1);
+ if (zend_hash_quick_find(&Z_OBJCE_P(object)->properties_info,
+ Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, h,
+ (void**)&property_info) != SUCCESS) {
+ zend_error(E_USER_ERROR, "Property does not exist.");
+ return EG(uninitialized_zval_ptr);
+ }
+
+ MessageHeader* self =
+ (MessageHeader*)zend_object_store_get_object(object TSRMLS_CC);
-static void stackenv_init(stackenv* se, const char* errmsg) {
- se->php_error_template = errmsg;
- upb_env_init(&se->env);
- upb_seededalloc_init(&se->alloc, &se->allocbuf, STACK_ENV_STACKBYTES);
- upb_env_setallocfunc(&se->env, upb_seededalloc_getallocfunc(&se->alloc),
- &se->alloc);
- upb_env_seterrorfunc(&se->env, env_error_func, se);
+ const upb_fielddef* field;
+ field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member));
+ if (field == NULL) {
+ return EG(uninitialized_zval_ptr);
+ }
+ return layout_get(
+ self->descriptor->layout, message_data(self), field,
+ &Z_OBJ_P(object)->properties_table[property_info->offset] TSRMLS_CC);
}
-static void stackenv_uninit(stackenv* se) {
- upb_env_uninit(&se->env);
- upb_seededalloc_uninit(&se->alloc);
+static zval** message_get_property_ptr_ptr(zval* object, zval* member, int type,
+ const zend_literal* key TSRMLS_DC) {
+ return NULL;
}
// -----------------------------------------------------------------------------
-// Message
+// C Message Utilities
// -----------------------------------------------------------------------------
-static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
- if (desc->pb_serialize_handlers == NULL) {
- desc->pb_serialize_handlers =
- upb_pb_encoder_newhandlers(desc->msgdef, &desc->pb_serialize_handlers);
- }
- return desc->pb_serialize_handlers;
+void* message_data(void* msg) {
+ return ((uint8_t*)msg) + sizeof(MessageHeader);
}
-PHP_METHOD(Message, encode) {
- Descriptor* desc = (Descriptor*)zend_object_store_get_object(
- CE_STATIC_MEMBERS(Z_OBJCE_P(getThis()))[0] TSRMLS_CC);
-
- stringsink sink;
- stringsink_init(&sink);
-
- {
- const upb_handlers* serialize_handlers = msgdef_pb_serialize_handlers(desc);
+static void message_free(void* object TSRMLS_DC) {
+ MessageHeader* msg = (MessageHeader*)object;
+ int i;
- stackenv se;
- upb_pb_encoder* encoder;
-
- 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);
-
- RETVAL_STRINGL(sink.ptr, sink.len, 1);
-
- stackenv_uninit(&se);
- stringsink_uninit(&sink);
+ for (i = 0; i < msg->std.ce->default_properties_count; i++) {
+ zval_ptr_dtor(&msg->std.properties_table[i]);
}
+ efree(msg->std.properties_table);
+ efree(msg);
}
-void message_free(void * object TSRMLS_DC) {
- FREE(object);
-}
-
-zend_object_value message_create(zend_class_entry* ce TSRMLS_DC) {
+static zend_object_value message_create(zend_class_entry* ce TSRMLS_DC) {
zend_object_value return_value;
- zval* php_descriptor = get_def_obj(ce);
+ zval* php_descriptor = get_ce_obj(ce);
Descriptor* desc = zend_object_store_get_object(php_descriptor TSRMLS_CC);
MessageHeader* msg = (MessageHeader*)ALLOC_N(
uint8_t, sizeof(MessageHeader) + desc->layout->size);
memset(message_data(msg), 0, desc->layout->size);
- // We wrap first so that everything in the message object is GC-rooted in case
- // a collection happens during object creation in layout_init().
+ // We wrap first so that everything in the message object is GC-rooted in
+ // case a collection happens during object creation in layout_init().
msg->descriptor = desc;
- layout_init(desc->layout, message_data(msg));
zend_object_std_init(&msg->std, ce TSRMLS_CC);
+ object_properties_init(&msg->std, ce);
+ layout_init(desc->layout, message_data(msg), msg->std.properties_table);
return_value.handle = zend_objects_store_put(
- msg, (zend_objects_store_dtor_t)zend_objects_destroy_object,
- message_free, NULL TSRMLS_CC);
+ msg, (zend_objects_store_dtor_t)zend_objects_destroy_object, message_free,
+ NULL TSRMLS_CC);
- return_value.handlers = PROTOBUF_G(message_handlers);
+ return_value.handlers = message_handlers;
return return_value;
}
-const zend_class_entry* build_class_from_descriptor(
- zval* php_descriptor TSRMLS_DC) {
- Descriptor* desc = php_to_descriptor(php_descriptor);
+void build_class_from_descriptor(zval* php_descriptor TSRMLS_DC) {
+ Descriptor* desc = UNBOX(Descriptor, php_descriptor);
+
+ // Map entries don't have existing php class.
+ if (upb_msgdef_mapentry(desc->msgdef)) {
+ return;
+ }
+
+ zend_class_entry* registered_ce = desc->klass;
+
if (desc->layout == NULL) {
MessageLayout* layout = create_layout(desc->msgdef);
desc->layout = layout;
}
- // TODO(teboring): Add it back.
- // if (desc->fill_method == NULL) {
- // desc->fill_method = new_fillmsg_decodermethod(desc, &desc->fill_method);
- // }
-
- const char* name = upb_msgdef_fullname(desc->msgdef);
- if (name == NULL) {
- zend_error(E_ERROR, "Descriptor does not have assigned name.");
+
+ registered_ce->create_object = message_create;
+}
+
+// -----------------------------------------------------------------------------
+// PHP Methods
+// -----------------------------------------------------------------------------
+
+PHP_METHOD(Message, readOneof) {
+ long index;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
+ FAILURE) {
+ return;
}
- zend_class_entry class_entry;
- INIT_CLASS_ENTRY_EX(class_entry, name, strlen(name), message_methods);
- zend_class_entry* registered_ce =
- zend_register_internal_class(&class_entry TSRMLS_CC);
+ MessageHeader* msg =
+ (MessageHeader*)zend_object_store_get_object(getThis() TSRMLS_CC);
- add_def_obj(registered_ce, php_descriptor);
+ const upb_fielddef* field = upb_msgdef_itof(msg->descriptor->msgdef, index);
- if (PROTOBUF_G(message_handlers) == NULL) {
- PROTOBUF_G(message_handlers) = ALLOC(zend_object_handlers);
- memcpy(PROTOBUF_G(message_handlers), zend_get_std_object_handlers(),
- sizeof(zend_object_handlers));
- PROTOBUF_G(message_handlers)->write_property = message_set_property;
- PROTOBUF_G(message_handlers)->read_property = message_get_property;
+ int property_cache_index =
+ msg->descriptor->layout->fields[upb_fielddef_index(field)].cache_index;
+ zval** cache_ptr = &(msg->std.properties_table)[property_cache_index];
+
+ layout_get(msg->descriptor->layout, message_data(msg), field,
+ return_value_ptr TSRMLS_CC);
+}
+
+PHP_METHOD(Message, writeOneof) {
+ long index;
+ zval* value;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &index, &value) ==
+ FAILURE) {
+ return;
}
- registered_ce->create_object = message_create;
+ MessageHeader* msg =
+ (MessageHeader*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ const upb_fielddef* field = upb_msgdef_itof(msg->descriptor->msgdef, index);
+
+ layout_set(msg->descriptor->layout, msg, field, value TSRMLS_CC);
}
diff --git a/php/ext/google/protobuf/package.xml b/php/ext/google/protobuf/package.xml
new file mode 100644
index 00000000..83719091
--- /dev/null
+++ b/php/ext/google/protobuf/package.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.9.5" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
+ <name>protobuf</name>
+ <channel>pecl.php.net</channel>
+ <summary>Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data.</summary>
+ <description>https://developers.google.com/protocol-buffers/</description>
+ <lead>
+ <name>Bo Yang</name>
+ <user>teboring</user>
+ <email>protobuf-opensource@google.com</email>
+ <active>yes</active>
+ </lead>
+ <date>2016-09-02</date>
+ <time>16:06:07</time>
+ <version>
+ <release>3.1.0</release>
+ <api>3.1.0</api>
+ </version>
+ <stability>
+ <release>alpha</release>
+ <api>alpha</api>
+ </stability>
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
+ <notes>
+First alpha release.
+ </notes>
+ <contents>
+ <dir baseinstalldir="/" name="/">
+ <file baseinstalldir="/" name="config.m4" role="src" />
+ <file baseinstalldir="/" name="array.c" role="src" />
+ <file baseinstalldir="/" name="def.c" role="src" />
+ <file baseinstalldir="/" name="encode_decode.c" role="src" />
+ <file baseinstalldir="/" name="map.c" role="src" />
+ <file baseinstalldir="/" name="message.c" role="src" />
+ <file baseinstalldir="/" name="protobuf.c" role="src" />
+ <file baseinstalldir="/" name="protobuf.h" role="src" />
+ <file baseinstalldir="/" name="storage.c" role="src" />
+ <file baseinstalldir="/" name="type_check.c" role="src" />
+ <file baseinstalldir="/" name="upb.c" role="src" />
+ <file baseinstalldir="/" name="upb.h" role="src" />
+ <file baseinstalldir="/" name="utf8.c" role="src" />
+ <file baseinstalldir="/" name="utf8.h" role="src" />
+ </dir>
+ </contents>
+ <dependencies>
+ <required>
+ <php>
+ <min>5.6.0</min>
+ </php>
+ <pearinstaller>
+ <min>1.4.0</min>
+ </pearinstaller>
+ </required>
+ </dependencies>
+ <providesextension>protobuf</providesextension>
+ <extsrcrelease />
+ <changelog>
+ <release>
+ <version>
+ <release>3.1.0</release>
+ <api>3.1.0</api>
+ </version>
+ <stability>
+ <release>alpha</release>
+ <api>alpha</api>
+ </stability>
+ <date>2016-09-02</date>
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
+ <notes>
+First alpha release
+ </notes>
+ </release>
+ </changelog>
+</package>
diff --git a/php/ext/google/protobuf/protobuf.c b/php/ext/google/protobuf/protobuf.c
index b1ace8b0..d8ad3c88 100644
--- a/php/ext/google/protobuf/protobuf.c
+++ b/php/ext/google/protobuf/protobuf.c
@@ -1,3 +1,33 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
#include "protobuf.h"
#include <zend_hash.h>
@@ -5,56 +35,81 @@
ZEND_DECLARE_MODULE_GLOBALS(protobuf)
static PHP_GINIT_FUNCTION(protobuf);
static PHP_GSHUTDOWN_FUNCTION(protobuf);
+static PHP_RINIT_FUNCTION(protobuf);
+static PHP_RSHUTDOWN_FUNCTION(protobuf);
+static PHP_MINIT_FUNCTION(protobuf);
+static PHP_MSHUTDOWN_FUNCTION(protobuf);
-// -----------------------------------------------------------------------------
// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
// instances.
+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 maps.
// -----------------------------------------------------------------------------
-void add_def_obj(const void* def, zval* value) {
- uint nIndex = (ulong)def & PROTOBUF_G(upb_def_to_php_obj_map).nTableMask;
+static void add_to_table(HashTable* t, const void* def, void* value) {
+ uint nIndex = (ulong)def & t->nTableMask;
zval* pDest = NULL;
- Z_ADDREF_P(value);
- zend_hash_index_update(&PROTOBUF_G(upb_def_to_php_obj_map), (zend_ulong)def,
- &value, sizeof(zval*), &pDest);
+ zend_hash_index_update(t, (zend_ulong)def, &value, sizeof(zval*), &pDest);
}
-zval* get_def_obj(const void* def) {
- zval** value;
- if (zend_hash_index_find(&PROTOBUF_G(upb_def_to_php_obj_map), (zend_ulong)def,
- &value) == FAILURE) {
+static void* get_from_table(const HashTable* t, const void* def) {
+ void** value;
+ if (zend_hash_index_find(t, (zend_ulong)def, (void**)&value) == FAILURE) {
zend_error(E_ERROR, "PHP object not found for given definition.\n");
return NULL;
}
return *value;
}
+static void add_to_list(HashTable* t, void* value) {
+ zval* pDest = NULL;
+ zend_hash_next_index_insert(t, &value, sizeof(void*), &pDest);
+}
+
+void add_def_obj(const void* def, zval* value) {
+ Z_ADDREF_P(value);
+ add_to_table(upb_def_to_php_obj_map, def, value);
+}
+
+zval* get_def_obj(const void* def) {
+ return (zval*)get_from_table(upb_def_to_php_obj_map, def);
+}
+
+void add_ce_obj(const void* ce, zval* value) {
+ Z_ADDREF_P(value);
+ add_to_table(ce_to_php_obj_map, ce, value);
+}
+
+zval* get_ce_obj(const void* ce) {
+ return (zval*)get_from_table(ce_to_php_obj_map, ce);
+}
+
// -----------------------------------------------------------------------------
// Utilities.
// -----------------------------------------------------------------------------
-// define the function(s) we want to add
zend_function_entry protobuf_functions[] = {
- ZEND_FE(get_generated_pool, NULL)
ZEND_FE_END
};
-// "protobuf_functions" refers to the struct defined above
-// we'll be filling in more of this later: you can use this to specify
-// globals, php.ini info, startup and teardown functions, etc.
zend_module_entry protobuf_module_entry = {
STANDARD_MODULE_HEADER,
- PHP_PROTOBUF_EXTNAME, // extension name
- protobuf_functions, // function list
- PHP_MINIT(protobuf), // process startup
- NULL, // process shutdown
- NULL, // request startup
- NULL, // request shutdown
- NULL, // extension info
+ PHP_PROTOBUF_EXTNAME, // extension name
+ protobuf_functions, // function list
+ PHP_MINIT(protobuf), // process startup
+ PHP_MSHUTDOWN(protobuf), // process shutdown
+ PHP_RINIT(protobuf), // request shutdown
+ PHP_RSHUTDOWN(protobuf), // request shutdown
+ NULL, // extension info
PHP_PROTOBUF_VERSION, // extension version
PHP_MODULE_GLOBALS(protobuf), // globals descriptor
- PHP_GINIT(protobuf), // globals ctor
+ PHP_GINIT(protobuf), // globals ctor
PHP_GSHUTDOWN(protobuf), // globals dtor
NULL, // post deactivate
STANDARD_MODULE_PROPERTIES_EX
@@ -65,25 +120,48 @@ ZEND_GET_MODULE(protobuf)
// global variables
static PHP_GINIT_FUNCTION(protobuf) {
- protobuf_globals->generated_pool = NULL;
- generated_pool = NULL;
- protobuf_globals->message_handlers = NULL;
- zend_hash_init(&protobuf_globals->upb_def_to_php_obj_map, 16, NULL,
- ZVAL_PTR_DTOR, 0);
}
static PHP_GSHUTDOWN_FUNCTION(protobuf) {
- if (protobuf_globals->generated_pool != NULL) {
- FREE_ZVAL(protobuf_globals->generated_pool);
- }
- if (protobuf_globals->message_handlers != NULL) {
- FREE(protobuf_globals->message_handlers);
+}
+
+static PHP_RINIT_FUNCTION(protobuf) {
+ ALLOC_HASHTABLE(upb_def_to_php_obj_map);
+ zend_hash_init(upb_def_to_php_obj_map, 16, NULL, ZVAL_PTR_DTOR, 0);
+
+ ALLOC_HASHTABLE(ce_to_php_obj_map);
+ zend_hash_init(ce_to_php_obj_map, 16, NULL, ZVAL_PTR_DTOR, 0);
+
+ generated_pool = NULL;
+ generated_pool_php = NULL;
+}
+
+static PHP_RSHUTDOWN_FUNCTION(protobuf) {
+ zend_hash_destroy(upb_def_to_php_obj_map);
+ FREE_HASHTABLE(upb_def_to_php_obj_map);
+
+ zend_hash_destroy(ce_to_php_obj_map);
+ FREE_HASHTABLE(ce_to_php_obj_map);
+
+ if (generated_pool_php != NULL) {
+ zval_dtor(generated_pool_php);
+ FREE_ZVAL(generated_pool_php);
}
- zend_hash_destroy(&protobuf_globals->upb_def_to_php_obj_map);
}
-PHP_MINIT_FUNCTION(protobuf) {
+static PHP_MINIT_FUNCTION(protobuf) {
+ map_field_init(TSRMLS_C);
+ repeated_field_init(TSRMLS_C);
+ gpb_type_init(TSRMLS_C);
+ message_init(TSRMLS_C);
descriptor_pool_init(TSRMLS_C);
descriptor_init(TSRMLS_C);
- message_builder_context_init(TSRMLS_C);
+ enum_descriptor_init(TSRMLS_C);
+ util_init(TSRMLS_C);
+}
+
+static PHP_MSHUTDOWN_FUNCTION(protobuf) {
+ PEFREE(message_handlers);
+ PEFREE(repeated_field_handlers);
+ PEFREE(map_field_handlers);
}
diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h
index f9038550..0330f36f 100644
--- a/php/ext/google/protobuf/protobuf.h
+++ b/php/ext/google/protobuf/protobuf.h
@@ -1,46 +1,73 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
#ifndef __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
#define __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
#include <php.h>
+// ubp.h has to be placed after php.h. Othwise, php.h will introduce NDEBUG.
#include "upb.h"
#define PHP_PROTOBUF_EXTNAME "protobuf"
#define PHP_PROTOBUF_VERSION "0.01"
-// Forward decls.
+// -----------------------------------------------------------------------------
+// Forward Declaration
+// ----------------------------------------------------------------------------
+
struct DescriptorPool;
struct Descriptor;
-struct FieldDescriptor;
struct EnumDescriptor;
-struct MessageLayout;
+struct FieldDescriptor;
struct MessageField;
struct MessageHeader;
-struct MessageBuilderContext;
-struct EnumBuilderContext;
+struct MessageLayout;
+struct RepeatedField;
+struct MapField;
typedef struct DescriptorPool DescriptorPool;
typedef struct Descriptor Descriptor;
-typedef struct FieldDescriptor FieldDescriptor;
-typedef struct OneofDescriptor OneofDescriptor;
typedef struct EnumDescriptor EnumDescriptor;
-typedef struct MessageLayout MessageLayout;
+typedef struct FieldDescriptor FieldDescriptor;
typedef struct MessageField MessageField;
typedef struct MessageHeader MessageHeader;
-typedef struct MessageBuilderContext MessageBuilderContext;
-typedef struct OneofBuilderContext OneofBuilderContext;
-typedef struct EnumBuilderContext EnumBuilderContext;
-
-extern zend_class_entry* builder_type;
-extern zend_class_entry* descriptor_type;
-extern zend_class_entry* message_builder_context_type;
+typedef struct MessageLayout MessageLayout;
+typedef struct RepeatedField RepeatedField;
+typedef struct MapField MapField;
-extern DescriptorPool* generated_pool; // The actual generated pool
+// -----------------------------------------------------------------------------
+// Globals.
+// -----------------------------------------------------------------------------
ZEND_BEGIN_MODULE_GLOBALS(protobuf)
- zval* generated_pool;
- zend_object_handlers* message_handlers;
- HashTable upb_def_to_php_obj_map;
ZEND_END_MODULE_GLOBALS(protobuf)
ZEND_DECLARE_MODULE_GLOBALS(protobuf)
@@ -51,14 +78,31 @@ ZEND_DECLARE_MODULE_GLOBALS(protobuf)
#define PROTOBUF_G(v) (protobuf_globals.v)
#endif
-// -----------------------------------------------------------------------------
-// PHP functions and global variables.
-// -----------------------------------------------------------------------------
+// Init module and PHP classes.
+void descriptor_init(TSRMLS_D);
+void enum_descriptor_init(TSRMLS_D);
+void descriptor_pool_init(TSRMLS_D);
+void gpb_type_init(TSRMLS_D);
+void map_field_init(TSRMLS_D);
+void repeated_field_init(TSRMLS_D);
+void util_init(TSRMLS_D);
+void message_init(TSRMLS_D);
+
+// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
+// instances.
+void add_def_obj(const void* def, zval* value);
+zval* get_def_obj(const void* def);
-PHP_MINIT_FUNCTION(protobuf);
+// Global map from PHP class entries to wrapper Descriptor/EnumDescriptor
+// instances.
+void add_ce_obj(const void* ce, zval* value);
+zval* get_ce_obj(const void* ce);
+
+extern zend_class_entry* map_field_type;
+extern zend_class_entry* repeated_field_type;
// -----------------------------------------------------------------------------
-// PHP class structure.
+// Descriptor.
// -----------------------------------------------------------------------------
struct DescriptorPool {
@@ -67,72 +111,112 @@ struct DescriptorPool {
HashTable* pending_list;
};
+PHP_METHOD(DescriptorPool, getGeneratedPool);
+PHP_METHOD(DescriptorPool, internalAddGeneratedFile);
+
+extern zval* generated_pool_php; // wrapper of generated pool
+extern DescriptorPool* generated_pool; // The actual generated pool
+
struct Descriptor {
zend_object std;
const upb_msgdef* msgdef;
MessageLayout* layout;
- // zval* klass; // begins as NULL
- // const upb_handlers* fill_handlers;
- // const upb_pbdecodermethod* fill_method;
+ zend_class_entry* klass; // begins as NULL
+ const upb_handlers* fill_handlers;
+ const upb_pbdecodermethod* fill_method;
const upb_handlers* pb_serialize_handlers;
- // const upb_handlers* json_serialize_handlers;
- // Handlers hold type class references for sub-message fields directly in some
- // cases. We need to keep these rooted because they might otherwise be
- // collected.
- // zval_array typeclass_references;
};
+extern zend_class_entry* descriptor_type;
+
+void descriptor_name_set(Descriptor *desc, const char *name);
+
struct FieldDescriptor {
zend_object std;
const upb_fielddef* fielddef;
};
-struct OneofDescriptor {
- zend_object std;
- const upb_oneofdef* oneofdef;
-};
-
struct EnumDescriptor {
zend_object std;
const upb_enumdef* enumdef;
- // zval* module; // begins as NULL
+ zend_class_entry* klass; // begins as NULL
+ // VALUE module; // begins as nil
};
+extern zend_class_entry* enum_descriptor_type;
+
// -----------------------------------------------------------------------------
-// Native slot storage abstraction.
+// Message class creation.
// -----------------------------------------------------------------------------
-#define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
-
-size_t native_slot_size(upb_fieldtype_t type);
+void* message_data(void* msg);
-#define MAP_KEY_FIELD 1
-#define MAP_VALUE_FIELD 2
+// Build PHP class for given descriptor. Instead of building from scratch, this
+// function modifies existing class which has been partially defined in PHP
+// code.
+void build_class_from_descriptor(zval* php_descriptor TSRMLS_DC);
-// Oneof case slot value to indicate that no oneof case is set. The value `0` is
-// safe because field numbers are used as case identifiers, and no field can
-// have a number of 0.
-#define ONEOF_CASE_NONE 0
-
-// These operate on a map field (i.e., a repeated field of submessages whose
-// submessage type is a map-entry msgdef).
-bool is_map_field(const upb_fielddef* field);
-const upb_fielddef* map_field_key(const upb_fielddef* field);
-const upb_fielddef* map_field_value(const upb_fielddef* field);
-
-// These operate on a map-entry msgdef.
-const upb_fielddef* map_entry_key(const upb_msgdef* msgdef);
-const upb_fielddef* map_entry_value(const upb_msgdef* msgdef);
+extern zend_object_handlers* message_handlers;
// -----------------------------------------------------------------------------
// Message layout / storage.
// -----------------------------------------------------------------------------
+/*
+ * In c extension, each protobuf message is a zval instance. The zval instance
+ * is like union, which can be used to store int, string, zend_object_value and
+ * etc. For protobuf message, the zval instance is used to store the
+ * zend_object_value.
+ *
+ * The zend_object_value is composed of handlers and a handle to look up the
+ * actual stored data. The handlers are pointers to functions, e.g., read,
+ * write, and etc, to access properties.
+ *
+ * The actual data of protobuf messages is stored as MessageHeader in zend
+ * engine's central repository. Each MessageHeader instance is composed of a
+ * zend_object, a Descriptor instance and the real message data.
+ *
+ * For the reason that PHP's native types may not be large enough to store
+ * protobuf message's field (e.g., int64), all message's data is stored in
+ * custom memory layout and is indexed by the Descriptor instance.
+ *
+ * The zend_object contains the zend class entry and the properties table. The
+ * zend class entry contains all information about protobuf message's
+ * corresponding PHP class. The most useful information is the offset table of
+ * properties. Because read access to properties requires returning zval
+ * instance, we need to convert data from the custom layout to zval instance.
+ * Instead of creating zval instance for every read access, we use the zval
+ * instances in the properties table in the zend_object as cache. When
+ * accessing properties, the offset is needed to find the zval property in
+ * zend_object's properties table. These properties will be updated using the
+ * data from custom memory layout only when reading these properties.
+ *
+ * zval
+ * |-zend_object_value obj
+ * |-zend_object_handlers* handlers -> |-read_property_handler
+ * | |-write_property_handler
+ * | ++++++++++++++++++++++
+ * |-zend_object_handle handle -> + central repository +
+ * ++++++++++++++++++++++
+ * MessageHeader <-----------------|
+ * |-zend_object std
+ * | |-class_entry* ce -> class_entry
+ * | | |-HashTable properties_table (name->offset)
+ * | |-zval** properties_table <------------------------------|
+ * | |------> zval* property(cache)
+ * |-Descriptor* desc (name->offset)
+ * |-void** data <-----------|
+ * |-----------------------> void* property(data)
+ *
+ */
+
#define MESSAGE_FIELD_NO_CASE ((size_t)-1)
struct MessageField {
size_t offset;
- size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE.
+ int cache_index; // Each field except oneof field has a zval cache to avoid
+ // multiple creation when being accessed.
+ size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE.
};
struct MessageLayout {
@@ -141,141 +225,230 @@ struct MessageLayout {
size_t size;
};
-void layout_init(MessageLayout* layout, void* storage);
-zval* layout_get(MessageLayout* layout, const void* storage,
- const upb_fielddef* field TSRMLS_DC);
+struct MessageHeader {
+ zend_object std; // Stores properties table and class info of PHP instance.
+ // This is needed for MessageHeader to be accessed via PHP.
+ Descriptor* descriptor; // Kept alive by self.class.descriptor reference.
+ // The real message data is appended after MessageHeader.
+};
+
MessageLayout* create_layout(const upb_msgdef* msgdef);
+void layout_init(MessageLayout* layout, void* storage, zval** properties_table);
+zval* layout_get(MessageLayout* layout, const void* storage,
+ const upb_fielddef* field, zval** cache TSRMLS_DC);
+void layout_set(MessageLayout* layout, MessageHeader* header,
+ const upb_fielddef* field, zval* val);
void free_layout(MessageLayout* layout);
-zval* native_slot_get(upb_fieldtype_t type, /*VALUE type_class,*/
- const void* memory TSRMLS_DC);
+
+PHP_METHOD(Message, readOneof);
+PHP_METHOD(Message, writeOneof);
// -----------------------------------------------------------------------------
-// Message class creation.
+// Encode / Decode.
// -----------------------------------------------------------------------------
-struct MessageHeader {
- zend_object std;
- Descriptor* descriptor; // kept alive by self.class.descriptor reference.
- // Data comes after this.
-};
+// Maximum depth allowed during encoding, to avoid stack overflows due to
+// cycles.
+#define ENCODE_MAX_NESTING 63
-struct MessageBuilderContext {
- zend_object std;
- zval* descriptor;
- zval* pool;
-};
+// Constructs the upb decoder method for parsing messages of this type.
+// This is called from the message class creation code.
+const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor *desc,
+ const void *owner);
+
+PHP_METHOD(Message, encode);
+PHP_METHOD(Message, decode);
+
+// -----------------------------------------------------------------------------
+// Type check / conversion.
+// -----------------------------------------------------------------------------
+
+bool protobuf_convert_to_int32(zval* from, int32_t* to);
+bool protobuf_convert_to_uint32(zval* from, uint32_t* to);
+bool protobuf_convert_to_int64(zval* from, int64_t* to);
+bool protobuf_convert_to_uint64(zval* from, uint64_t* to);
+bool protobuf_convert_to_float(zval* from, float* to);
+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);
+
+PHP_METHOD(Util, checkInt32);
+PHP_METHOD(Util, checkUint32);
+PHP_METHOD(Util, checkInt64);
+PHP_METHOD(Util, checkUint64);
+PHP_METHOD(Util, checkEnum);
+PHP_METHOD(Util, checkFloat);
+PHP_METHOD(Util, checkDouble);
+PHP_METHOD(Util, checkBool);
+PHP_METHOD(Util, checkString);
+PHP_METHOD(Util, checkBytes);
+PHP_METHOD(Util, checkMessage);
+PHP_METHOD(Util, checkRepeatedField);
+
+// -----------------------------------------------------------------------------
+// Native slot storage abstraction.
+// -----------------------------------------------------------------------------
+
+#define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
+
+size_t native_slot_size(upb_fieldtype_t type);
+bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
+ void* memory, zval* value);
+void native_slot_init(upb_fieldtype_t type, void* memory, zval** cache);
+// For each property, in order to avoid conversion between the zval object and
+// the actual data type during parsing/serialization, the containing message
+// object use the custom memory layout to store the actual data type for each
+// property inside of it. To access a property from php code, the property
+// needs to be converted to a zval object. The message object is not responsible
+// for providing such a zval object. Instead the caller needs to provide one
+// (cache) and update it with the actual data (memory).
+void native_slot_get(upb_fieldtype_t type, const void* memory,
+ zval** cache TSRMLS_DC);
+void native_slot_get_default(upb_fieldtype_t type, zval** cache TSRMLS_DC);
+
+// -----------------------------------------------------------------------------
+// Map Field.
+// -----------------------------------------------------------------------------
-struct OneofBuilderContext {
+extern zend_object_handlers* map_field_handlers;
+
+typedef struct {
zend_object std;
- // VALUE descriptor;
- // VALUE builder;
-};
+ upb_fieldtype_t key_type;
+ upb_fieldtype_t value_type;
+ const zend_class_entry* msg_ce; // class entry for value message
+ upb_strtable table;
+} Map;
+
+typedef struct {
+ Map* self;
+ upb_strtable_iter it;
+} MapIter;
+
+void map_begin(zval* self, MapIter* iter);
+void map_next(MapIter* iter);
+bool map_done(MapIter* iter);
+const char* map_iter_key(MapIter* iter, int* len);
+upb_value map_iter_value(MapIter* iter, int* len);
+
+// These operate on a map-entry msgdef.
+const upb_fielddef* map_entry_key(const upb_msgdef* msgdef);
+const upb_fielddef* map_entry_value(const upb_msgdef* msgdef);
-struct EnumBuilderContext {
+zend_object_value map_field_create(zend_class_entry *ce TSRMLS_DC);
+void map_field_create_with_type(zend_class_entry *ce, const upb_fielddef *field,
+ zval **map_field TSRMLS_DC);
+void map_field_free(void* object TSRMLS_DC);
+void* upb_value_memory(upb_value* v);
+
+#define MAP_KEY_FIELD 1
+#define MAP_VALUE_FIELD 2
+
+// These operate on a map field (i.e., a repeated field of submessages whose
+// submessage type is a map-entry msgdef).
+const upb_fielddef* map_field_key(const upb_fielddef* field);
+const upb_fielddef* map_field_value(const upb_fielddef* field);
+
+bool map_index_set(Map *intern, const char* keyval, int length, upb_value v);
+
+PHP_METHOD(MapField, __construct);
+PHP_METHOD(MapField, offsetExists);
+PHP_METHOD(MapField, offsetGet);
+PHP_METHOD(MapField, offsetSet);
+PHP_METHOD(MapField, offsetUnset);
+PHP_METHOD(MapField, count);
+
+// -----------------------------------------------------------------------------
+// Repeated Field.
+// -----------------------------------------------------------------------------
+
+extern zend_object_handlers* repeated_field_handlers;
+
+struct RepeatedField {
zend_object std;
- // VALUE enumdesc;
+ zval* array;
+ upb_fieldtype_t type;
+ const zend_class_entry* msg_ce; // class entry for containing message
+ // (for message field only).
};
-// Forward-declare all of the PHP method implementations.
-
-DescriptorPool* php_to_descriptor_pool(zval* value TSRMLS_DC);
-zend_object_value descriptor_pool_create(zend_class_entry *ce TSRMLS_DC);
-void descriptor_pool_free_c(DescriptorPool* object TSRMLS_DC);
-void descriptor_pool_free(void* object TSRMLS_DC);
-void descriptor_pool_init_c_instance(DescriptorPool* pool TSRMLS_DC);
-PHP_METHOD(DescriptorPool, addMessage);
-PHP_METHOD(DescriptorPool, finalize);
-
-Descriptor* php_to_descriptor(zval* value TSRMLS_DC);
-zend_object_value descriptor_create(zend_class_entry *ce TSRMLS_DC);
-void descriptor_init_c_instance(Descriptor* intern TSRMLS_DC);
-void descriptor_free_c(Descriptor* object TSRMLS_DC);
-void descriptor_free(void* object TSRMLS_DC);
-void descriptor_name_set(Descriptor *desc, const char *name);
+void repeated_field_create_with_type(zend_class_entry* ce,
+ const upb_fielddef* field,
+ zval** repeated_field TSRMLS_DC);
+// Return the element at the index position from the repeated field. There is
+// not restriction on the type of stored elements.
+void *repeated_field_index_native(RepeatedField *intern, int index);
+// Add the element to the end of the repeated field. There is not restriction on
+// the type of stored elements.
+void repeated_field_push_native(RepeatedField *intern, void *value);
+
+PHP_METHOD(RepeatedField, __construct);
+PHP_METHOD(RepeatedField, append);
+PHP_METHOD(RepeatedField, offsetExists);
+PHP_METHOD(RepeatedField, offsetGet);
+PHP_METHOD(RepeatedField, offsetSet);
+PHP_METHOD(RepeatedField, offsetUnset);
+PHP_METHOD(RepeatedField, count);
-MessageBuilderContext* php_to_message_builder_context(zval* value TSRMLS_DC);
-zend_object_value message_builder_context_create(
- zend_class_entry* ce TSRMLS_DC);
-void message_builder_context_init_c_instance(
- MessageBuilderContext* intern TSRMLS_DC);
-void message_builder_context_free_c(MessageBuilderContext* object TSRMLS_DC);
-void message_builder_context_free(void* object TSRMLS_DC);
-PHP_METHOD(MessageBuilderContext, optional);
-PHP_METHOD(MessageBuilderContext, finalizeToPool);
+// -----------------------------------------------------------------------------
+// Oneof Field.
+// -----------------------------------------------------------------------------
-PHP_METHOD(Message, encode);
-const zend_class_entry* build_class_from_descriptor(
- zval* php_descriptor TSRMLS_DC);
+typedef struct {
+ zend_object std;
+ upb_oneofdef* oneofdef;
+ int index; // Index of field in oneof. -1 if not set.
+ char value[NATIVE_SLOT_MAX_SIZE];
+} Oneof;
-PHP_FUNCTION(get_generated_pool);
+// Oneof case slot value to indicate that no oneof case is set. The value `0` is
+// safe because field numbers are used as case identifiers, and no field can
+// have a number of 0.
+#define ONEOF_CASE_NONE 0
// -----------------------------------------------------------------------------
-// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
-// instances.
-// ----------------------------------------------------------------------------
+// Upb.
+// -----------------------------------------------------------------------------
-void add_def_obj(const void* def, zval* value);
-zval* get_def_obj(const void* def);
+upb_fieldtype_t to_fieldtype(upb_descriptortype_t type);
+const zend_class_entry *field_type_class(const upb_fielddef *field);
// -----------------------------------------------------------------------------
// Utilities.
// -----------------------------------------------------------------------------
-// PHP Array utils.
-#define Z_ARRVAL_SIZE_P(zval_p) zend_hash_num_elements(Z_ARRVAL_P(zval_p))
-#define Z_ARRVAL_BEGIN_P(zval_p) Z_ARRVAL_P(zval_p)->pListHead
-#define Z_BUCKET_NEXT_PP(bucket_pp) *bucket_pp = (*bucket_pp)->pListNext
-
-#define DEFINE_PHP_OBJECT(class_name, class_name_lower, name) \
- do { \
- zval* name; \
- MAKE_STD_ZVAL(name); \
- object_init_ex(name, class_name_lower##_type); \
- } while (0)
-
-#define DEFINE_PHP_WRAPPER(class_name, class_name_lower, name, intern) \
- zval* name; \
- MAKE_STD_ZVAL(name); \
- object_init_ex(name, class_name_lower##_type); \
- Z_OBJVAL_P(name) \
- .handle = zend_objects_store_put( \
- intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, \
- class_name_lower##_free, NULL TSRMLS_CC);
-
-#define DEFINE_PHP_ZVAL(name) \
- do { \
- zval* name; \
- MAKE_STD_ZVAL(name); \
- } while (0)
-
-#define DEFINE_PHP_STRING(name, value) \
- do { \
- zval* name; \
- MAKE_STD_ZVAL(name); \
- ZVAL_STRING(name, value, 1); \
- } while (0)
-
-// Upb Utilities
-
-void check_upb_status(const upb_status* status, const char* msg);
-
-#define CHECK_UPB(code, msg) \
- do { \
- upb_status status = UPB_STATUS_INIT; \
- code; \
- check_upb_status(&status, msg); \
- } while (0)
+// PHP <-> C conversion.
+#define UNBOX(class_name, val) \
+ (class_name*)zend_object_store_get_object(val TSRMLS_CC);
-// Memory management
+#define BOX(class_name, wrapper, intern, free_func) \
+ MAKE_STD_ZVAL(wrapper); \
+ Z_TYPE_P(wrapper) = IS_OBJECT; \
+ Z_OBJVAL_P(wrapper) \
+ .handle = \
+ zend_objects_store_put(intern, NULL, free_func, NULL TSRMLS_CC); \
+ Z_OBJVAL_P(wrapper).handlers = zend_get_std_object_handlers();
+// Memory management
#define ALLOC(class_name) (class_name*) emalloc(sizeof(class_name))
+#define PEMALLOC(class_name) (class_name*) pemalloc(sizeof(class_name), 1)
#define ALLOC_N(class_name, n) (class_name*) emalloc(sizeof(class_name) * n)
#define FREE(object) efree(object)
-
-// Type Checking
-#define CHECK_TYPE(field, type) \
- if (Z_TYPE_P(field) != type) { \
- zend_error(E_ERROR, "Unexpected type"); \
- }
+#define PEFREE(object) pefree(object, 1)
+
+// Create PHP internal instance.
+#define CREATE(class_name, intern, init_func) \
+ intern = ALLOC(class_name); \
+ memset(intern, 0, sizeof(class_name)); \
+ init_func(intern TSRMLS_CC);
+
+// String argument.
+#define STR(str) (str), strlen(str)
+
+// Zend Value
+#define Z_OBJ_P(zval_p) \
+ ((zend_object*)(EG(objects_store) \
+ .object_buckets[Z_OBJ_HANDLE_P(zval_p)] \
+ .bucket.obj.object))
#endif // __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
diff --git a/php/ext/google/protobuf/storage.c b/php/ext/google/protobuf/storage.c
index e5a09c17..7423552b 100644
--- a/php/ext/google/protobuf/storage.c
+++ b/php/ext/google/protobuf/storage.c
@@ -1,19 +1,41 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
#include <stdint.h>
#include <protobuf.h>
+#include <Zend/zend.h>
// -----------------------------------------------------------------------------
-// PHP <-> native slot management.
+// Native slot storage.
// -----------------------------------------------------------------------------
-static zval* int32_to_zval(int32_t value) {
- zval* tmp;
- MAKE_STD_ZVAL(tmp);
- ZVAL_LONG(tmp, value);
- php_printf("int32 to zval\n");
- // ZVAL_LONG(tmp, 1);
- return tmp;
-}
-
#define DEREF(memory, type) *(type*)(memory)
size_t native_slot_size(upb_fieldtype_t type) {
@@ -21,9 +43,9 @@ size_t native_slot_size(upb_fieldtype_t type) {
case UPB_TYPE_FLOAT: return 4;
case UPB_TYPE_DOUBLE: return 8;
case UPB_TYPE_BOOL: return 1;
- case UPB_TYPE_STRING: return sizeof(zval*);
- case UPB_TYPE_BYTES: return sizeof(zval*);
- case UPB_TYPE_MESSAGE: return sizeof(zval*);
+ case UPB_TYPE_STRING: return sizeof(void*);
+ case UPB_TYPE_BYTES: return sizeof(void*);
+ case UPB_TYPE_MESSAGE: return sizeof(void*);
case UPB_TYPE_ENUM: return 4;
case UPB_TYPE_INT32: return 4;
case UPB_TYPE_INT64: return 8;
@@ -33,72 +55,77 @@ size_t native_slot_size(upb_fieldtype_t type) {
}
}
-static bool is_php_num(zval* value) {
- // Is numerial string also valid?
- return (Z_TYPE_P(value) == IS_LONG ||
- Z_TYPE_P(value) == IS_DOUBLE);
-}
+bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
+ void* memory, zval* value) {
+ switch (type) {
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES: {
+ if (!protobuf_convert_to_string(value)) {
+ return false;
+ }
+ if (type == UPB_TYPE_STRING &&
+ !is_structurally_valid_utf8(Z_STRVAL_P(value), Z_STRLEN_P(value))) {
+ zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
+ return false;
+ }
+ if (*(zval**)memory != NULL) {
+ REPLACE_ZVAL_VALUE((zval**)memory, value, 1);
+ } else {
+ // Handles repeated/map string field. Memory provided by
+ // RepeatedField/Map is not initialized.
+ MAKE_STD_ZVAL(DEREF(memory, zval*));
+ ZVAL_STRINGL(DEREF(memory, zval*), Z_STRVAL_P(value), Z_STRLEN_P(value),
+ 1);
+ }
+ break;
+ }
+ case UPB_TYPE_MESSAGE: {
+ if (Z_TYPE_P(value) != IS_OBJECT && Z_TYPE_P(value) != IS_NULL) {
+ zend_error(E_USER_ERROR, "Given value is not message.");
+ return false;
+ }
+ if (Z_TYPE_P(value) == IS_OBJECT && klass != Z_OBJCE_P(value)) {
+ zend_error(E_USER_ERROR, "Given message does not have correct class.");
+ return false;
+ }
+ if (EXPECTED(DEREF(memory, zval*) != value)) {
+ if (DEREF(memory, zval*) != NULL) {
+ zval_ptr_dtor((zval**)memory);
+ }
+ DEREF(memory, zval*) = value;
+ Z_ADDREF_P(value);
+ }
+ break;
+ }
-void native_slot_check_int_range_precision(upb_fieldtype_t type, zval* val) {
- // TODO(teboring): Add it back.
- // if (!is_php_num(val)) {
- // zend_error(E_ERROR, "Expected number type for integral field.");
- // }
-
- // if (Z_TYPE_P(val) == IS_DOUBLE) {
- // double dbl_val = NUM2DBL(val);
- // if (floor(dbl_val) != dbl_val) {
- // zend_error(E_ERROR,
- // "Non-integral floating point value assigned to integer field.");
- // }
- // }
- // if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
- // if (NUM2DBL(val) < 0) {
- // zend_error(E_ERROR,
- // "Assigning negative value to unsigned integer field.");
- // }
- // }
-}
+#define CASE_TYPE(upb_type, type, c_type, php_type) \
+ case UPB_TYPE_##upb_type: { \
+ c_type type##_value; \
+ if (protobuf_convert_to_##type(value, &type##_value)) { \
+ DEREF(memory, c_type) = type##_value; \
+ } \
+ break; \
+ }
+ CASE_TYPE(INT32, int32, int32_t, LONG)
+ CASE_TYPE(UINT32, uint32, uint32_t, LONG)
+ CASE_TYPE(ENUM, int32, int32_t, LONG)
+ CASE_TYPE(INT64, int64, int64_t, LONG)
+ CASE_TYPE(UINT64, uint64, uint64_t, LONG)
+ CASE_TYPE(FLOAT, float, float, DOUBLE)
+ CASE_TYPE(DOUBLE, double, double, DOUBLE)
+ CASE_TYPE(BOOL, bool, int8_t, BOOL)
+
+#undef CASE_TYPE
-zval* native_slot_get(upb_fieldtype_t type, /*VALUE type_class,*/
- const void* memory TSRMLS_DC) {
- zval* retval = NULL;
- switch (type) {
- // TODO(teboring): Add it back.
- // case UPB_TYPE_FLOAT:
- // return DBL2NUM(DEREF(memory, float));
- // case UPB_TYPE_DOUBLE:
- // return DBL2NUM(DEREF(memory, double));
- // case UPB_TYPE_BOOL:
- // return DEREF(memory, int8_t) ? Qtrue : Qfalse;
- // case UPB_TYPE_STRING:
- // case UPB_TYPE_BYTES:
- // case UPB_TYPE_MESSAGE:
- // return DEREF(memory, VALUE);
- // case UPB_TYPE_ENUM: {
- // int32_t val = DEREF(memory, int32_t);
- // VALUE symbol = enum_lookup(type_class, INT2NUM(val));
- // if (symbol == Qnil) {
- // return INT2NUM(val);
- // } else {
- // return symbol;
- // }
- // }
- case UPB_TYPE_INT32:
- return int32_to_zval(DEREF(memory, int32_t));
- // TODO(teboring): Add it back.
- // case UPB_TYPE_INT64:
- // return LL2NUM(DEREF(memory, int64_t));
- // case UPB_TYPE_UINT32:
- // return UINT2NUM(DEREF(memory, uint32_t));
- // case UPB_TYPE_UINT64:
- // return ULL2NUM(DEREF(memory, uint64_t));
default:
- return EG(uninitialized_zval_ptr);
+ break;
}
+
+ return true;
}
-void native_slot_init(upb_fieldtype_t type, void* memory) {
+void native_slot_init(upb_fieldtype_t type, void* memory, zval** cache) {
+ zval* tmp = NULL;
switch (type) {
case UPB_TYPE_FLOAT:
DEREF(memory, float) = 0.0;
@@ -109,17 +136,11 @@ void native_slot_init(upb_fieldtype_t type, void* memory) {
case UPB_TYPE_BOOL:
DEREF(memory, int8_t) = 0;
break;
- // TODO(teboring): Add it back.
- // case UPB_TYPE_STRING:
- // case UPB_TYPE_BYTES:
- // DEREF(memory, VALUE) = php_str_new2("");
- // php_enc_associate(DEREF(memory, VALUE), (type == UPB_TYPE_BYTES)
- // ? kRubyString8bitEncoding
- // : kRubyStringUtf8Encoding);
- // break;
- // case UPB_TYPE_MESSAGE:
- // DEREF(memory, VALUE) = Qnil;
- // break;
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_MESSAGE:
+ DEREF(memory, zval**) = cache;
+ break;
case UPB_TYPE_ENUM:
case UPB_TYPE_INT32:
DEREF(memory, int32_t) = 0;
@@ -138,122 +159,93 @@ void native_slot_init(upb_fieldtype_t type, void* memory) {
}
}
-void native_slot_set(upb_fieldtype_t type, /*VALUE type_class,*/ void* memory,
- zval* value) {
- native_slot_set_value_and_case(type, /*type_class,*/ memory, value, NULL, 0);
-}
-
-void native_slot_set_value_and_case(upb_fieldtype_t type, /*VALUE type_class,*/
- void* memory, zval* value,
- uint32_t* case_memory,
- uint32_t case_number) {
+void native_slot_get(upb_fieldtype_t type, const void* memory,
+ zval** cache TSRMLS_DC) {
switch (type) {
- case UPB_TYPE_FLOAT:
- if (!Z_TYPE_P(value) == IS_LONG) {
- zend_error(E_ERROR, "Expected number type for float field.");
+#define CASE(upb_type, php_type, c_type) \
+ case UPB_TYPE_##upb_type: \
+ SEPARATE_ZVAL_IF_NOT_REF(cache); \
+ ZVAL_##php_type(*cache, DEREF(memory, c_type)); \
+ return;
+
+CASE(FLOAT, DOUBLE, float)
+CASE(DOUBLE, DOUBLE, double)
+CASE(BOOL, BOOL, int8_t)
+CASE(INT32, LONG, int32_t)
+CASE(INT64, LONG, int64_t)
+CASE(UINT64, LONG, uint64_t)
+CASE(ENUM, LONG, uint32_t)
+
+#undef CASE
+ case UPB_TYPE_UINT32: {
+ // Prepend bit-1 for negative numbers, so that uint32 value will be
+ // consistent on both 32-bit and 64-bit architectures.
+ SEPARATE_ZVAL_IF_NOT_REF(cache);
+ int value = DEREF(memory, int32_t);
+ if (sizeof(int) == 8) {
+ value |= (-((value >> 31) & 0x1) & 0xFFFFFFFF00000000);
}
- DEREF(memory, float) = Z_DVAL_P(value);
- break;
- case UPB_TYPE_DOUBLE:
- // TODO(teboring): Add it back.
- // if (!is_php_num(value)) {
- // zend_error(E_ERROR, "Expected number type for double field.");
- // }
- // DEREF(memory, double) = Z_DVAL_P(value);
- break;
- case UPB_TYPE_BOOL: {
- int8_t val = -1;
- if (zval_is_true(value)) {
- val = 1;
- } else {
- val = 0;
- }
- // TODO(teboring): Add it back.
- // else if (value == Qfalse) {
- // val = 0;
- // }
- // else {
- // php_raise(php_eTypeError, "Invalid argument for boolean field.");
- // }
- DEREF(memory, int8_t) = val;
- break;
+ ZVAL_LONG(*cache, value);
+ return;
}
+
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES: {
- // TODO(teboring): Add it back.
- // if (Z_TYPE_P(value) != IS_STRING) {
- // zend_error(E_ERROR, "Invalid argument for string field.");
- // }
- // native_slot_validate_string_encoding(type, value);
- // DEREF(memory, zval*) = value;
+ // For optional string/bytes fields, the cache is owned by the containing
+ // message and should have been updated during setting/decoding. However,
+ // for repeated string/bytes fields, the cache is provided by zend engine
+ // and has not been updated.
+ zval* value = DEREF(memory, zval*);
+ if (*cache != value) {
+ ZVAL_STRINGL(*cache, Z_STRVAL_P(value), Z_STRLEN_P(value), 1);
+ }
break;
}
case UPB_TYPE_MESSAGE: {
- // TODO(teboring): Add it back.
- // if (CLASS_OF(value) == CLASS_OF(Qnil)) {
- // value = Qnil;
- // } else if (CLASS_OF(value) != type_class) {
- // php_raise(php_eTypeError,
- // "Invalid type %s to assign to submessage field.",
- // php_class2name(CLASS_OF(value)));
- // }
- // DEREF(memory, VALUE) = value;
- break;
- }
- case UPB_TYPE_ENUM: {
- // TODO(teboring): Add it back.
- // int32_t int_val = 0;
- // if (!is_php_num(value) && TYPE(value) != T_SYMBOL) {
- // php_raise(php_eTypeError,
- // "Expected number or symbol type for enum field.");
- // }
- // if (TYPE(value) == T_SYMBOL) {
- // // Ensure that the given symbol exists in the enum module.
- // VALUE lookup = php_funcall(type_class, php_intern("resolve"), 1, value);
- // if (lookup == Qnil) {
- // php_raise(php_eRangeError, "Unknown symbol value for enum field.");
- // } else {
- // int_val = NUM2INT(lookup);
- // }
- // } else {
- // native_slot_check_int_range_precision(UPB_TYPE_INT32, value);
- // int_val = NUM2INT(value);
- // }
- // DEREF(memory, int32_t) = int_val;
- // break;
- }
- case UPB_TYPE_INT32:
- case UPB_TYPE_INT64:
- case UPB_TYPE_UINT32:
- case UPB_TYPE_UINT64:
- native_slot_check_int_range_precision(type, value);
- switch (type) {
- case UPB_TYPE_INT32:
- php_printf("Setting INT32 field\n");
- DEREF(memory, int32_t) = Z_LVAL_P(value);
- break;
- case UPB_TYPE_INT64:
- // TODO(teboring): Add it back.
- // DEREF(memory, int64_t) = NUM2LL(value);
- break;
- case UPB_TYPE_UINT32:
- // TODO(teboring): Add it back.
- // DEREF(memory, uint32_t) = NUM2UINT(value);
- break;
- case UPB_TYPE_UINT64:
- // TODO(teboring): Add it back.
- // DEREF(memory, uint64_t) = NUM2ULL(value);
- break;
- default:
- break;
+ // Same as above for string/bytes fields.
+ zval* value = DEREF(memory, zval*);
+ if (*cache != value) {
+ ZVAL_ZVAL(*cache, value, 1, 0);
}
- break;
+ return;
+ }
default:
- break;
+ return EG(uninitialized_zval_ptr);
}
+}
- if (case_memory != NULL) {
- *case_memory = case_number;
+void native_slot_get_default(upb_fieldtype_t type, zval** cache TSRMLS_DC) {
+ switch (type) {
+#define CASE(upb_type, php_type) \
+ case UPB_TYPE_##upb_type: \
+ SEPARATE_ZVAL_IF_NOT_REF(cache); \
+ ZVAL_##php_type(*cache, 0); \
+ return;
+
+ CASE(FLOAT, DOUBLE)
+ CASE(DOUBLE, DOUBLE)
+ CASE(BOOL, BOOL)
+ CASE(INT32, LONG)
+ CASE(INT64, LONG)
+ CASE(UINT32, LONG)
+ CASE(UINT64, LONG)
+ CASE(ENUM, LONG)
+
+#undef CASE
+
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES: {
+ SEPARATE_ZVAL_IF_NOT_REF(cache);
+ ZVAL_STRINGL(*cache, "", 0, 1);
+ break;
+ }
+ case UPB_TYPE_MESSAGE: {
+ SEPARATE_ZVAL_IF_NOT_REF(cache);
+ ZVAL_NULL(*cache);
+ return;
+ }
+ default:
+ return EG(uninitialized_zval_ptr);
}
}
@@ -281,6 +273,40 @@ bool is_map_field(const upb_fielddef* field) {
return tryget_map_entry_msgdef(field) != NULL;
}
+const upb_fielddef* map_field_key(const upb_fielddef* field) {
+ const upb_msgdef* subdef = map_entry_msgdef(field);
+ return map_entry_key(subdef);
+}
+
+const upb_fielddef* map_field_value(const upb_fielddef* field) {
+ const upb_msgdef* subdef = map_entry_msgdef(field);
+ return map_entry_value(subdef);
+}
+
+const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) {
+ const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD);
+ assert(key_field != NULL);
+ return key_field;
+}
+
+const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
+ const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD);
+ assert(value_field != NULL);
+ return value_field;
+}
+
+const zend_class_entry* field_type_class(const upb_fielddef* field) {
+ if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
+ zval* desc_php = get_def_obj(upb_fielddef_subdef(field));
+ Descriptor* desc = zend_object_store_get_object(desc_php TSRMLS_CC);
+ return desc->klass;
+ } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
+ zval* desc_php = get_def_obj(upb_fielddef_subdef(field));
+ EnumDescriptor* desc = zend_object_store_get_object(desc_php TSRMLS_CC);
+ return desc->klass;
+ }
+}
+
// -----------------------------------------------------------------------------
// Memory layout management.
// -----------------------------------------------------------------------------
@@ -290,12 +316,29 @@ 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) +
+ layout->fields[upb_fielddef_index(field)].case_offset);
+}
+
+static int slot_property_cache(MessageLayout* layout, const void* storage,
+ const upb_fielddef* field) {
+ return layout->fields[upb_fielddef_index(field)].cache_index;
+}
+
MessageLayout* create_layout(const upb_msgdef* msgdef) {
MessageLayout* layout = ALLOC(MessageLayout);
int nfields = upb_msgdef_numfields(msgdef);
upb_msg_field_iter it;
upb_msg_oneof_iter oit;
size_t off = 0;
+ int i = 0;
layout->fields = ALLOC_N(MessageField, nfields);
@@ -322,6 +365,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
layout->fields[upb_fielddef_index(field)].offset = off;
layout->fields[upb_fielddef_index(field)].case_offset =
MESSAGE_FIELD_NO_CASE;
+ layout->fields[upb_fielddef_index(field)].cache_index = i++;
off += field_size;
}
@@ -353,11 +397,13 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
upb_oneof_next(&fit)) {
const upb_fielddef* field = upb_oneof_iter_field(&fit);
layout->fields[upb_fielddef_index(field)].offset = off;
+ layout->fields[upb_fielddef_index(field)].cache_index = i;
}
+ i++;
off += field_size;
}
- // Now the case fields.
+ // Now the case offset.
for (upb_msg_oneof_begin(&oit, msgdef); !upb_msg_oneof_done(&oit);
upb_msg_oneof_next(&oit)) {
const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
@@ -389,151 +435,125 @@ void free_layout(MessageLayout* layout) {
FREE(layout);
}
-// TODO(teboring): Add it back.
-// VALUE field_type_class(const upb_fielddef* field) {
-// VALUE type_class = Qnil;
-// if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
-// VALUE submsgdesc = get_def_obj(upb_fielddef_subdef(field));
-// type_class = Descriptor_msgclass(submsgdesc);
-// } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
-// VALUE subenumdesc = get_def_obj(upb_fielddef_subdef(field));
-// type_class = EnumDescriptor_enummodule(subenumdesc);
-// }
-// return type_class;
-// }
+void layout_init(MessageLayout* layout, void* storage, zval** properties_table) {
+ int i;
+ upb_msg_field_iter it;
+ 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);
+ void* memory = slot_memory(layout, storage, field);
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
+ int cache_index = slot_property_cache(layout, storage, field);
+ zval** property_ptr = &properties_table[cache_index];
-static void* slot_memory(MessageLayout* layout, const void* storage,
- const upb_fielddef* field) {
- return ((uint8_t*)storage) + layout->fields[upb_fielddef_index(field)].offset;
+ if (upb_fielddef_containingoneof(field)) {
+ memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
+ *oneof_case = ONEOF_CASE_NONE;
+ } else if (is_map_field(field)) {
+ zval_ptr_dtor(property_ptr);
+ map_field_create_with_type(map_field_type, field, property_ptr);
+ DEREF(memory, zval**) = property_ptr;
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+ zval_ptr_dtor(property_ptr);
+ repeated_field_create_with_type(repeated_field_type, field, property_ptr);
+ DEREF(memory, zval**) = property_ptr;
+ } else {
+ native_slot_init(upb_fielddef_type(field), memory, property_ptr);
+ }
+ }
}
-static uint32_t* slot_oneof_case(MessageLayout* layout, const void* storage,
- const upb_fielddef* field) {
- return (uint32_t*)(((uint8_t*)storage) +
- layout->fields[upb_fielddef_index(field)].case_offset);
+// For non-singular fields, the related memory needs to point to the actual
+// zval in properties table first.
+static void* value_memory(const upb_fielddef* field, void* memory) {
+ switch (upb_fielddef_type(field)) {
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_MESSAGE:
+ memory = DEREF(memory, zval**);
+ break;
+ default:
+ // No operation
+ break;
+ }
+ return memory;
}
-void layout_set(MessageLayout* layout, void* storage, const upb_fielddef* field,
- zval* val) {
+zval* layout_get(MessageLayout* layout, const void* storage,
+ const upb_fielddef* field, zval** cache TSRMLS_DC) {
void* memory = slot_memory(layout, storage, field);
uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
if (upb_fielddef_containingoneof(field)) {
- if (Z_TYPE_P(val) == IS_NULL) {
- // Assigning nil to a oneof field clears the oneof completely.
- *oneof_case = ONEOF_CASE_NONE;
- memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
+ if (*oneof_case != upb_fielddef_number(field)) {
+ native_slot_get_default(upb_fielddef_type(field), cache TSRMLS_CC);
} else {
- // The transition between field types for a single oneof (union) slot is
- // somewhat complex because we need to ensure that a GC triggered at any
- // point by a call into the Ruby VM sees a valid state for this field and
- // does not either go off into the weeds (following what it thinks is a
- // VALUE but is actually a different field type) or miss an object (seeing
- // what it thinks is a primitive field but is actually a VALUE for the new
- // field type).
- //
- // In order for the transition to be safe, the oneof case slot must be in
- // sync with the value slot whenever the Ruby VM has been called. Thus, we
- // use native_slot_set_value_and_case(), which ensures that both the value
- // and case number are altered atomically (w.r.t. the Ruby VM).
- native_slot_set_value_and_case(upb_fielddef_type(field),
- /*field_type_class(field),*/ memory, val,
- oneof_case, upb_fielddef_number(field));
+ native_slot_get(upb_fielddef_type(field), value_memory(field, memory),
+ cache TSRMLS_CC);
}
- } else if (is_map_field(field)) {
- // TODO(teboring): Add it back.
- // check_map_field_type(val, field);
- // DEREF(memory, zval*) = val;
+ return *cache;
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
- // TODO(teboring): Add it back.
- // check_repeated_field_type(val, field);
- // DEREF(memory, zval*) = val;
+ return *cache;
} else {
- native_slot_set(upb_fielddef_type(field), /*field_type_class(field),*/ memory,
- val);
- }
-}
-
-void layout_init(MessageLayout* layout, void* storage) {
- upb_msg_field_iter it;
- for (upb_msg_field_begin(&it, layout->msgdef); !upb_msg_field_done(&it);
- upb_msg_field_next(&it)) {
- const upb_fielddef* field = upb_msg_iter_field(&it);
- void* memory = slot_memory(layout, storage, field);
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
-
- if (upb_fielddef_containingoneof(field)) {
- // TODO(teboring): Add it back.
- // memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
- // *oneof_case = ONEOF_CASE_NONE;
- } else if (is_map_field(field)) {
- // TODO(teboring): Add it back.
- // VALUE map = Qnil;
-
- // const upb_fielddef* key_field = map_field_key(field);
- // const upb_fielddef* value_field = map_field_value(field);
- // VALUE type_class = field_type_class(value_field);
-
- // if (type_class != Qnil) {
- // VALUE args[3] = {
- // fieldtype_to_php(upb_fielddef_type(key_field)),
- // fieldtype_to_php(upb_fielddef_type(value_field)), type_class,
- // };
- // map = php_class_new_instance(3, args, cMap);
- // } else {
- // VALUE args[2] = {
- // fieldtype_to_php(upb_fielddef_type(key_field)),
- // fieldtype_to_php(upb_fielddef_type(value_field)),
- // };
- // map = php_class_new_instance(2, args, cMap);
- // }
-
- // DEREF(memory, VALUE) = map;
- } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
- // TODO(teboring): Add it back.
- // VALUE ary = Qnil;
-
- // VALUE type_class = field_type_class(field);
-
- // if (type_class != Qnil) {
- // VALUE args[2] = {
- // fieldtype_to_php(upb_fielddef_type(field)), type_class,
- // };
- // ary = php_class_new_instance(2, args, cRepeatedField);
- // } else {
- // VALUE args[1] = {fieldtype_to_php(upb_fielddef_type(field))};
- // ary = php_class_new_instance(1, args, cRepeatedField);
- // }
-
- // DEREF(memory, VALUE) = ary;
- } else {
- native_slot_init(upb_fielddef_type(field), memory);
- }
+ native_slot_get(upb_fielddef_type(field), value_memory(field, memory),
+ cache TSRMLS_CC);
+ return *cache;
}
}
-zval* layout_get(MessageLayout* layout, const void* storage,
- const upb_fielddef* field TSRMLS_DC) {
+void layout_set(MessageLayout* layout, MessageHeader* header, const upb_fielddef* field,
+ zval* val) {
+ void* storage = message_data(header);
void* memory = slot_memory(layout, storage, field);
uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
if (upb_fielddef_containingoneof(field)) {
- if (*oneof_case != upb_fielddef_number(field)) {
- return NULL;
- // TODO(teboring): Add it back.
- // return Qnil;
+ upb_fieldtype_t type = upb_fielddef_type(field);
+ zend_class_entry *ce = NULL;
+
+ // For non-singular fields, the related memory needs to point to the actual
+ // zval in properties table first.
+ switch (type) {
+ case UPB_TYPE_MESSAGE: {
+ upb_msgdef* msg = upb_fielddef_msgsubdef(field);
+ zval* desc_php = get_def_obj(msg);
+ Descriptor* desc = zend_object_store_get_object(desc_php TSRMLS_CC);
+ ce = desc->klass;
+ // Intentionally fall through.
+ }
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES: {
+ int property_cache_index =
+ header->descriptor->layout->fields[upb_fielddef_index(field)]
+ .cache_index;
+ DEREF(memory, zval**) =
+ &(header->std.properties_table)[property_cache_index];
+ memory = DEREF(memory, zval**);
+ break;
+ }
+ default:
+ break;
}
- return NULL;
- // TODO(teboring): Add it back.
- // return native_slot_get(upb_fielddef_type(field), field_type_class(field),
- // memory);
+
+ native_slot_set(type, ce, memory, val);
+ *oneof_case = upb_fielddef_number(field);
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
- return NULL;
- // TODO(teboring): Add it back.
- // return *((VALUE*)memory);
+ // Works for both repeated and map fields
+ memory = DEREF(memory, zval**);
+ if (EXPECTED(DEREF(memory, zval*) != val)) {
+ zval_ptr_dtor(memory);
+ DEREF(memory, zval*) = val;
+ Z_ADDREF_P(val);
+ }
} else {
- return native_slot_get(
- upb_fielddef_type(field), /*field_type_class(field), */
- memory TSRMLS_CC);
+ upb_fieldtype_t type = upb_fielddef_type(field);
+ zend_class_entry *ce = NULL;
+ if (type == UPB_TYPE_MESSAGE) {
+ upb_msgdef* msg = upb_fielddef_msgsubdef(field);
+ zval* desc_php = get_def_obj(msg);
+ Descriptor* desc = zend_object_store_get_object(desc_php TSRMLS_CC);
+ ce = desc->klass;
+ }
+ native_slot_set(type, ce, value_memory(field, memory), val);
}
}
diff --git a/php/ext/google/protobuf/test.php b/php/ext/google/protobuf/test.php
deleted file mode 100644
index 6bbadd48..00000000
--- a/php/ext/google/protobuf/test.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-
-
-namespace Google\Protobuf;
-
-$pool = get_generated_pool();
-$pool->addMessage("TestMessage")
- ->optional("optional_int32_a", "int32", 1)
- ->optional("optional_int32_b", "int32", 2)
- ->finalizeToPool()
- ->finalize();
-
-$test_message = new \TestMessage();
-
-?>
diff --git a/php/ext/google/protobuf/type_check.c b/php/ext/google/protobuf/type_check.c
new file mode 100644
index 00000000..fe9359fc
--- /dev/null
+++ b/php/ext/google/protobuf/type_check.c
@@ -0,0 +1,310 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <Zend/zend_operators.h>
+
+#include "protobuf.h"
+#include "utf8.h"
+
+static zend_class_entry* util_type;
+
+ZEND_BEGIN_ARG_INFO_EX(arg_check_optional, 0, 0, 1)
+ ZEND_ARG_INFO(1, val)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arg_check_message, 0, 0, 2)
+ ZEND_ARG_INFO(1, val)
+ ZEND_ARG_INFO(0, klass)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arg_check_repeated, 0, 0, 2)
+ ZEND_ARG_INFO(1, val)
+ ZEND_ARG_INFO(0, type)
+ ZEND_ARG_INFO(0, klass)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry util_methods[] = {
+ PHP_ME(Util, checkInt32, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ PHP_ME(Util, checkUint32, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ PHP_ME(Util, checkInt64, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ PHP_ME(Util, checkUint64, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ PHP_ME(Util, checkEnum, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ PHP_ME(Util, checkFloat, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ PHP_ME(Util, checkDouble, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ PHP_ME(Util, checkBool, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ PHP_ME(Util, checkString, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ PHP_ME(Util, checkBytes, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ PHP_ME(Util, checkMessage, arg_check_message, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ PHP_ME(Util, checkRepeatedField, arg_check_repeated,
+ ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ ZEND_FE_END
+};
+
+void util_init(TSRMLS_D) {
+ zend_class_entry class_type;
+ INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBUtil",
+ util_methods);
+ util_type = zend_register_internal_class(&class_type TSRMLS_CC);
+}
+
+// -----------------------------------------------------------------------------
+// Type checking/conversion.
+// -----------------------------------------------------------------------------
+
+#define CONVERT_TO_INTEGER(type) \
+ static bool convert_long_to_##type(long val, type##_t* type##_value) { \
+ *type##_value = (type##_t)val; \
+ return true; \
+ } \
+ \
+ static bool convert_double_to_##type(double val, type##_t* type##_value) { \
+ *type##_value = (type##_t)zend_dval_to_lval(val); \
+ return true; \
+ } \
+ \
+ static bool convert_string_to_##type(const char* val, int len, \
+ type##_t* type##_value) { \
+ long lval; \
+ double dval; \
+ \
+ switch (is_numeric_string(val, len, &lval, &dval, 0)) { \
+ case IS_DOUBLE: { \
+ return convert_double_to_##type(dval, type##_value); \
+ } \
+ case IS_LONG: { \
+ return convert_long_to_##type(lval, type##_value); \
+ } \
+ default: \
+ zend_error(E_USER_ERROR, \
+ "Given string value cannot be converted to integer."); \
+ return false; \
+ } \
+ } \
+ \
+ bool protobuf_convert_to_##type(zval* from, type##_t* to) { \
+ switch (Z_TYPE_P(from)) { \
+ case IS_LONG: { \
+ return convert_long_to_##type(Z_LVAL_P(from), to); \
+ } \
+ case IS_DOUBLE: { \
+ return convert_double_to_##type(Z_DVAL_P(from), to); \
+ } \
+ case IS_STRING: { \
+ return convert_string_to_##type(Z_STRVAL_P(from), Z_STRLEN_P(from), \
+ to); \
+ } \
+ default: { \
+ zend_error(E_USER_ERROR, \
+ "Given value cannot be converted to integer."); \
+ return false; \
+ } \
+ } \
+ return false; \
+ }
+
+CONVERT_TO_INTEGER(int32);
+CONVERT_TO_INTEGER(uint32);
+CONVERT_TO_INTEGER(int64);
+CONVERT_TO_INTEGER(uint64);
+
+#undef CONVERT_TO_INTEGER
+
+#define CONVERT_TO_FLOAT(type) \
+ static bool convert_long_to_##type(long val, type* type##_value) { \
+ *type##_value = (type)val; \
+ return true; \
+ } \
+ \
+ static bool convert_double_to_##type(double val, type* type##_value) { \
+ *type##_value = (type)val; \
+ return true; \
+ } \
+ \
+ static bool convert_string_to_##type(const char* val, int len, \
+ type* type##_value) { \
+ long lval; \
+ double dval; \
+ \
+ switch (is_numeric_string(val, len, &lval, &dval, 0)) { \
+ case IS_DOUBLE: { \
+ *type##_value = (type)dval; \
+ return true; \
+ } \
+ case IS_LONG: { \
+ *type##_value = (type)lval; \
+ return true; \
+ } \
+ default: \
+ zend_error(E_USER_ERROR, \
+ "Given string value cannot be converted to integer."); \
+ return false; \
+ } \
+ } \
+ \
+ bool protobuf_convert_to_##type(zval* from, type* to) { \
+ switch (Z_TYPE_P(from)) { \
+ case IS_LONG: { \
+ return convert_long_to_##type(Z_LVAL_P(from), to); \
+ } \
+ case IS_DOUBLE: { \
+ return convert_double_to_##type(Z_DVAL_P(from), to); \
+ } \
+ case IS_STRING: { \
+ return convert_string_to_##type(Z_STRVAL_P(from), Z_STRLEN_P(from), \
+ to); \
+ } \
+ default: { \
+ zend_error(E_USER_ERROR, \
+ "Given value cannot be converted to integer."); \
+ return false; \
+ } \
+ } \
+ return false; \
+ }
+
+CONVERT_TO_FLOAT(float);
+CONVERT_TO_FLOAT(double);
+
+#undef CONVERT_TO_FLOAT
+
+bool protobuf_convert_to_bool(zval* from, int8_t* to) {
+ switch (Z_TYPE_P(from)) {
+ case IS_BOOL:
+ *to = (int8_t)Z_BVAL_P(from);
+ break;
+ case IS_LONG:
+ *to = (int8_t)(Z_LVAL_P(from) != 0);
+ break;
+ case IS_DOUBLE:
+ *to = (int8_t)(Z_LVAL_P(from) != 0);
+ break;
+ case IS_STRING: {
+ char* strval = Z_STRVAL_P(from);
+
+ if (Z_STRLEN_P(from) == 0 ||
+ (Z_STRLEN_P(from) == 1 && Z_STRVAL_P(from)[0] == '0')) {
+ *to = 0;
+ } else {
+ *to = 1;
+ }
+ STR_FREE(strval);
+ } break;
+ default: {
+ zend_error(E_USER_ERROR, "Given value cannot be converted to bool.");
+ return false;
+ }
+ }
+ return true;
+}
+
+bool protobuf_convert_to_string(zval* from) {
+ switch (Z_TYPE_P(from)) {
+ case IS_STRING: {
+ return true;
+ }
+ case IS_BOOL:
+ case IS_LONG:
+ case IS_DOUBLE: {
+ int use_copy;
+ zval tmp;
+ zend_make_printable_zval(from, &tmp, &use_copy);
+ ZVAL_COPY_VALUE(from, &tmp);
+ return true;
+ }
+ default:
+ zend_error(E_USER_ERROR, "Given value cannot be converted to string.");
+ return false;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// PHP Functions.
+// -----------------------------------------------------------------------------
+
+// The implementation of type checking for primitive fields is empty. This is
+// because type checking is done when direct assigning message fields (e.g.,
+// foo->a = 1). Functions defined here are place holders in generated code for
+// pure PHP implementation (c extension and pure PHP share the same generated
+// code).
+#define PHP_TYPE_CHECK(type) \
+ PHP_METHOD(Util, check##type) {}
+
+PHP_TYPE_CHECK(Int32)
+PHP_TYPE_CHECK(Uint32)
+PHP_TYPE_CHECK(Int64)
+PHP_TYPE_CHECK(Uint64)
+PHP_TYPE_CHECK(Enum)
+PHP_TYPE_CHECK(Float)
+PHP_TYPE_CHECK(Double)
+PHP_TYPE_CHECK(Bool)
+PHP_TYPE_CHECK(String)
+PHP_TYPE_CHECK(Bytes)
+
+#undef PHP_TYPE_CHECK
+
+PHP_METHOD(Util, checkMessage) {
+ zval* val;
+ zend_class_entry* klass = NULL;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!C", &val, &klass) ==
+ FAILURE) {
+ return;
+ }
+ if (val == NULL) {
+ RETURN_NULL();
+ }
+ if (!instanceof_function(Z_OBJCE_P(val), klass TSRMLS_CC)) {
+ zend_error(E_USER_ERROR, "Given value is not an instance of %s.",
+ klass->name);
+ return;
+ }
+ RETURN_ZVAL(val, 1, 0);
+}
+
+PHP_METHOD(Util, checkRepeatedField) {
+ zval* val;
+ long type;
+ const zend_class_entry* klass = NULL;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol|C", &val,
+ repeated_field_type, &type, &klass) == FAILURE) {
+ return;
+ }
+
+ RepeatedField *intern =
+ (RepeatedField *)zend_object_store_get_object(val TSRMLS_CC);
+ if (to_fieldtype(type) != intern->type) {
+ zend_error(E_USER_ERROR, "Incorrect repeated field type.");
+ return;
+ }
+ if (klass != NULL && intern->msg_ce != klass) {
+ zend_error(E_USER_ERROR, "Expect a repeated field of %s, but %s is given.",
+ klass->name, intern->msg_ce->name);
+ return;
+ }
+}
diff --git a/php/ext/google/protobuf/upb.c b/php/ext/google/protobuf/upb.c
index 048a163a..98daafc0 100644
--- a/php/ext/google/protobuf/upb.c
+++ b/php/ext/google/protobuf/upb.c
@@ -1,7 +1,37 @@
-// Amalgamated source file
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
#include "upb.h"
+#include <ctype.h>
#include <stdlib.h>
#include <string.h>
@@ -11,7 +41,7 @@ typedef struct {
} str_t;
static str_t *newstr(const char *data, size_t len) {
- str_t *ret = malloc(sizeof(*ret) + len);
+ str_t *ret = upb_gmalloc(sizeof(*ret) + len);
if (!ret) return NULL;
ret->len = len;
memcpy(ret->str, data, len);
@@ -19,7 +49,7 @@ static str_t *newstr(const char *data, size_t len) {
return ret;
}
-static void freestr(str_t *s) { free(s); }
+static void freestr(str_t *s) { upb_gfree(s); }
/* isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. */
static bool upb_isbetween(char c, char low, char high) {
@@ -64,6 +94,22 @@ static bool upb_isident(const char *str, size_t len, bool full, upb_status *s) {
return !start;
}
+static bool upb_isoneof(const upb_refcounted *def) {
+ return def->vtbl == &upb_oneofdef_vtbl;
+}
+
+static bool upb_isfield(const upb_refcounted *def) {
+ return def->vtbl == &upb_fielddef_vtbl;
+}
+
+static const upb_oneofdef *upb_trygetoneof(const upb_refcounted *def) {
+ return upb_isoneof(def) ? (const upb_oneofdef*)def : NULL;
+}
+
+static const upb_fielddef *upb_trygetfield(const upb_refcounted *def) {
+ return upb_isfield(def) ? (const upb_fielddef*)def : NULL;
+}
+
/* upb_def ********************************************************************/
@@ -71,14 +117,39 @@ upb_deftype_t upb_def_type(const upb_def *d) { return d->type; }
const char *upb_def_fullname(const upb_def *d) { return d->fullname; }
+const char *upb_def_name(const upb_def *d) {
+ const char *p;
+
+ if (d->fullname == NULL) {
+ return NULL;
+ } else if ((p = strrchr(d->fullname, '.')) == NULL) {
+ /* No '.' in the name, return the full string. */
+ return d->fullname;
+ } else {
+ /* Return one past the last '.'. */
+ return p + 1;
+ }
+}
+
bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s) {
- assert(!upb_def_isfrozen(def));
- if (!upb_isident(fullname, strlen(fullname), true, s)) return false;
- free((void*)def->fullname);
- def->fullname = upb_strdup(fullname);
+ UPB_ASSERT(!upb_def_isfrozen(def));
+ if (!upb_isident(fullname, strlen(fullname), true, s)) {
+ return false;
+ }
+
+ fullname = upb_gstrdup(fullname);
+ if (!fullname) {
+ upb_upberr_setoom(s);
+ return false;
+ }
+
+ upb_gfree((void*)def->fullname);
+ def->fullname = fullname;
return true;
}
+const upb_filedef *upb_def_file(const upb_def *d) { return d->file; }
+
upb_def *upb_def_dup(const upb_def *def, const void *o) {
switch (def->type) {
case UPB_DEF_MSG:
@@ -90,7 +161,7 @@ upb_def *upb_def_dup(const upb_def *def, const void *o) {
case UPB_DEF_ENUM:
return upb_enumdef_upcast_mutable(
upb_enumdef_dup(upb_downcast_enumdef(def), o));
- default: assert(false); return NULL;
+ default: UPB_ASSERT(false); return NULL;
}
}
@@ -101,11 +172,12 @@ static bool upb_def_init(upb_def *def, upb_deftype_t type,
def->type = type;
def->fullname = NULL;
def->came_from_user = false;
+ def->file = NULL;
return true;
}
static void upb_def_uninit(upb_def *def) {
- free((void*)def->fullname);
+ upb_gfree((void*)def->fullname);
}
static const char *msgdef_name(const upb_msgdef *m) {
@@ -160,14 +232,14 @@ static bool upb_validate_field(upb_fielddef *f, upb_status *s) {
bool has_default_number = upb_fielddef_enumhasdefaultint32(f);
/* Previously verified by upb_validate_enumdef(). */
- assert(upb_enumdef_numvals(upb_fielddef_enumsubdef(f)) > 0);
+ UPB_ASSERT(upb_enumdef_numvals(upb_fielddef_enumsubdef(f)) > 0);
/* We've already validated that we have an associated enumdef and that it
* has at least one member, so at least one of these should be true.
* Because if the user didn't set anything, we'll pick up the enum's
* default, but if the user *did* set something we should at least pick up
* the one they set (int32 or string). */
- assert(has_default_name || has_default_number);
+ UPB_ASSERT(has_default_name || has_default_number);
if (!has_default_name) {
upb_status_seterrf(s,
@@ -223,7 +295,7 @@ static bool upb_validate_enumdef(const upb_enumdef *e, upb_status *s) {
uint32_t field_rank(const upb_fielddef *f) {
uint32_t ret = upb_fielddef_number(f);
const uint32_t high_bit = 1 << 30;
- assert(ret < high_bit);
+ UPB_ASSERT(ret < high_bit);
if (!upb_fielddef_issubmsg(f))
ret |= high_bit;
return ret;
@@ -242,17 +314,28 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
int i;
uint32_t selector;
int n = upb_msgdef_numfields(m);
- upb_fielddef **fields = malloc(n * sizeof(*fields));
- if (!fields) return false;
+ upb_fielddef **fields;
+
+ if (n == 0) {
+ m->selector_count = UPB_STATIC_SELECTOR_COUNT;
+ m->submsg_field_count = 0;
+ return true;
+ }
+
+ fields = upb_gmalloc(n * sizeof(*fields));
+ if (!fields) {
+ upb_upberr_setoom(s);
+ return false;
+ }
m->submsg_field_count = 0;
for(i = 0, upb_msg_field_begin(&j, m);
!upb_msg_field_done(&j);
upb_msg_field_next(&j), i++) {
upb_fielddef *f = upb_msg_iter_field(&j);
- assert(f->msg.def == m);
+ UPB_ASSERT(f->msg.def == m);
if (!upb_validate_field(f, s)) {
- free(fields);
+ upb_gfree(fields);
return false;
}
if (upb_fielddef_issubmsg(f)) {
@@ -312,15 +395,12 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
#undef TRY
#endif
- free(fields);
+ upb_gfree(fields);
return true;
}
-bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) {
- int i;
- int maxdepth;
- bool ret;
- upb_status_clear(s);
+bool _upb_def_validate(upb_def *const*defs, size_t n, upb_status *s) {
+ size_t i;
/* First perform validation, in two passes so we can check that we have a
* transitive closure without needing to search. */
@@ -346,8 +426,9 @@ bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) {
/* Second pass of validation. Also assign selector bases and indexes, and
* compact tables. */
for (i = 0; i < n; i++) {
- upb_msgdef *m = upb_dyncast_msgdef_mutable(defs[i]);
- upb_enumdef *e = upb_dyncast_enumdef_mutable(defs[i]);
+ upb_def *def = defs[i];
+ upb_msgdef *m = upb_dyncast_msgdef_mutable(def);
+ upb_enumdef *e = upb_dyncast_enumdef_mutable(def);
if (m) {
upb_inttable_compact(&m->itof);
if (!assign_msg_indices(m, s)) {
@@ -358,46 +439,68 @@ bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) {
}
}
- /* Def graph contains FieldDefs between each MessageDef, so double the
- * limit. */
- maxdepth = UPB_MAX_MESSAGE_DEPTH * 2;
-
- /* Validation all passed; freeze the defs. */
- ret = upb_refcounted_freeze((upb_refcounted * const *)defs, n, s, maxdepth);
- assert(!(s && ret != upb_ok(s)));
- return ret;
+ return true;
err:
for (i = 0; i < n; i++) {
- defs[i]->came_from_user = false;
+ upb_def *def = defs[i];
+ def->came_from_user = false;
}
- assert(!(s && upb_ok(s)));
+ UPB_ASSERT(!(s && upb_ok(s)));
return false;
}
+bool upb_def_freeze(upb_def *const* defs, size_t n, upb_status *s) {
+ /* Def graph contains FieldDefs between each MessageDef, so double the
+ * limit. */
+ const size_t maxdepth = UPB_MAX_MESSAGE_DEPTH * 2;
+
+ if (!_upb_def_validate(defs, n, s)) {
+ return false;
+ }
+
+
+ /* Validation all passed; freeze the objects. */
+ return upb_refcounted_freeze((upb_refcounted *const*)defs, n, s, maxdepth);
+}
+
/* upb_enumdef ****************************************************************/
-static void upb_enumdef_free(upb_refcounted *r) {
+static void visitenum(const upb_refcounted *r, upb_refcounted_visit *visit,
+ void *closure) {
+ const upb_enumdef *e = (const upb_enumdef*)r;
+ const upb_def *def = upb_enumdef_upcast(e);
+ if (upb_def_file(def)) {
+ visit(r, upb_filedef_upcast(upb_def_file(def)), closure);
+ }
+}
+
+static void freeenum(upb_refcounted *r) {
upb_enumdef *e = (upb_enumdef*)r;
upb_inttable_iter i;
upb_inttable_begin(&i, &e->iton);
for( ; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- /* To clean up the upb_strdup() from upb_enumdef_addval(). */
- free(upb_value_getcstr(upb_inttable_iter_value(&i)));
+ /* To clean up the upb_gstrdup() from upb_enumdef_addval(). */
+ upb_gfree(upb_value_getcstr(upb_inttable_iter_value(&i)));
}
upb_strtable_uninit(&e->ntoi);
upb_inttable_uninit(&e->iton);
upb_def_uninit(upb_enumdef_upcast_mutable(e));
- free(e);
+ upb_gfree(e);
}
+const struct upb_refcounted_vtbl upb_enumdef_vtbl = {&visitenum, &freeenum};
+
upb_enumdef *upb_enumdef_new(const void *owner) {
- static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_enumdef_free};
- upb_enumdef *e = malloc(sizeof(*e));
+ upb_enumdef *e = upb_gmalloc(sizeof(*e));
if (!e) return NULL;
- if (!upb_def_init(upb_enumdef_upcast_mutable(e), UPB_DEF_ENUM, &vtbl, owner))
+
+ if (!upb_def_init(upb_enumdef_upcast_mutable(e), UPB_DEF_ENUM,
+ &upb_enumdef_vtbl, owner)) {
goto err2;
+ }
+
if (!upb_strtable_init(&e->ntoi, UPB_CTYPE_INT32)) goto err2;
if (!upb_inttable_init(&e->iton, UPB_CTYPE_CSTR)) goto err1;
return e;
@@ -405,7 +508,7 @@ upb_enumdef *upb_enumdef_new(const void *owner) {
err1:
upb_strtable_uninit(&e->ntoi);
err2:
- free(e);
+ upb_gfree(e);
return NULL;
}
@@ -433,6 +536,10 @@ const char *upb_enumdef_fullname(const upb_enumdef *e) {
return upb_def_fullname(upb_enumdef_upcast(e));
}
+const char *upb_enumdef_name(const upb_enumdef *e) {
+ return upb_def_name(upb_enumdef_upcast(e));
+}
+
bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname,
upb_status *s) {
return upb_def_setfullname(upb_enumdef_upcast_mutable(e), fullname, s);
@@ -440,37 +547,46 @@ bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname,
bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num,
upb_status *status) {
+ char *name2;
+
if (!upb_isident(name, strlen(name), false, status)) {
return false;
}
+
if (upb_enumdef_ntoiz(e, name, NULL)) {
upb_status_seterrf(status, "name '%s' is already defined", name);
return false;
}
+
if (!upb_strtable_insert(&e->ntoi, name, upb_value_int32(num))) {
upb_status_seterrmsg(status, "out of memory");
return false;
}
- if (!upb_inttable_lookup(&e->iton, num, NULL) &&
- !upb_inttable_insert(&e->iton, num, upb_value_cstr(upb_strdup(name)))) {
- upb_status_seterrmsg(status, "out of memory");
- upb_strtable_remove(&e->ntoi, name, NULL);
- return false;
+
+ if (!upb_inttable_lookup(&e->iton, num, NULL)) {
+ name2 = upb_gstrdup(name);
+ if (!name2 || !upb_inttable_insert(&e->iton, num, upb_value_cstr(name2))) {
+ upb_status_seterrmsg(status, "out of memory");
+ upb_strtable_remove(&e->ntoi, name, NULL);
+ return false;
+ }
}
+
if (upb_enumdef_numvals(e) == 1) {
bool ok = upb_enumdef_setdefault(e, num, NULL);
- UPB_ASSERT_VAR(ok, ok);
+ UPB_ASSERT(ok);
}
+
return true;
}
int32_t upb_enumdef_default(const upb_enumdef *e) {
- assert(upb_enumdef_iton(e, e->defaultval));
+ UPB_ASSERT(upb_enumdef_iton(e, e->defaultval));
return e->defaultval;
}
bool upb_enumdef_setdefault(upb_enumdef *e, int32_t val, upb_status *s) {
- assert(!upb_enumdef_isfrozen(e));
+ UPB_ASSERT(!upb_enumdef_isfrozen(e));
if (!upb_enumdef_iton(e, val)) {
upb_status_seterrf(s, "number '%d' is not in the enum.", val);
return false;
@@ -525,32 +641,40 @@ static void upb_fielddef_uninit_default(upb_fielddef *f) {
freestr(f->defaultval.bytes);
}
+const char *upb_fielddef_fullname(const upb_fielddef *e) {
+ return upb_def_fullname(upb_fielddef_upcast(e));
+}
+
static void visitfield(const upb_refcounted *r, upb_refcounted_visit *visit,
void *closure) {
const upb_fielddef *f = (const upb_fielddef*)r;
+ const upb_def *def = upb_fielddef_upcast(f);
if (upb_fielddef_containingtype(f)) {
visit(r, upb_msgdef_upcast2(upb_fielddef_containingtype(f)), closure);
}
if (upb_fielddef_containingoneof(f)) {
- visit(r, upb_oneofdef_upcast2(upb_fielddef_containingoneof(f)), closure);
+ visit(r, upb_oneofdef_upcast(upb_fielddef_containingoneof(f)), closure);
}
if (upb_fielddef_subdef(f)) {
visit(r, upb_def_upcast(upb_fielddef_subdef(f)), closure);
}
+ if (upb_def_file(def)) {
+ visit(r, upb_filedef_upcast(upb_def_file(def)), closure);
+ }
}
static void freefield(upb_refcounted *r) {
upb_fielddef *f = (upb_fielddef*)r;
upb_fielddef_uninit_default(f);
if (f->subdef_is_symbolic)
- free(f->sub.name);
+ upb_gfree(f->sub.name);
upb_def_uninit(upb_fielddef_upcast_mutable(f));
- free(f);
+ upb_gfree(f);
}
static const char *enumdefaultstr(const upb_fielddef *f) {
const upb_enumdef *e;
- assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
+ UPB_ASSERT(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
e = upb_fielddef_enumsubdef(f);
if (f->default_is_string && f->defaultval.bytes) {
/* Default was explicitly set as a string. */
@@ -567,7 +691,7 @@ static const char *enumdefaultstr(const upb_fielddef *f) {
/* Default is completely unset; pull enumdef default. */
if (upb_enumdef_numvals(e) > 0) {
const char *name = upb_enumdef_iton(e, upb_enumdef_default(e));
- assert(name);
+ UPB_ASSERT(name);
return name;
}
}
@@ -577,7 +701,7 @@ static const char *enumdefaultstr(const upb_fielddef *f) {
static bool enumdefaultint32(const upb_fielddef *f, int32_t *val) {
const upb_enumdef *e;
- assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
+ UPB_ASSERT(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
e = upb_fielddef_enumsubdef(f);
if (!f->default_is_string) {
/* Default was explicitly set as an integer. */
@@ -601,12 +725,14 @@ static bool enumdefaultint32(const upb_fielddef *f, int32_t *val) {
return false;
}
+const struct upb_refcounted_vtbl upb_fielddef_vtbl = {visitfield, freefield};
+
upb_fielddef *upb_fielddef_new(const void *o) {
- static const struct upb_refcounted_vtbl vtbl = {visitfield, freefield};
- upb_fielddef *f = malloc(sizeof(*f));
+ upb_fielddef *f = upb_gmalloc(sizeof(*f));
if (!f) return NULL;
- if (!upb_def_init(upb_fielddef_upcast_mutable(f), UPB_DEF_FIELD, &vtbl, o)) {
- free(f);
+ if (!upb_def_init(upb_fielddef_upcast_mutable(f), UPB_DEF_FIELD,
+ &upb_fielddef_vtbl, o)) {
+ upb_gfree(f);
return NULL;
}
f->msg.def = NULL;
@@ -657,7 +783,7 @@ upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) {
srcname = f->sub.def ? upb_def_fullname(f->sub.def) : NULL;
}
if (srcname) {
- char *newname = malloc(strlen(f->sub.def->fullname) + 2);
+ char *newname = upb_gmalloc(strlen(f->sub.def->fullname) + 2);
if (!newname) {
upb_fielddef_unref(newf, owner);
return NULL;
@@ -665,7 +791,7 @@ upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) {
strcpy(newname, ".");
strcat(newname, f->sub.def->fullname);
upb_fielddef_setsubdefname(newf, newname, NULL);
- free(newname);
+ upb_gfree(newname);
}
return newf;
@@ -676,7 +802,7 @@ bool upb_fielddef_typeisset(const upb_fielddef *f) {
}
upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) {
- assert(f->type_is_set_);
+ UPB_ASSERT(f->type_is_set_);
return f->type_;
}
@@ -716,6 +842,45 @@ const char *upb_fielddef_name(const upb_fielddef *f) {
return upb_def_fullname(upb_fielddef_upcast(f));
}
+size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len) {
+ const char *name = upb_fielddef_name(f);
+ size_t src, dst = 0;
+ bool ucase_next = false;
+
+#define WRITE(byte) \
+ ++dst; \
+ if (dst < len) buf[dst - 1] = byte; \
+ else if (dst == len) buf[dst - 1] = '\0'
+
+ if (!name) {
+ WRITE('\0');
+ return 0;
+ }
+
+ /* Implement the transformation as described in the spec:
+ * 1. upper case all letters after an underscore.
+ * 2. remove all underscores.
+ */
+ for (src = 0; name[src]; src++) {
+ if (name[src] == '_') {
+ ucase_next = true;
+ continue;
+ }
+
+ if (ucase_next) {
+ WRITE(toupper(name[src]));
+ ucase_next = false;
+ } else {
+ WRITE(name[src]);
+ }
+ }
+
+ WRITE('\0');
+ return dst;
+
+#undef WRITE
+}
+
const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
return f->msg_is_symbolic ? NULL : f->msg.def;
}
@@ -733,20 +898,28 @@ const char *upb_fielddef_containingtypename(upb_fielddef *f) {
}
static void release_containingtype(upb_fielddef *f) {
- if (f->msg_is_symbolic) free(f->msg.name);
+ if (f->msg_is_symbolic) upb_gfree(f->msg.name);
}
bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name,
upb_status *s) {
- assert(!upb_fielddef_isfrozen(f));
+ char *name_copy;
+ UPB_ASSERT(!upb_fielddef_isfrozen(f));
if (upb_fielddef_containingtype(f)) {
upb_status_seterrmsg(s, "field has already been added to a message.");
return false;
}
/* TODO: validate name (upb_isident() doesn't quite work atm because this name
* may have a leading "."). */
+
+ name_copy = upb_gstrdup(name);
+ if (!name_copy) {
+ upb_upberr_setoom(s);
+ return false;
+ }
+
release_containingtype(f);
- f->msg.name = upb_strdup(name);
+ f->msg.name = name_copy;
f->msg_is_symbolic = true;
return true;
}
@@ -762,7 +935,7 @@ bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s) {
static void chkdefaulttype(const upb_fielddef *f, upb_fieldtype_t type) {
UPB_UNUSED(f);
UPB_UNUSED(type);
- assert(f->type_is_set_ && upb_fielddef_type(f) == type);
+ UPB_ASSERT(f->type_is_set_ && upb_fielddef_type(f) == type);
}
int64_t upb_fielddef_defaultint64(const upb_fielddef *f) {
@@ -774,7 +947,7 @@ int32_t upb_fielddef_defaultint32(const upb_fielddef *f) {
if (f->type_is_set_ && upb_fielddef_type(f) == UPB_TYPE_ENUM) {
int32_t val;
bool ok = enumdefaultint32(f, &val);
- UPB_ASSERT_VAR(ok, ok);
+ UPB_ASSERT(ok);
return val;
} else {
chkdefaulttype(f, UPB_TYPE_INT32);
@@ -808,14 +981,14 @@ double upb_fielddef_defaultdouble(const upb_fielddef *f) {
}
const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
- assert(f->type_is_set_);
- assert(upb_fielddef_type(f) == UPB_TYPE_STRING ||
+ UPB_ASSERT(f->type_is_set_);
+ UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_STRING ||
upb_fielddef_type(f) == UPB_TYPE_BYTES ||
upb_fielddef_type(f) == UPB_TYPE_ENUM);
if (upb_fielddef_type(f) == UPB_TYPE_ENUM) {
const char *ret = enumdefaultstr(f);
- assert(ret);
+ UPB_ASSERT(ret);
/* Enum defaults can't have embedded NULLs. */
if (len) *len = strlen(ret);
return ret;
@@ -897,8 +1070,8 @@ bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s) {
}
void upb_fielddef_settype(upb_fielddef *f, upb_fieldtype_t type) {
- assert(!upb_fielddef_isfrozen(f));
- assert(upb_fielddef_checktype(type));
+ UPB_ASSERT(!upb_fielddef_isfrozen(f));
+ UPB_ASSERT(upb_fielddef_checktype(type));
upb_fielddef_uninit_default(f);
f->type_ = type;
f->type_is_set_ = true;
@@ -906,7 +1079,7 @@ void upb_fielddef_settype(upb_fielddef *f, upb_fieldtype_t type) {
}
void upb_fielddef_setdescriptortype(upb_fielddef *f, int type) {
- assert(!upb_fielddef_isfrozen(f));
+ UPB_ASSERT(!upb_fielddef_isfrozen(f));
switch (type) {
case UPB_DESCRIPTOR_TYPE_DOUBLE:
upb_fielddef_settype(f, UPB_TYPE_DOUBLE);
@@ -948,7 +1121,7 @@ void upb_fielddef_setdescriptortype(upb_fielddef *f, int type) {
case UPB_DESCRIPTOR_TYPE_ENUM:
upb_fielddef_settype(f, UPB_TYPE_ENUM);
break;
- default: assert(false);
+ default: UPB_ASSERT(false);
}
if (type == UPB_DESCRIPTOR_TYPE_FIXED64 ||
@@ -1006,34 +1179,34 @@ upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
}
void upb_fielddef_setisextension(upb_fielddef *f, bool is_extension) {
- assert(!upb_fielddef_isfrozen(f));
+ UPB_ASSERT(!upb_fielddef_isfrozen(f));
f->is_extension_ = is_extension;
}
void upb_fielddef_setlazy(upb_fielddef *f, bool lazy) {
- assert(!upb_fielddef_isfrozen(f));
+ UPB_ASSERT(!upb_fielddef_isfrozen(f));
f->lazy_ = lazy;
}
void upb_fielddef_setpacked(upb_fielddef *f, bool packed) {
- assert(!upb_fielddef_isfrozen(f));
+ UPB_ASSERT(!upb_fielddef_isfrozen(f));
f->packed_ = packed;
}
void upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label) {
- assert(!upb_fielddef_isfrozen(f));
- assert(upb_fielddef_checklabel(label));
+ UPB_ASSERT(!upb_fielddef_isfrozen(f));
+ UPB_ASSERT(upb_fielddef_checklabel(label));
f->label_ = label;
}
void upb_fielddef_setintfmt(upb_fielddef *f, upb_intfmt_t fmt) {
- assert(!upb_fielddef_isfrozen(f));
- assert(upb_fielddef_checkintfmt(fmt));
+ UPB_ASSERT(!upb_fielddef_isfrozen(f));
+ UPB_ASSERT(upb_fielddef_checkintfmt(fmt));
f->intfmt = fmt;
}
void upb_fielddef_settagdelim(upb_fielddef *f, bool tag_delim) {
- assert(!upb_fielddef_isfrozen(f));
+ UPB_ASSERT(!upb_fielddef_isfrozen(f));
f->tagdelim = tag_delim;
f->tagdelim = tag_delim;
}
@@ -1041,12 +1214,12 @@ void upb_fielddef_settagdelim(upb_fielddef *f, bool tag_delim) {
static bool checksetdefault(upb_fielddef *f, upb_fieldtype_t type) {
if (!f->type_is_set_ || upb_fielddef_isfrozen(f) ||
upb_fielddef_type(f) != type) {
- assert(false);
+ UPB_ASSERT(false);
return false;
}
if (f->default_is_string) {
str_t *s = f->defaultval.bytes;
- assert(s || type == UPB_TYPE_ENUM);
+ UPB_ASSERT(s || type == UPB_TYPE_ENUM);
if (s) freestr(s);
}
f->default_is_string = false;
@@ -1094,16 +1267,16 @@ void upb_fielddef_setdefaultdouble(upb_fielddef *f, double value) {
bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len,
upb_status *s) {
str_t *str2;
- assert(upb_fielddef_isstring(f) || f->type_ == UPB_TYPE_ENUM);
+ UPB_ASSERT(upb_fielddef_isstring(f) || f->type_ == UPB_TYPE_ENUM);
if (f->type_ == UPB_TYPE_ENUM && !upb_isident(str, len, false, s))
return false;
if (f->default_is_string) {
str_t *s = f->defaultval.bytes;
- assert(s || f->type_ == UPB_TYPE_ENUM);
+ UPB_ASSERT(s || f->type_ == UPB_TYPE_ENUM);
if (s) freestr(s);
} else {
- assert(f->type_ == UPB_TYPE_ENUM);
+ UPB_ASSERT(f->type_ == UPB_TYPE_ENUM);
}
str2 = newstr(str, len);
@@ -1114,18 +1287,18 @@ bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len,
void upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str,
upb_status *s) {
- assert(f->type_is_set_);
+ UPB_ASSERT(f->type_is_set_);
upb_fielddef_setdefaultstr(f, str, str ? strlen(str) : 0, s);
}
bool upb_fielddef_enumhasdefaultint32(const upb_fielddef *f) {
int32_t val;
- assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
+ UPB_ASSERT(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
return enumdefaultint32(f, &val);
}
bool upb_fielddef_enumhasdefaultstr(const upb_fielddef *f) {
- assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
+ UPB_ASSERT(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
return enumdefaultstr(f) != NULL;
}
@@ -1147,7 +1320,7 @@ static bool upb_subdef_typecheck(upb_fielddef *f, const upb_def *subdef,
static void release_subdef(upb_fielddef *f) {
if (f->subdef_is_symbolic) {
- free(f->sub.name);
+ upb_gfree(f->sub.name);
} else if (f->sub.def) {
upb_unref2(f->sub.def, f);
}
@@ -1155,8 +1328,8 @@ static void release_subdef(upb_fielddef *f) {
bool upb_fielddef_setsubdef(upb_fielddef *f, const upb_def *subdef,
upb_status *s) {
- assert(!upb_fielddef_isfrozen(f));
- assert(upb_fielddef_hassubdef(f));
+ UPB_ASSERT(!upb_fielddef_isfrozen(f));
+ UPB_ASSERT(upb_fielddef_hassubdef(f));
if (subdef && !upb_subdef_typecheck(f, subdef, s)) return false;
release_subdef(f);
f->sub.def = subdef;
@@ -1177,15 +1350,23 @@ bool upb_fielddef_setenumsubdef(upb_fielddef *f, const upb_enumdef *subdef,
bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name,
upb_status *s) {
- assert(!upb_fielddef_isfrozen(f));
+ char *name_copy;
+ UPB_ASSERT(!upb_fielddef_isfrozen(f));
if (!upb_fielddef_hassubdef(f)) {
upb_status_seterrmsg(s, "field type does not accept a subdef");
return false;
}
+
+ name_copy = upb_gstrdup(name);
+ if (!name_copy) {
+ upb_upberr_setoom(s);
+ return false;
+ }
+
/* TODO: validate name (upb_isident() doesn't quite work atm because this name
* may have a leading "."). */
release_subdef(f);
- f->sub.name = upb_strdup(name);
+ f->sub.name = name_copy;
f->subdef_is_symbolic = true;
return true;
}
@@ -1212,6 +1393,16 @@ bool upb_fielddef_ismap(const upb_fielddef *f) {
upb_msgdef_mapentry(upb_fielddef_msgsubdef(f));
}
+bool upb_fielddef_haspresence(const upb_fielddef *f) {
+ if (upb_fielddef_isseq(f)) return false;
+ if (upb_fielddef_issubmsg(f)) return true;
+
+ /* Primitive field: return true unless there is a message that specifies
+ * presence should not exist. */
+ if (f->msg_is_symbolic || !f->msg.def) return true;
+ return f->msg.def->syntax == UPB_SYNTAX_PROTO2;
+}
+
bool upb_fielddef_hassubdef(const upb_fielddef *f) {
return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM;
}
@@ -1234,6 +1425,7 @@ static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit,
void *closure) {
upb_msg_oneof_iter o;
const upb_msgdef *m = (const upb_msgdef*)r;
+ const upb_def *def = upb_msgdef_upcast(m);
upb_msg_field_iter i;
for(upb_msg_field_begin(&i, m);
!upb_msg_field_done(&i);
@@ -1245,37 +1437,42 @@ static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit,
!upb_msg_oneof_done(&o);
upb_msg_oneof_next(&o)) {
upb_oneofdef *f = upb_msg_iter_oneof(&o);
- visit(r, upb_oneofdef_upcast2(f), closure);
+ visit(r, upb_oneofdef_upcast(f), closure);
+ }
+ if (upb_def_file(def)) {
+ visit(r, upb_filedef_upcast(upb_def_file(def)), closure);
}
}
static void freemsg(upb_refcounted *r) {
upb_msgdef *m = (upb_msgdef*)r;
- upb_strtable_uninit(&m->ntoo);
upb_strtable_uninit(&m->ntof);
upb_inttable_uninit(&m->itof);
upb_def_uninit(upb_msgdef_upcast_mutable(m));
- free(m);
+ upb_gfree(m);
}
+const struct upb_refcounted_vtbl upb_msgdef_vtbl = {visitmsg, freemsg};
+
upb_msgdef *upb_msgdef_new(const void *owner) {
- static const struct upb_refcounted_vtbl vtbl = {visitmsg, freemsg};
- upb_msgdef *m = malloc(sizeof(*m));
+ upb_msgdef *m = upb_gmalloc(sizeof(*m));
if (!m) return NULL;
- if (!upb_def_init(upb_msgdef_upcast_mutable(m), UPB_DEF_MSG, &vtbl, owner))
+
+ if (!upb_def_init(upb_msgdef_upcast_mutable(m), UPB_DEF_MSG, &upb_msgdef_vtbl,
+ owner)) {
goto err2;
- if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err3;
- if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err2;
- if (!upb_strtable_init(&m->ntoo, UPB_CTYPE_PTR)) goto err1;
+ }
+
+ if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err2;
+ if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err1;
m->map_entry = false;
+ m->syntax = UPB_SYNTAX_PROTO2;
return m;
err1:
- upb_strtable_uninit(&m->ntof);
-err2:
upb_inttable_uninit(&m->itof);
-err3:
- free(m);
+err2:
+ upb_gfree(m);
return NULL;
}
@@ -1290,7 +1487,8 @@ upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) {
upb_def_fullname(upb_msgdef_upcast(m)),
NULL);
newm->map_entry = m->map_entry;
- UPB_ASSERT_VAR(ok, ok);
+ newm->syntax = m->syntax;
+ UPB_ASSERT(ok);
for(upb_msg_field_begin(&i, m);
!upb_msg_field_done(&i);
upb_msg_field_next(&i)) {
@@ -1323,11 +1521,28 @@ const char *upb_msgdef_fullname(const upb_msgdef *m) {
return upb_def_fullname(upb_msgdef_upcast(m));
}
+const char *upb_msgdef_name(const upb_msgdef *m) {
+ return upb_def_name(upb_msgdef_upcast(m));
+}
+
bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname,
upb_status *s) {
return upb_def_setfullname(upb_msgdef_upcast_mutable(m), fullname, s);
}
+bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax) {
+ if (syntax != UPB_SYNTAX_PROTO2 && syntax != UPB_SYNTAX_PROTO3) {
+ return false;
+ }
+
+ m->syntax = syntax;
+ return true;
+}
+
+upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) {
+ return m->syntax;
+}
+
/* Helper: check that the field |f| is safe to add to msgdef |m|. Set an error
* on status |s| and return false if not. */
static bool check_field_add(const upb_msgdef *m, const upb_fielddef *f,
@@ -1338,9 +1553,11 @@ static bool check_field_add(const upb_msgdef *m, const upb_fielddef *f,
} else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
upb_status_seterrmsg(s, "field name or number were not set");
return false;
- } else if (upb_msgdef_ntofz(m, upb_fielddef_name(f)) ||
- upb_msgdef_itof(m, upb_fielddef_number(f))) {
- upb_status_seterrmsg(s, "duplicate field name or number for field");
+ } else if (upb_msgdef_itof(m, upb_fielddef_number(f))) {
+ upb_status_seterrmsg(s, "duplicate field number");
+ return false;
+ } else if (upb_strtable_lookup(&m->ntof, upb_fielddef_name(f), NULL)) {
+ upb_status_seterrmsg(s, "name conflicts with existing field or oneof");
return false;
}
return true;
@@ -1373,6 +1590,7 @@ bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor,
* This method is idempotent. Check if |f| is already part of this msgdef and
* return immediately if so. */
if (upb_fielddef_containingtype(f) == m) {
+ if (ref_donor) upb_fielddef_unref(f, ref_donor);
return true;
}
@@ -1401,8 +1619,8 @@ bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
} else if (upb_oneofdef_name(o) == NULL) {
upb_status_seterrmsg(s, "oneofdef name was not set");
return false;
- } else if (upb_msgdef_ntooz(m, upb_oneofdef_name(o))) {
- upb_status_seterrmsg(s, "duplicate oneof name");
+ } else if (upb_strtable_lookup(&m->ntof, upb_oneofdef_name(o), NULL)) {
+ upb_status_seterrmsg(s, "name conflicts with existing field or oneof");
return false;
}
@@ -1419,7 +1637,7 @@ bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
/* Add oneof itself first. */
o->parent = m;
- upb_strtable_insert(&m->ntoo, upb_oneofdef_name(o), upb_value_ptr(o));
+ upb_strtable_insert(&m->ntof, upb_oneofdef_name(o), upb_value_ptr(o));
upb_ref2(o, m);
upb_ref2(m, o);
@@ -1443,27 +1661,51 @@ const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
size_t len) {
upb_value val;
- return upb_strtable_lookup2(&m->ntof, name, len, &val) ?
- upb_value_getptr(val) : NULL;
+
+ if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+ return NULL;
+ }
+
+ return upb_trygetfield(upb_value_getptr(val));
}
const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
size_t len) {
upb_value val;
- return upb_strtable_lookup2(&m->ntoo, name, len, &val) ?
- upb_value_getptr(val) : NULL;
+
+ if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+ return NULL;
+ }
+
+ return upb_trygetoneof(upb_value_getptr(val));
+}
+
+bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
+ const upb_fielddef **f, const upb_oneofdef **o) {
+ upb_value val;
+
+ if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+ return false;
+ }
+
+ *o = upb_trygetoneof(upb_value_getptr(val));
+ *f = upb_trygetfield(upb_value_getptr(val));
+ UPB_ASSERT((*o != NULL) ^ (*f != NULL)); /* Exactly one of the two should be set. */
+ return true;
}
int upb_msgdef_numfields(const upb_msgdef *m) {
- return upb_strtable_count(&m->ntof);
+ /* The number table contains only fields. */
+ return upb_inttable_count(&m->itof);
}
int upb_msgdef_numoneofs(const upb_msgdef *m) {
- return upb_strtable_count(&m->ntoo);
+ /* The name table includes oneofs, and the number table does not. */
+ return upb_strtable_count(&m->ntof) - upb_inttable_count(&m->itof);
}
void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry) {
- assert(!upb_msgdef_isfrozen(m));
+ UPB_ASSERT(!upb_msgdef_isfrozen(m));
m->map_entry = map_entry;
}
@@ -1490,10 +1732,21 @@ void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
}
void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
- upb_strtable_begin(iter, &m->ntoo);
+ upb_strtable_begin(iter, &m->ntof);
+ /* We need to skip past any initial fields. */
+ while (!upb_strtable_done(iter) &&
+ !upb_isoneof(upb_value_getptr(upb_strtable_iter_value(iter)))) {
+ upb_strtable_next(iter);
+ }
}
-void upb_msg_oneof_next(upb_msg_oneof_iter *iter) { upb_strtable_next(iter); }
+void upb_msg_oneof_next(upb_msg_oneof_iter *iter) {
+ /* We need to skip past fields to return only oneofs. */
+ do {
+ upb_strtable_next(iter);
+ } while (!upb_strtable_done(iter) &&
+ !upb_isoneof(upb_value_getptr(upb_strtable_iter_value(iter))));
+}
bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
return upb_strtable_done(iter);
@@ -1526,26 +1779,36 @@ static void freeoneof(upb_refcounted *r) {
upb_oneofdef *o = (upb_oneofdef*)r;
upb_strtable_uninit(&o->ntof);
upb_inttable_uninit(&o->itof);
- upb_def_uninit(upb_oneofdef_upcast_mutable(o));
- free(o);
+ upb_gfree((void*)o->name);
+ upb_gfree(o);
}
+const struct upb_refcounted_vtbl upb_oneofdef_vtbl = {visitoneof, freeoneof};
+
upb_oneofdef *upb_oneofdef_new(const void *owner) {
- static const struct upb_refcounted_vtbl vtbl = {visitoneof, freeoneof};
- upb_oneofdef *o = malloc(sizeof(*o));
+ upb_oneofdef *o = upb_gmalloc(sizeof(*o));
+
+ if (!o) {
+ return NULL;
+ }
+
o->parent = NULL;
- if (!o) return NULL;
- if (!upb_def_init(upb_oneofdef_upcast_mutable(o), UPB_DEF_ONEOF, &vtbl,
- owner))
+ o->name = NULL;
+
+ if (!upb_refcounted_init(upb_oneofdef_upcast_mutable(o), &upb_oneofdef_vtbl,
+ owner)) {
goto err2;
+ }
+
if (!upb_inttable_init(&o->itof, UPB_CTYPE_PTR)) goto err2;
if (!upb_strtable_init(&o->ntof, UPB_CTYPE_PTR)) goto err1;
+
return o;
err1:
upb_inttable_uninit(&o->itof);
err2:
- free(o);
+ upb_gfree(o);
return NULL;
}
@@ -1554,9 +1817,8 @@ upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner) {
upb_oneof_iter i;
upb_oneofdef *newo = upb_oneofdef_new(owner);
if (!newo) return NULL;
- ok = upb_def_setfullname(upb_oneofdef_upcast_mutable(newo),
- upb_def_fullname(upb_oneofdef_upcast(o)), NULL);
- UPB_ASSERT_VAR(ok, ok);
+ ok = upb_oneofdef_setname(newo, upb_oneofdef_name(o), NULL);
+ UPB_ASSERT(ok);
for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) {
upb_fielddef *f = upb_fielddef_dup(upb_oneof_iter_field(&i), &f);
if (!f || !upb_oneofdef_addfield(newo, f, &f, NULL)) {
@@ -1567,17 +1829,28 @@ upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner) {
return newo;
}
-const char *upb_oneofdef_name(const upb_oneofdef *o) {
- return upb_def_fullname(upb_oneofdef_upcast(o));
-}
+const char *upb_oneofdef_name(const upb_oneofdef *o) { return o->name; }
-bool upb_oneofdef_setname(upb_oneofdef *o, const char *fullname,
- upb_status *s) {
+bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s) {
+ UPB_ASSERT(!upb_oneofdef_isfrozen(o));
if (upb_oneofdef_containingtype(o)) {
upb_status_seterrmsg(s, "oneof already added to a message");
return false;
}
- return upb_def_setfullname(upb_oneofdef_upcast_mutable(o), fullname, s);
+
+ if (!upb_isident(name, strlen(name), true, s)) {
+ return false;
+ }
+
+ name = upb_gstrdup(name);
+ if (!name) {
+ upb_status_seterrmsg(s, "One of memory");
+ return false;
+ }
+
+ upb_gfree((void*)o->name);
+ o->name = name;
+ return true;
}
const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) {
@@ -1591,8 +1864,8 @@ int upb_oneofdef_numfields(const upb_oneofdef *o) {
bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f,
const void *ref_donor,
upb_status *s) {
- assert(!upb_oneofdef_isfrozen(o));
- assert(!o->parent || !upb_msgdef_isfrozen(o->parent));
+ UPB_ASSERT(!upb_oneofdef_isfrozen(o));
+ UPB_ASSERT(!o->parent || !upb_msgdef_isfrozen(o->parent));
/* This method is idempotent. Check if |f| is already part of this oneofdef
* and return immediately if so. */
@@ -1696,287 +1969,209 @@ void upb_oneof_iter_setdone(upb_oneof_iter *iter) {
upb_inttable_iter_setdone(iter);
}
+/* upb_filedef ****************************************************************/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-typedef struct cleanup_ent {
- upb_cleanup_func *cleanup;
- void *ud;
- struct cleanup_ent *next;
-} cleanup_ent;
-
-static void *seeded_alloc(void *ud, void *ptr, size_t oldsize, size_t size);
-
-/* Default allocator **********************************************************/
-
-/* Just use realloc, keeping all allocated blocks in a linked list to destroy at
- * the end. */
-
-typedef struct mem_block {
- /* List is doubly-linked, because in cases where realloc() moves an existing
- * block, we need to be able to remove the old pointer from the list
- * efficiently. */
- struct mem_block *prev, *next;
-#ifndef NDEBUG
- size_t size; /* Doesn't include mem_block structure. */
-#endif
-} mem_block;
-
-typedef struct {
- mem_block *head;
-} default_alloc_ud;
-
-static void *default_alloc(void *_ud, void *ptr, size_t oldsize, size_t size) {
- default_alloc_ud *ud = _ud;
- mem_block *from, *block;
- void *ret;
- UPB_UNUSED(oldsize);
-
- from = ptr ? (void*)((char*)ptr - sizeof(mem_block)) : NULL;
-
-#ifndef NDEBUG
- if (from) {
- assert(oldsize <= from->size);
- }
-#endif
-
- /* TODO(haberman): we probably need to provide even better alignment here,
- * like 16-byte alignment of the returned data pointer. */
- block = realloc(from, size + sizeof(mem_block));
- if (!block) return NULL;
- ret = (char*)block + sizeof(*block);
-
-#ifndef NDEBUG
- block->size = size;
-#endif
+static void visitfiledef(const upb_refcounted *r, upb_refcounted_visit *visit,
+ void *closure) {
+ const upb_filedef *f = (const upb_filedef*)r;
+ size_t i;
- if (from) {
- if (block != from) {
- /* The block was moved, so pointers in next and prev blocks must be
- * updated to its new location. */
- if (block->next) block->next->prev = block;
- if (block->prev) block->prev->next = block;
- if (ud->head == from) ud->head = block;
- }
- } else {
- /* Insert at head of linked list. */
- block->prev = NULL;
- block->next = ud->head;
- if (block->next) block->next->prev = block;
- ud->head = block;
+ for(i = 0; i < upb_filedef_defcount(f); i++) {
+ visit(r, upb_def_upcast(upb_filedef_def(f, i)), closure);
}
-
- return ret;
}
-static void default_alloc_cleanup(void *_ud) {
- default_alloc_ud *ud = _ud;
- mem_block *block = ud->head;
+static void freefiledef(upb_refcounted *r) {
+ upb_filedef *f = (upb_filedef*)r;
+ size_t i;
- while (block) {
- void *to_free = block;
- block = block->next;
- free(to_free);
+ for(i = 0; i < upb_filedef_depcount(f); i++) {
+ upb_filedef_unref(upb_filedef_dep(f, i), f);
}
+
+ upb_inttable_uninit(&f->defs);
+ upb_inttable_uninit(&f->deps);
+ upb_gfree((void*)f->name);
+ upb_gfree((void*)f->package);
+ upb_gfree(f);
}
+const struct upb_refcounted_vtbl upb_filedef_vtbl = {visitfiledef, freefiledef};
-/* Standard error functions ***************************************************/
+upb_filedef *upb_filedef_new(const void *owner) {
+ upb_filedef *f = upb_gmalloc(sizeof(*f));
-static bool default_err(void *ud, const upb_status *status) {
- UPB_UNUSED(ud);
- UPB_UNUSED(status);
- return false;
-}
-
-static bool write_err_to(void *ud, const upb_status *status) {
- upb_status *copy_to = ud;
- upb_status_copy(copy_to, status);
- return false;
-}
+ if (!f) {
+ return NULL;
+ }
+ f->package = NULL;
+ f->name = NULL;
+ f->syntax = UPB_SYNTAX_PROTO2;
-/* upb_env ********************************************************************/
+ if (!upb_refcounted_init(upb_filedef_upcast_mutable(f), &upb_filedef_vtbl,
+ owner)) {
+ goto err;
+ }
-void upb_env_init(upb_env *e) {
- default_alloc_ud *ud = (default_alloc_ud*)&e->default_alloc_ud;
- e->ok_ = true;
- e->bytes_allocated = 0;
- e->cleanup_head = NULL;
+ if (!upb_inttable_init(&f->defs, UPB_CTYPE_CONSTPTR)) {
+ goto err;
+ }
- ud->head = NULL;
+ if (!upb_inttable_init(&f->deps, UPB_CTYPE_CONSTPTR)) {
+ goto err2;
+ }
- /* Set default functions. */
- upb_env_setallocfunc(e, default_alloc, ud);
- upb_env_seterrorfunc(e, default_err, NULL);
-}
+ return f;
-void upb_env_uninit(upb_env *e) {
- cleanup_ent *ent = e->cleanup_head;
- while (ent) {
- ent->cleanup(ent->ud);
- ent = ent->next;
- }
+err2:
+ upb_inttable_uninit(&f->defs);
- /* Must do this after running cleanup functions, because this will delete
- the memory we store our cleanup entries in! */
- if (e->alloc == default_alloc) {
- default_alloc_cleanup(e->alloc_ud);
- }
+err:
+ upb_gfree(f);
+ return NULL;
}
-UPB_FORCEINLINE void upb_env_setallocfunc(upb_env *e, upb_alloc_func *alloc,
- void *ud) {
- e->alloc = alloc;
- e->alloc_ud = ud;
+const char *upb_filedef_name(const upb_filedef *f) {
+ return f->name;
}
-UPB_FORCEINLINE void upb_env_seterrorfunc(upb_env *e, upb_error_func *func,
- void *ud) {
- e->err = func;
- e->err_ud = ud;
+const char *upb_filedef_package(const upb_filedef *f) {
+ return f->package;
}
-void upb_env_reporterrorsto(upb_env *e, upb_status *status) {
- e->err = write_err_to;
- e->err_ud = status;
+upb_syntax_t upb_filedef_syntax(const upb_filedef *f) {
+ return f->syntax;
}
-bool upb_env_ok(const upb_env *e) {
- return e->ok_;
+size_t upb_filedef_defcount(const upb_filedef *f) {
+ return upb_inttable_count(&f->defs);
}
-bool upb_env_reporterror(upb_env *e, const upb_status *status) {
- e->ok_ = false;
- return e->err(e->err_ud, status);
+size_t upb_filedef_depcount(const upb_filedef *f) {
+ return upb_inttable_count(&f->deps);
}
-bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud) {
- cleanup_ent *ent = upb_env_malloc(e, sizeof(cleanup_ent));
- if (!ent) return false;
-
- ent->cleanup = func;
- ent->ud = ud;
- ent->next = e->cleanup_head;
- e->cleanup_head = ent;
-
- return true;
-}
+const upb_def *upb_filedef_def(const upb_filedef *f, size_t i) {
+ upb_value v;
-void *upb_env_malloc(upb_env *e, size_t size) {
- e->bytes_allocated += size;
- if (e->alloc == seeded_alloc) {
- /* This is equivalent to the next branch, but allows inlining for a
- * measurable perf benefit. */
- return seeded_alloc(e->alloc_ud, NULL, 0, size);
+ if (upb_inttable_lookup32(&f->defs, i, &v)) {
+ return upb_value_getconstptr(v);
} else {
- return e->alloc(e->alloc_ud, NULL, 0, size);
+ return NULL;
}
}
-void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size) {
- char *ret;
- assert(oldsize <= size);
- ret = e->alloc(e->alloc_ud, ptr, oldsize, size);
-
-#ifndef NDEBUG
- /* Overwrite non-preserved memory to ensure callers are passing the oldsize
- * that they truly require. */
- memset(ret + oldsize, 0xff, size - oldsize);
-#endif
+const upb_filedef *upb_filedef_dep(const upb_filedef *f, size_t i) {
+ upb_value v;
- return ret;
+ if (upb_inttable_lookup32(&f->deps, i, &v)) {
+ return upb_value_getconstptr(v);
+ } else {
+ return NULL;
+ }
}
-size_t upb_env_bytesallocated(const upb_env *e) {
- return e->bytes_allocated;
+bool upb_filedef_setname(upb_filedef *f, const char *name, upb_status *s) {
+ name = upb_gstrdup(name);
+ if (!name) {
+ upb_upberr_setoom(s);
+ return false;
+ }
+ upb_gfree((void*)f->name);
+ f->name = name;
+ return true;
}
-
-/* upb_seededalloc ************************************************************/
-
-/* Be conservative and choose 16 in case anyone is using SSE. */
-static const size_t maxalign = 16;
-
-static size_t align_up(size_t size) {
- return ((size + maxalign - 1) / maxalign) * maxalign;
+bool upb_filedef_setpackage(upb_filedef *f, const char *package,
+ upb_status *s) {
+ if (!upb_isident(package, strlen(package), true, s)) return false;
+ package = upb_gstrdup(package);
+ if (!package) {
+ upb_upberr_setoom(s);
+ return false;
+ }
+ upb_gfree((void*)f->package);
+ f->package = package;
+ return true;
}
-UPB_FORCEINLINE static void *seeded_alloc(void *ud, void *ptr, size_t oldsize,
- size_t size) {
- upb_seededalloc *a = ud;
-
- size = align_up(size);
-
- assert(a->mem_limit >= a->mem_ptr);
+bool upb_filedef_setsyntax(upb_filedef *f, upb_syntax_t syntax,
+ upb_status *s) {
+ UPB_UNUSED(s);
+ if (syntax != UPB_SYNTAX_PROTO2 &&
+ syntax != UPB_SYNTAX_PROTO3) {
+ upb_status_seterrmsg(s, "Unknown syntax value.");
+ return false;
+ }
+ f->syntax = syntax;
- if (oldsize == 0 && size <= (size_t)(a->mem_limit - a->mem_ptr)) {
- /* Fast path: we can satisfy from the initial allocation. */
- void *ret = a->mem_ptr;
- a->mem_ptr += size;
- return ret;
- } else {
- char *chptr = ptr;
- /* Slow path: fallback to other allocator. */
- a->need_cleanup = true;
- /* Is `ptr` part of the user-provided initial block? Don't pass it to the
- * default allocator if so; otherwise, it may try to realloc() the block. */
- if (chptr >= a->mem_base && chptr < a->mem_limit) {
- void *ret;
- assert(chptr + oldsize <= a->mem_limit);
- ret = a->alloc(a->alloc_ud, NULL, 0, size);
- if (ret) memcpy(ret, ptr, oldsize);
- return ret;
- } else {
- return a->alloc(a->alloc_ud, ptr, oldsize, size);
+ {
+ /* Set all messages in this file to match. */
+ size_t i;
+ for (i = 0; i < upb_filedef_defcount(f); i++) {
+ /* Casting const away is safe since all defs in mutable filedef must
+ * also be mutable. */
+ upb_def *def = (upb_def*)upb_filedef_def(f, i);
+
+ upb_msgdef *m = upb_dyncast_msgdef_mutable(def);
+ if (m) {
+ m->syntax = syntax;
+ }
}
}
-}
-
-void upb_seededalloc_init(upb_seededalloc *a, void *mem, size_t len) {
- default_alloc_ud *ud = (default_alloc_ud*)&a->default_alloc_ud;
- a->mem_base = mem;
- a->mem_ptr = mem;
- a->mem_limit = (char*)mem + len;
- a->need_cleanup = false;
- a->returned_allocfunc = false;
-
- ud->head = NULL;
- upb_seededalloc_setfallbackalloc(a, default_alloc, ud);
+ return true;
}
-void upb_seededalloc_uninit(upb_seededalloc *a) {
- if (a->alloc == default_alloc && a->need_cleanup) {
- default_alloc_cleanup(a->alloc_ud);
+bool upb_filedef_adddef(upb_filedef *f, upb_def *def, const void *ref_donor,
+ upb_status *s) {
+ if (def->file) {
+ upb_status_seterrmsg(s, "Def is already part of another filedef.");
+ return false;
}
-}
-UPB_FORCEINLINE void upb_seededalloc_setfallbackalloc(upb_seededalloc *a,
- upb_alloc_func *alloc,
- void *ud) {
- assert(!a->returned_allocfunc);
- a->alloc = alloc;
- a->alloc_ud = ud;
+ if (upb_inttable_push(&f->defs, upb_value_constptr(def))) {
+ def->file = f;
+ upb_ref2(def, f);
+ upb_ref2(f, def);
+ if (ref_donor) upb_def_unref(def, ref_donor);
+ if (def->type == UPB_DEF_MSG) {
+ upb_downcast_msgdef_mutable(def)->syntax = f->syntax;
+ }
+ return true;
+ } else {
+ upb_upberr_setoom(s);
+ return false;
+ }
}
-upb_alloc_func *upb_seededalloc_getallocfunc(upb_seededalloc *a) {
- a->returned_allocfunc = true;
- return seeded_alloc;
+bool upb_filedef_adddep(upb_filedef *f, const upb_filedef *dep) {
+ if (upb_inttable_push(&f->deps, upb_value_constptr(dep))) {
+ /* Regular ref instead of ref2 because files can't form cycles. */
+ upb_filedef_ref(dep, f);
+ return true;
+ } else {
+ return false;
+ }
}
/*
** TODO(haberman): it's unclear whether a lot of the consistency checks should
-** assert() or return false.
+** UPB_ASSERT() or return false.
*/
-#include <stdlib.h>
#include <string.h>
+static void *upb_calloc(size_t size) {
+ void *mem = upb_gmalloc(size);
+ if (mem) {
+ memset(mem, 0, size);
+ }
+ return mem;
+}
/* Defined for the sole purpose of having a unique pointer value for
* UPB_NO_CLOSURE. */
@@ -1996,8 +2191,8 @@ static void freehandlers(upb_refcounted *r) {
upb_inttable_uninit(&h->cleanup_);
upb_msgdef_unref(h->msg, h);
- free(h->sub);
- free(h);
+ upb_gfree(h->sub);
+ upb_gfree(h);
}
static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit,
@@ -2073,7 +2268,7 @@ oom:
static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f,
upb_handlertype_t type) {
upb_selector_t sel;
- assert(!upb_handlers_isfrozen(h));
+ UPB_ASSERT(!upb_handlers_isfrozen(h));
if (upb_handlers_msgdef(h) != upb_fielddef_containingtype(f)) {
upb_status_seterrf(
&h->status_, "type mismatch: field %s does not belong to message %s",
@@ -2093,7 +2288,7 @@ static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f,
static upb_selector_t handlers_getsel(upb_handlers *h, const upb_fielddef *f,
upb_handlertype_t type) {
int32_t sel = trygetsel(h, f, type);
- assert(sel >= 0);
+ UPB_ASSERT(sel >= 0);
return sel;
}
@@ -2109,7 +2304,7 @@ static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f,
const void *closure_type;
const void **context_closure_type;
- assert(!upb_handlers_isfrozen(h));
+ UPB_ASSERT(!upb_handlers_isfrozen(h));
if (sel < 0) {
upb_status_seterrmsg(&h->status_,
@@ -2189,7 +2384,7 @@ const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f,
const void *ret;
upb_selector_t sel;
- assert(type != UPB_HANDLER_STRING);
+ UPB_ASSERT(type != UPB_HANDLER_STRING);
ret = h->top_closure_type;
if (upb_fielddef_isseq(f) &&
@@ -2244,17 +2439,23 @@ upb_handlers *upb_handlers_new(const upb_msgdef *md, const void *owner) {
int extra;
upb_handlers *h;
- assert(upb_msgdef_isfrozen(md));
+ UPB_ASSERT(upb_msgdef_isfrozen(md));
extra = sizeof(upb_handlers_tabent) * (md->selector_count - 1);
- h = calloc(sizeof(*h) + extra, 1);
+ h = upb_calloc(sizeof(*h) + extra);
if (!h) return NULL;
h->msg = md;
upb_msgdef_ref(h->msg, h);
upb_status_clear(&h->status_);
- h->sub = calloc(md->submsg_field_count, sizeof(*h->sub));
- if (!h->sub) goto oom;
+
+ if (md->submsg_field_count > 0) {
+ h->sub = upb_calloc(md->submsg_field_count * sizeof(*h->sub));
+ if (!h->sub) goto oom;
+ } else {
+ h->sub = 0;
+ }
+
if (!upb_refcounted_init(upb_handlers_upcast_mutable(h), &vtbl, owner))
goto oom;
if (!upb_inttable_init(&h->cleanup_, UPB_CTYPE_FPTR)) goto oom;
@@ -2287,18 +2488,18 @@ const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m,
r = upb_handlers_upcast_mutable(ret);
ok = upb_refcounted_freeze(&r, 1, NULL, UPB_MAX_HANDLER_DEPTH);
- UPB_ASSERT_VAR(ok, ok);
+ UPB_ASSERT(ok);
return ret;
}
const upb_status *upb_handlers_status(upb_handlers *h) {
- assert(!upb_handlers_isfrozen(h));
+ UPB_ASSERT(!upb_handlers_isfrozen(h));
return &h->status_;
}
void upb_handlers_clearerr(upb_handlers *h) {
- assert(!upb_handlers_isfrozen(h));
+ UPB_ASSERT(!upb_handlers_isfrozen(h));
upb_status_clear(&h->status_);
}
@@ -2334,16 +2535,16 @@ bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
upb_handlerattr *attr) {
- assert(!upb_handlers_isfrozen(h));
+ UPB_ASSERT(!upb_handlers_isfrozen(h));
return doset(h, UPB_ENDMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
(upb_func *)func, attr);
}
bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
const upb_handlers *sub) {
- assert(sub);
- assert(!upb_handlers_isfrozen(h));
- assert(upb_fielddef_issubmsg(f));
+ UPB_ASSERT(sub);
+ UPB_ASSERT(!upb_handlers_isfrozen(h));
+ UPB_ASSERT(upb_fielddef_issubmsg(f));
if (SUBH_F(h, f)) return false; /* Can't reset. */
if (upb_msgdef_upcast(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) {
return false;
@@ -2355,7 +2556,7 @@ bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
const upb_fielddef *f) {
- assert(upb_fielddef_issubmsg(f));
+ UPB_ASSERT(upb_fielddef_issubmsg(f));
return SUBH_F(h, f);
}
@@ -2381,7 +2582,7 @@ bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) {
return false;
}
ok = upb_inttable_insertptr(&h->cleanup_, p, upb_value_fptr(func));
- UPB_ASSERT_VAR(ok, ok);
+ UPB_ASSERT(ok);
return true;
}
@@ -2482,7 +2683,7 @@ upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) {
case UPB_TYPE_FLOAT: return UPB_HANDLER_FLOAT;
case UPB_TYPE_DOUBLE: return UPB_HANDLER_DOUBLE;
case UPB_TYPE_BOOL: return UPB_HANDLER_BOOL;
- default: assert(false); return -1; /* Invalid input. */
+ default: UPB_ASSERT(false); return -1; /* Invalid input. */
}
}
@@ -2545,7 +2746,7 @@ bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
*s = f->selector_base;
break;
}
- assert((size_t)*s < upb_fielddef_containingtype(f)->selector_count);
+ UPB_ASSERT((size_t)*s < upb_fielddef_containingtype(f)->selector_count);
return true;
}
@@ -2669,7 +2870,6 @@ bool upb_byteshandler_setendstr(upb_byteshandler *h,
#include <setjmp.h>
-#include <stdlib.h>
static void freeobj(upb_refcounted *o);
@@ -2745,8 +2945,31 @@ void upb_unlock();
/* UPB_DEBUG_REFS mode counts on being able to malloc() memory in some
* code-paths that can normally never fail, like upb_refcounted_ref(). Since
* we have no way to propagage out-of-memory errors back to the user, and since
- * these errors can only occur in UPB_DEBUG_REFS mode, we immediately fail. */
-#define CHECK_OOM(predicate) if (!(predicate)) { assert(predicate); exit(1); }
+ * these errors can only occur in UPB_DEBUG_REFS mode, we use an allocator that
+ * immediately aborts on failure (avoiding the global allocator, which might
+ * inject failures). */
+
+#include <stdlib.h>
+
+static void *upb_debugrefs_allocfunc(upb_alloc *alloc, void *ptr,
+ size_t oldsize, size_t size) {
+ UPB_UNUSED(alloc);
+ UPB_UNUSED(oldsize);
+ if (size == 0) {
+ free(ptr);
+ return NULL;
+ } else {
+ void *ret = realloc(ptr, size);
+
+ if (!ret) {
+ abort();
+ }
+
+ return ret;
+ }
+}
+
+upb_alloc upb_alloc_debugrefs = {&upb_debugrefs_allocfunc};
typedef struct {
int count; /* How many refs there are (duplicates only allowed for ref2). */
@@ -2754,8 +2977,7 @@ typedef struct {
} trackedref;
static trackedref *trackedref_new(bool is_ref2) {
- trackedref *ret = malloc(sizeof(*ret));
- CHECK_OOM(ret);
+ trackedref *ret = upb_malloc(&upb_alloc_debugrefs, sizeof(*ret));
ret->count = 1;
ret->is_ref2 = is_ref2;
return ret;
@@ -2764,7 +2986,7 @@ static trackedref *trackedref_new(bool is_ref2) {
static void track(const upb_refcounted *r, const void *owner, bool ref2) {
upb_value v;
- assert(owner);
+ UPB_ASSERT(owner);
if (owner == UPB_UNTRACKED_REF) return;
upb_lock();
@@ -2775,20 +2997,20 @@ static void track(const upb_refcounted *r, const void *owner, bool ref2) {
* tracking behavior we get with regular refs. Since ref2s only happen
* inside upb, we'll accept this limitation until/unless there is a really
* difficult upb-internal bug that can't be figured out without it. */
- assert(ref2);
- assert(ref->is_ref2);
+ UPB_ASSERT(ref2);
+ UPB_ASSERT(ref->is_ref2);
ref->count++;
} else {
trackedref *ref = trackedref_new(ref2);
- bool ok = upb_inttable_insertptr(r->refs, owner, upb_value_ptr(ref));
- CHECK_OOM(ok);
+ upb_inttable_insertptr2(r->refs, owner, upb_value_ptr(ref),
+ &upb_alloc_debugrefs);
if (ref2) {
/* We know this cast is safe when it is a ref2, because it's coming from
* another refcounted object. */
const upb_refcounted *from = owner;
- assert(!upb_inttable_lookupptr(from->ref2s, r, NULL));
- ok = upb_inttable_insertptr(from->ref2s, r, upb_value_ptr(NULL));
- CHECK_OOM(ok);
+ UPB_ASSERT(!upb_inttable_lookupptr(from->ref2s, r, NULL));
+ upb_inttable_insertptr2(from->ref2s, r, upb_value_ptr(NULL),
+ &upb_alloc_debugrefs);
}
}
upb_unlock();
@@ -2799,15 +3021,15 @@ static void untrack(const upb_refcounted *r, const void *owner, bool ref2) {
bool found;
trackedref *ref;
- assert(owner);
+ UPB_ASSERT(owner);
if (owner == UPB_UNTRACKED_REF) return;
upb_lock();
found = upb_inttable_lookupptr(r->refs, owner, &v);
/* This assert will fail if an owner attempts to release a ref it didn't have. */
- UPB_ASSERT_VAR(found, found);
+ UPB_ASSERT(found);
ref = upb_value_getptr(v);
- assert(ref->is_ref2 == ref2);
+ UPB_ASSERT(ref->is_ref2 == ref2);
if (--ref->count == 0) {
free(ref);
upb_inttable_removeptr(r->refs, owner, NULL);
@@ -2816,7 +3038,7 @@ static void untrack(const upb_refcounted *r, const void *owner, bool ref2) {
* another refcounted object. */
const upb_refcounted *from = owner;
bool removed = upb_inttable_removeptr(from->ref2s, r, NULL);
- assert(removed);
+ UPB_ASSERT(removed);
}
}
upb_unlock();
@@ -2829,9 +3051,9 @@ static void checkref(const upb_refcounted *r, const void *owner, bool ref2) {
upb_lock();
found = upb_inttable_lookupptr(r->refs, owner, &v);
- UPB_ASSERT_VAR(found, found);
+ UPB_ASSERT(found);
ref = upb_value_getptr(v);
- assert(ref->is_ref2 == ref2);
+ UPB_ASSERT(ref->is_ref2 == ref2);
upb_unlock();
}
@@ -2846,19 +3068,17 @@ static void getref2s(const upb_refcounted *owner, upb_inttable *tab) {
upb_value v;
upb_value count;
trackedref *ref;
- bool ok;
bool found;
upb_refcounted *to = (upb_refcounted*)upb_inttable_iter_key(&i);
/* To get the count we need to look in the target's table. */
found = upb_inttable_lookupptr(to->refs, owner, &v);
- assert(found);
+ UPB_ASSERT(found);
ref = upb_value_getptr(v);
count = upb_value_int32(ref->count);
- ok = upb_inttable_insertptr(tab, to, count);
- CHECK_OOM(ok);
+ upb_inttable_insertptr2(tab, to, count, &upb_alloc_debugrefs);
}
upb_unlock();
}
@@ -2876,62 +3096,50 @@ static void visit_check(const upb_refcounted *obj, const upb_refcounted *subobj,
bool removed;
int32_t newcount;
- assert(obj == s->obj);
- assert(subobj);
+ UPB_ASSERT(obj == s->obj);
+ UPB_ASSERT(subobj);
removed = upb_inttable_removeptr(ref2, subobj, &v);
/* The following assertion will fail if the visit() function visits a subobj
* that it did not have a ref2 on, or visits the same subobj too many times. */
- assert(removed);
+ UPB_ASSERT(removed);
newcount = upb_value_getint32(v) - 1;
if (newcount > 0) {
- upb_inttable_insert(ref2, (uintptr_t)subobj, upb_value_int32(newcount));
+ upb_inttable_insert2(ref2, (uintptr_t)subobj, upb_value_int32(newcount),
+ &upb_alloc_debugrefs);
}
}
static void visit(const upb_refcounted *r, upb_refcounted_visit *v,
void *closure) {
- bool ok;
-
/* In DEBUG_REFS mode we know what existing ref2 refs there are, so we know
* exactly the set of nodes that visit() should visit. So we verify visit()'s
* correctness here. */
check_state state;
state.obj = r;
- ok = upb_inttable_init(&state.ref2, UPB_CTYPE_INT32);
- CHECK_OOM(ok);
+ upb_inttable_init2(&state.ref2, UPB_CTYPE_INT32, &upb_alloc_debugrefs);
getref2s(r, &state.ref2);
/* This should visit any children in the ref2 table. */
if (r->vtbl->visit) r->vtbl->visit(r, visit_check, &state);
/* This assertion will fail if the visit() function missed any children. */
- assert(upb_inttable_count(&state.ref2) == 0);
- upb_inttable_uninit(&state.ref2);
+ UPB_ASSERT(upb_inttable_count(&state.ref2) == 0);
+ upb_inttable_uninit2(&state.ref2, &upb_alloc_debugrefs);
if (r->vtbl->visit) r->vtbl->visit(r, v, closure);
}
-static bool trackinit(upb_refcounted *r) {
- r->refs = malloc(sizeof(*r->refs));
- r->ref2s = malloc(sizeof(*r->ref2s));
- if (!r->refs || !r->ref2s) goto err1;
-
- if (!upb_inttable_init(r->refs, UPB_CTYPE_PTR)) goto err1;
- if (!upb_inttable_init(r->ref2s, UPB_CTYPE_PTR)) goto err2;
- return true;
-
-err2:
- upb_inttable_uninit(r->refs);
-err1:
- free(r->refs);
- free(r->ref2s);
- return false;
+static void trackinit(upb_refcounted *r) {
+ r->refs = upb_malloc(&upb_alloc_debugrefs, sizeof(*r->refs));
+ r->ref2s = upb_malloc(&upb_alloc_debugrefs, sizeof(*r->ref2s));
+ upb_inttable_init2(r->refs, UPB_CTYPE_PTR, &upb_alloc_debugrefs);
+ upb_inttable_init2(r->ref2s, UPB_CTYPE_PTR, &upb_alloc_debugrefs);
}
static void trackfree(const upb_refcounted *r) {
- upb_inttable_uninit(r->refs);
- upb_inttable_uninit(r->ref2s);
- free(r->refs);
- free(r->ref2s);
+ upb_inttable_uninit2(r->refs, &upb_alloc_debugrefs);
+ upb_inttable_uninit2(r->ref2s, &upb_alloc_debugrefs);
+ upb_free(&upb_alloc_debugrefs, r->refs);
+ upb_free(&upb_alloc_debugrefs, r->ref2s);
}
#else
@@ -2954,9 +3162,8 @@ static void checkref(const upb_refcounted *r, const void *owner, bool ref2) {
UPB_UNUSED(ref2);
}
-static bool trackinit(upb_refcounted *r) {
+static void trackinit(upb_refcounted *r) {
UPB_UNUSED(r);
- return true;
}
static void trackfree(const upb_refcounted *r) {
@@ -3023,7 +3230,7 @@ static uint64_t trygetattr(const tarjan *t, const upb_refcounted *r) {
static uint64_t getattr(const tarjan *t, const upb_refcounted *r) {
upb_value v;
bool found = upb_inttable_lookupptr(&t->objattr, r, &v);
- UPB_ASSERT_VAR(found, found);
+ UPB_ASSERT(found);
return upb_value_getuint64(v);
}
@@ -3037,13 +3244,13 @@ static color_t color(tarjan *t, const upb_refcounted *r) {
}
static void set_gray(tarjan *t, const upb_refcounted *r) {
- assert(color(t, r) == BLACK);
+ UPB_ASSERT(color(t, r) == BLACK);
setattr(t, r, GRAY);
}
/* Pushes an obj onto the Tarjan stack and sets it to GREEN. */
static void push(tarjan *t, const upb_refcounted *r) {
- assert(color(t, r) == BLACK || color(t, r) == GRAY);
+ UPB_ASSERT(color(t, r) == BLACK || color(t, r) == GRAY);
/* This defines the attr layout for the GREEN state. "index" and "lowlink"
* get 31 bits, which is plenty (limit of 2B objects frozen at a time). */
setattr(t, r, GREEN | (t->index << 2) | (t->index << 33));
@@ -3058,7 +3265,7 @@ static void push(tarjan *t, const upb_refcounted *r) {
* SCC group. */
static upb_refcounted *pop(tarjan *t) {
upb_refcounted *r = upb_value_getptr(upb_inttable_pop(&t->stack));
- assert(color(t, r) == GREEN);
+ UPB_ASSERT(color(t, r) == GREEN);
/* This defines the attr layout for nodes in the WHITE state.
* Top of group stack is [group, NULL]; we point at group. */
setattr(t, r, WHITE | (upb_inttable_count(&t->groups) - 2) << 8);
@@ -3066,19 +3273,19 @@ static upb_refcounted *pop(tarjan *t) {
}
static void tarjan_newgroup(tarjan *t) {
- uint32_t *group = malloc(sizeof(*group));
+ uint32_t *group = upb_gmalloc(sizeof(*group));
if (!group) oom(t);
/* Push group and empty group leader (we'll fill in leader later). */
if (!upb_inttable_push(&t->groups, upb_value_ptr(group)) ||
!upb_inttable_push(&t->groups, upb_value_ptr(NULL))) {
- free(group);
+ upb_gfree(group);
oom(t);
}
*group = 0;
}
static uint32_t idx(tarjan *t, const upb_refcounted *r) {
- assert(color(t, r) == GREEN);
+ UPB_ASSERT(color(t, r) == GREEN);
return (getattr(t, r) >> 2) & 0x7FFFFFFF;
}
@@ -3091,7 +3298,7 @@ static uint32_t lowlink(tarjan *t, const upb_refcounted *r) {
}
static void set_lowlink(tarjan *t, const upb_refcounted *r, uint32_t lowlink) {
- assert(color(t, r) == GREEN);
+ UPB_ASSERT(color(t, r) == GREEN);
setattr(t, r, ((uint64_t)lowlink << 33) | (getattr(t, r) & 0x1FFFFFFFF));
}
@@ -3100,10 +3307,10 @@ static uint32_t *group(tarjan *t, upb_refcounted *r) {
upb_value v;
bool found;
- assert(color(t, r) == WHITE);
+ UPB_ASSERT(color(t, r) == WHITE);
groupnum = getattr(t, r) >> 8;
found = upb_inttable_lookup(&t->groups, groupnum, &v);
- UPB_ASSERT_VAR(found, found);
+ UPB_ASSERT(found);
return upb_value_getptr(v);
}
@@ -3114,10 +3321,10 @@ static upb_refcounted *groupleader(tarjan *t, upb_refcounted *r) {
upb_value v;
bool found;
- assert(color(t, r) == WHITE);
+ UPB_ASSERT(color(t, r) == WHITE);
leader_slot = (getattr(t, r) >> 8) + 1;
found = upb_inttable_lookup(&t->groups, leader_slot, &v);
- UPB_ASSERT_VAR(found, found);
+ UPB_ASSERT(found);
if (upb_value_getptr(v)) {
return upb_value_getptr(v);
} else {
@@ -3177,7 +3384,7 @@ static void do_tarjan(const upb_refcounted *obj, tarjan *t) {
static void crossref(const upb_refcounted *r, const upb_refcounted *subobj,
void *_t) {
tarjan *t = _t;
- assert(color(t, r) > BLACK);
+ UPB_ASSERT(color(t, r) > BLACK);
if (color(t, subobj) > BLACK && r->group != subobj->group) {
/* Previously this ref was not reflected in subobj->group because they
* were in the same group; now that they are split a ref must be taken. */
@@ -3245,13 +3452,13 @@ static bool freeze(upb_refcounted *const*roots, int n, upb_status *s,
upb_refcounted *move = obj->next;
if (obj == move) {
/* Removing the last object from a group. */
- assert(*obj->group == obj->individual_count);
- free(obj->group);
+ UPB_ASSERT(*obj->group == obj->individual_count);
+ upb_gfree(obj->group);
} else {
obj->next = move->next;
/* This may decrease to zero; we'll collect GRAY objects (if any) that
* remain in the group in the third pass. */
- assert(*move->group >= move->individual_count);
+ UPB_ASSERT(*move->group >= move->individual_count);
*move->group -= move->individual_count;
}
@@ -3264,7 +3471,7 @@ static bool freeze(upb_refcounted *const*roots, int n, upb_status *s,
*move->group = move->individual_count;
} else {
/* Group already has at least one object in it. */
- assert(leader->group == group(&t, move));
+ UPB_ASSERT(leader->group == group(&t, move));
move->group = group(&t, move);
move->next = leader->next;
leader->next = move;
@@ -3302,7 +3509,7 @@ static bool freeze(upb_refcounted *const*roots, int n, upb_status *s,
/* We eagerly free() the group's count (since we can't easily determine
* the group's remaining size it's the easiest way to ensure it gets
* done). */
- free(obj->group);
+ upb_gfree(obj->group);
/* Visit to release ref2's (done in a separate pass since release_ref2
* depends on o->group being unmodified so it can test merged()). */
@@ -3322,7 +3529,7 @@ err4:
if (!ret) {
upb_inttable_begin(&iter, &t.groups);
for(; !upb_inttable_done(&iter); upb_inttable_next(&iter))
- free(upb_value_getptr(upb_inttable_iter_value(&iter)));
+ upb_gfree(upb_value_getptr(upb_inttable_iter_value(&iter)));
}
upb_inttable_uninit(&t.groups);
err3:
@@ -3346,7 +3553,7 @@ static void merge(upb_refcounted *r, upb_refcounted *from) {
if (merged(r, from)) return;
*r->group += *from->group;
- free(from->group);
+ upb_gfree(from->group);
base = from;
/* Set all refcount pointers in the "from" chain to the merged refcount.
@@ -3354,7 +3561,7 @@ static void merge(upb_refcounted *r, upb_refcounted *from) {
* TODO(haberman): this linear algorithm can result in an overall O(n^2) bound
* if the user continuously extends a group by one object. Prevent this by
* using one of the techniques in this paper:
- * ftp://www.ncedc.org/outgoing/geomorph/dino/orals/p245-tarjan.pdf */
+ * http://bioinfo.ict.ac.cn/~dbu/AlgorithmCourses/Lectures/Union-Find-Tarjan.pdf */
do { from->group = r->group; } while ((from = from->next) != base);
/* Merge the two circularly linked lists by swapping their next pointers. */
@@ -3371,7 +3578,7 @@ static void release_ref2(const upb_refcounted *obj,
UPB_UNUSED(closure);
untrack(subobj, obj, true);
if (!merged(obj, subobj)) {
- assert(subobj->is_frozen);
+ UPB_ASSERT(subobj->is_frozen);
unref(subobj);
}
}
@@ -3380,7 +3587,7 @@ static void unref(const upb_refcounted *r) {
if (unrefgroup(r->group)) {
const upb_refcounted *o;
- free(r->group);
+ upb_gfree(r->group);
/* In two passes, since release_ref2 needs a guarantee that any subobjs
* are alive. */
@@ -3390,7 +3597,7 @@ static void unref(const upb_refcounted *r) {
o = r;
do {
const upb_refcounted *next = o->next;
- assert(o->is_frozen || o->individual_count == 0);
+ UPB_ASSERT(o->is_frozen || o->individual_count == 0);
freeobj((upb_refcounted*)o);
o = next;
} while(o != r);
@@ -3414,9 +3621,9 @@ bool upb_refcounted_init(upb_refcounted *r,
* basically every program using upb. */
const int x = 1;
#ifdef UPB_BIG_ENDIAN
- assert(*(char*)&x != 1);
+ UPB_ASSERT(*(char*)&x != 1);
#else
- assert(*(char*)&x == 1);
+ UPB_ASSERT(*(char*)&x == 1);
#endif
#endif
@@ -3424,13 +3631,10 @@ bool upb_refcounted_init(upb_refcounted *r,
r->vtbl = vtbl;
r->individual_count = 0;
r->is_frozen = false;
- r->group = malloc(sizeof(*r->group));
+ r->group = upb_gmalloc(sizeof(*r->group));
if (!r->group) return false;
*r->group = 0;
- if (!trackinit(r)) {
- free(r->group);
- return false;
- }
+ trackinit(r);
upb_refcounted_ref(r, owner);
return true;
}
@@ -3454,7 +3658,7 @@ void upb_refcounted_unref(const upb_refcounted *r, const void *owner) {
}
void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from) {
- assert(!from->is_frozen); /* Non-const pointer implies this. */
+ UPB_ASSERT(!from->is_frozen); /* Non-const pointer implies this. */
track(r, from, true);
if (r->is_frozen) {
refgroup(r->group);
@@ -3464,18 +3668,18 @@ void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from) {
}
void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from) {
- assert(!from->is_frozen); /* Non-const pointer implies this. */
+ UPB_ASSERT(!from->is_frozen); /* Non-const pointer implies this. */
untrack(r, from, true);
if (r->is_frozen) {
unref(r);
} else {
- assert(merged(r, from));
+ UPB_ASSERT(merged(r, from));
}
}
void upb_refcounted_donateref(
const upb_refcounted *r, const void *from, const void *to) {
- assert(from != to);
+ UPB_ASSERT(from != to);
if (to != NULL)
upb_refcounted_ref(r, to);
if (from != NULL)
@@ -3489,15 +3693,16 @@ void upb_refcounted_checkref(const upb_refcounted *r, const void *owner) {
bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s,
int maxdepth) {
int i;
+ bool ret;
for (i = 0; i < n; i++) {
- assert(!roots[i]->is_frozen);
+ UPB_ASSERT(!roots[i]->is_frozen);
}
- return freeze(roots, n, s, maxdepth);
+ ret = freeze(roots, n, s, maxdepth);
+ UPB_ASSERT(!s || ret == upb_ok(s));
+ return ret;
}
-#include <stdlib.h>
-
/* Fallback implementation if the shim is not specialized by the JIT. */
#define SHIM_WRITER(type, ctype) \
bool upb_shim_set ## type (void *c, const void *hd, ctype val) { \
@@ -3523,14 +3728,14 @@ bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset,
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
bool ok;
- upb_shim_data *d = malloc(sizeof(*d));
+ upb_shim_data *d = upb_gmalloc(sizeof(*d));
if (!d) return false;
d->offset = offset;
d->hasbit = hasbit;
upb_handlerattr_sethandlerdata(&attr, d);
upb_handlerattr_setalwaysok(&attr, true);
- upb_handlers_addcleanup(h, d, free);
+ upb_handlers_addcleanup(h, d, upb_gfree);
#define TYPE(u, l) \
case UPB_TYPE_##u: \
@@ -3547,7 +3752,7 @@ bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset,
TYPE(DOUBLE, double);
TYPE(FLOAT, float);
TYPE(BOOL, bool);
- default: assert(false); break;
+ default: UPB_ASSERT(false); break;
}
#undef TYPE
@@ -3581,7 +3786,6 @@ const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s,
}
-#include <stdlib.h>
#include <string.h>
static void upb_symtab_free(upb_refcounted *r) {
@@ -3593,13 +3797,17 @@ static void upb_symtab_free(upb_refcounted *r) {
upb_def_unref(def, s);
}
upb_strtable_uninit(&s->symtab);
- free(s);
+ upb_gfree(s);
}
-
upb_symtab *upb_symtab_new(const void *owner) {
static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_symtab_free};
- upb_symtab *s = malloc(sizeof(*s));
+
+ upb_symtab *s = upb_gmalloc(sizeof(*s));
+ if (!s) {
+ return NULL;
+ }
+
upb_refcounted_init(upb_symtab_upcast_mutable(s), &vtbl, owner);
upb_strtable_init(&s->symtab, UPB_CTYPE_PTR);
return s;
@@ -3609,13 +3817,13 @@ void upb_symtab_freeze(upb_symtab *s) {
upb_refcounted *r;
bool ok;
- assert(!upb_symtab_isfrozen(s));
+ UPB_ASSERT(!upb_symtab_isfrozen(s));
r = upb_symtab_upcast_mutable(s);
/* The symtab does not take ref2's (see refcounted.h) on the defs, because
* defs cannot refer back to the table and therefore cannot create cycles. So
* 0 will suffice for maxdepth here. */
ok = upb_refcounted_freeze(&r, 1, NULL, 0);
- UPB_ASSERT_VAR(ok, ok);
+ UPB_ASSERT(ok);
}
const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym) {
@@ -3653,7 +3861,7 @@ static upb_def *upb_resolvename(const upb_strtable *t,
/* Remove components from base until we find an entry or run out.
* TODO: This branch is totally broken, but currently not used. */
(void)base;
- assert(false);
+ UPB_ASSERT(false);
return NULL;
}
}
@@ -3715,7 +3923,7 @@ static bool upb_resolve_dfs(const upb_def *def, upb_strtable *addtab,
upb_value v;
const upb_msgdef *m;
- assert(upb_def_isfrozen(def));
+ UPB_ASSERT(upb_def_isfrozen(def));
if (def->type == UPB_DEF_FIELD) continue;
if (upb_strtable_lookup(addtab, upb_def_fullname(def), &v)) {
need_dup = true;
@@ -3773,15 +3981,24 @@ oom:
/* TODO(haberman): we need a lot more testing of error conditions.
* The came_from_user stuff in particular is not tested. */
-bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor,
- upb_status *status) {
- int i;
+static bool symtab_add(upb_symtab *s, upb_def *const*defs, size_t n,
+ void *ref_donor, upb_refcounted *freeze_also,
+ upb_status *status) {
+ size_t i;
+ size_t add_n;
+ size_t freeze_n;
upb_strtable_iter iter;
+ upb_refcounted **add_objs = NULL;
upb_def **add_defs = NULL;
+ size_t add_objs_size;
upb_strtable addtab;
upb_inttable seen;
- assert(!upb_symtab_isfrozen(s));
+ if (n == 0 && !freeze_also) {
+ return true;
+ }
+
+ UPB_ASSERT(!upb_symtab_isfrozen(s));
if (!upb_strtable_init(&addtab, UPB_CTYPE_PTR)) {
upb_status_seterrmsg(status, "out of memory");
return false;
@@ -3797,7 +4014,7 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor,
upb_status_seterrmsg(status, "added defs must be mutable");
goto err;
}
- assert(!upb_def_isfrozen(def));
+ UPB_ASSERT(!upb_def_isfrozen(def));
fullname = upb_def_fullname(def);
if (!fullname) {
upb_status_seterrmsg(
@@ -3841,7 +4058,7 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor,
if (!f) continue;
msgname = upb_fielddef_containingtypename(f);
/* We validated this earlier in this function. */
- assert(msgname);
+ UPB_ASSERT(msgname);
/* If the extendee name is absolutely qualified, move past the initial ".".
* TODO(haberman): it is not obvious what it would mean if this was not
@@ -3922,15 +4139,38 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor,
}
}
- /* We need an array of the defs in addtab, for passing to upb_def_freeze. */
- add_defs = malloc(sizeof(void*) * upb_strtable_count(&addtab));
+ /* We need an array of the defs in addtab, for passing to
+ * upb_refcounted_freeze(). */
+ add_objs_size = upb_strtable_count(&addtab);
+ if (freeze_also) {
+ add_objs_size++;
+ }
+
+ add_defs = upb_gmalloc(sizeof(void*) * add_objs_size);
if (add_defs == NULL) goto oom_err;
upb_strtable_begin(&iter, &addtab);
- for (n = 0; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
- add_defs[n++] = upb_value_getptr(upb_strtable_iter_value(&iter));
+ for (add_n = 0; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
+ add_defs[add_n++] = upb_value_getptr(upb_strtable_iter_value(&iter));
+ }
+
+ /* Validate defs. */
+ if (!_upb_def_validate(add_defs, add_n, status)) {
+ goto err;
+ }
+
+ /* Cheat a little and give the array a new type.
+ * This is probably undefined behavior, but this code will be deleted soon. */
+ add_objs = (upb_refcounted**)add_defs;
+
+ freeze_n = add_n;
+ if (freeze_also) {
+ add_objs[freeze_n++] = freeze_also;
}
- if (!upb_def_freeze(add_defs, n, status)) goto err;
+ if (!upb_refcounted_freeze(add_objs, freeze_n, status,
+ UPB_MAX_MESSAGE_DEPTH * 2)) {
+ goto err;
+ }
/* This must be delayed until all errors have been detected, since error
* recovery code uses this table to cleanup defs. */
@@ -3938,8 +4178,8 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor,
/* TODO(haberman) we don't properly handle errors after this point (like
* OOM in upb_strtable_insert() below). */
- for (i = 0; i < n; i++) {
- upb_def *def = add_defs[i];
+ for (i = 0; i < add_n; i++) {
+ upb_def *def = (upb_def*)add_objs[i];
const char *name = upb_def_fullname(def);
upb_value v;
bool success;
@@ -3949,9 +4189,9 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor,
upb_def_unref(def, s);
}
success = upb_strtable_insert(&s->symtab, name, upb_value_ptr(def));
- UPB_ASSERT_VAR(success, success == true);
+ UPB_ASSERT(success == true);
}
- free(add_defs);
+ upb_gfree(add_defs);
return true;
oom_err:
@@ -3972,11 +4212,40 @@ err: {
}
}
upb_strtable_uninit(&addtab);
- free(add_defs);
- assert(!upb_ok(status));
+ upb_gfree(add_defs);
+ UPB_ASSERT(!upb_ok(status));
return false;
}
+bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, size_t n,
+ void *ref_donor, upb_status *status) {
+ return symtab_add(s, defs, n, ref_donor, NULL, status);
+}
+
+bool upb_symtab_addfile(upb_symtab *s, upb_filedef *file, upb_status *status) {
+ size_t n;
+ size_t i;
+ upb_def **defs;
+ bool ret;
+
+ n = upb_filedef_defcount(file);
+ defs = upb_gmalloc(sizeof(*defs) * n);
+
+ if (defs == NULL) {
+ upb_status_seterrmsg(status, "Out of memory");
+ return false;
+ }
+
+ for (i = 0; i < n; i++) {
+ defs[i] = upb_filedef_mutabledef(file, i);
+ }
+
+ ret = symtab_add(s, defs, n, NULL, upb_filedef_upcast_mutable(file), status);
+
+ upb_gfree(defs);
+ return ret;
+}
+
/* Iteration. */
static void advance_to_matching(upb_symtab_iter *iter) {
@@ -4015,7 +4284,6 @@ const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) {
*/
-#include <stdlib.h>
#include <string.h>
#define UPB_MAXARRSIZE 16 /* 64k. */
@@ -4024,6 +4292,12 @@ const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) {
#define ARRAY_SIZE(x) \
((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
+static void upb_check_alloc(upb_table *t, upb_alloc *a) {
+ UPB_UNUSED(t);
+ UPB_UNUSED(a);
+ UPB_ASSERT_DEBUGVAR(t->alloc == a);
+}
+
static const double MAX_LOAD = 0.85;
/* The minimum utilization of the array part of a mixed hash/array table. This
@@ -4041,11 +4315,11 @@ int log2ceil(uint64_t v) {
return UPB_MIN(UPB_MAXARRSIZE, ret);
}
-char *upb_strdup(const char *s) {
- return upb_strdup2(s, strlen(s));
+char *upb_strdup(const char *s, upb_alloc *a) {
+ return upb_strdup2(s, strlen(s), a);
}
-char *upb_strdup2(const char *s, size_t len) {
+char *upb_strdup2(const char *s, size_t len, upb_alloc *a) {
size_t n;
char *p;
@@ -4054,7 +4328,7 @@ char *upb_strdup2(const char *s, size_t len) {
/* Always null-terminate, even if binary data; but don't rely on the input to
* have a null-terminating byte since it may be a raw binary buffer. */
n = len + 1;
- p = malloc(n);
+ p = upb_malloc(a, n);
if (p) {
memcpy(p, s, len);
p[len] = 0;
@@ -4095,19 +4369,27 @@ static upb_tabent *mutable_entries(upb_table *t) {
}
static bool isfull(upb_table *t) {
- return (double)(t->count + 1) / upb_table_size(t) > MAX_LOAD;
+ if (upb_table_size(t) == 0) {
+ return true;
+ } else {
+ return ((double)(t->count + 1) / upb_table_size(t)) > MAX_LOAD;
+ }
}
-static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2) {
+static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2,
+ upb_alloc *a) {
size_t bytes;
t->count = 0;
t->ctype = ctype;
t->size_lg2 = size_lg2;
t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
+#ifndef NDEBUG
+ t->alloc = a;
+#endif
bytes = upb_table_size(t) * sizeof(upb_tabent);
if (bytes > 0) {
- t->entries = malloc(bytes);
+ t->entries = upb_malloc(a, bytes);
if (!t->entries) return false;
memset(mutable_entries(t), 0, bytes);
} else {
@@ -4116,11 +4398,14 @@ static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2) {
return true;
}
-static void uninit(upb_table *t) { free(mutable_entries(t)); }
+static void uninit(upb_table *t, upb_alloc *a) {
+ upb_check_alloc(t, a);
+ upb_free(a, mutable_entries(t));
+}
static upb_tabent *emptyent(upb_table *t) {
upb_tabent *e = mutable_entries(t) + upb_table_size(t);
- while (1) { if (upb_tabent_isempty(--e)) return e; assert(e > t->entries); }
+ while (1) { if (upb_tabent_isempty(--e)) return e; UPB_ASSERT(e > t->entries); }
}
static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) {
@@ -4165,10 +4450,8 @@ static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
upb_tabent *mainpos_e;
upb_tabent *our_e;
- UPB_UNUSED(eql);
- UPB_UNUSED(key);
- assert(findentry(t, key, hash, eql) == NULL);
- assert(val.ctype == t->ctype);
+ UPB_ASSERT(findentry(t, key, hash, eql) == NULL);
+ UPB_ASSERT_DEBUGVAR(val.ctype == t->ctype);
t->count++;
mainpos_e = getentry_mutable(t, hash);
@@ -4195,7 +4478,7 @@ static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
*new_e = *mainpos_e; /* copies next. */
while (chain->next != mainpos_e) {
chain = (upb_tabent*)chain->next;
- assert(chain);
+ UPB_ASSERT(chain);
}
chain->next = new_e;
our_e = mainpos_e;
@@ -4204,7 +4487,7 @@ static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
}
our_e->key = tabkey;
our_e->val.val = val.val;
- assert(findentry(t, key, hash, eql) == our_e);
+ UPB_ASSERT(findentry(t, key, hash, eql) == our_e);
}
static bool rm(upb_table *t, lookupkey_t key, upb_value *val,
@@ -4214,38 +4497,33 @@ static bool rm(upb_table *t, lookupkey_t key, upb_value *val,
if (eql(chain->key, key)) {
/* Element to remove is at the head of its chain. */
t->count--;
- if (val) {
- _upb_value_setval(val, chain->val.val, t->ctype);
- }
+ if (val) _upb_value_setval(val, chain->val.val, t->ctype);
+ if (removed) *removed = chain->key;
if (chain->next) {
upb_tabent *move = (upb_tabent*)chain->next;
*chain = *move;
- if (removed) *removed = move->key;
move->key = 0; /* Make the slot empty. */
} else {
- if (removed) *removed = chain->key;
chain->key = 0; /* Make the slot empty. */
}
return true;
} else {
/* Element to remove is either in a non-head position or not in the
* table. */
- while (chain->next && !eql(chain->next->key, key))
+ while (chain->next && !eql(chain->next->key, key)) {
chain = (upb_tabent*)chain->next;
+ }
if (chain->next) {
/* Found element to remove. */
- upb_tabent *rm;
-
- if (val) {
- _upb_value_setval(val, chain->next->val.val, t->ctype);
- }
- rm = (upb_tabent*)chain->next;
+ upb_tabent *rm = (upb_tabent*)chain->next;
+ t->count--;
+ if (val) _upb_value_setval(val, chain->next->val.val, t->ctype);
if (removed) *removed = rm->key;
- rm->key = 0;
+ rm->key = 0; /* Make the slot empty. */
chain->next = rm->next;
- t->count--;
return true;
} else {
+ /* Element to remove is not in the table. */
return false;
}
}
@@ -4269,8 +4547,8 @@ static size_t begin(const upb_table *t) {
/* A simple "subclass" of upb_table that only adds a hash function for strings. */
-static upb_tabkey strcopy(lookupkey_t k2) {
- char *str = malloc(k2.str.len + sizeof(uint32_t) + 1);
+static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) {
+ char *str = upb_malloc(a, k2.str.len + sizeof(uint32_t) + 1);
if (str == NULL) return 0;
memcpy(str, &k2.str.len, sizeof(uint32_t));
memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len + 1);
@@ -4289,51 +4567,56 @@ static bool streql(upb_tabkey k1, lookupkey_t k2) {
return len == k2.str.len && memcmp(str, k2.str.str, len) == 0;
}
-bool upb_strtable_init(upb_strtable *t, upb_ctype_t ctype) {
- return init(&t->t, ctype, 2);
+bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) {
+ return init(&t->t, ctype, 2, a);
}
-void upb_strtable_uninit(upb_strtable *t) {
+void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) {
size_t i;
for (i = 0; i < upb_table_size(&t->t); i++)
- free((void*)t->t.entries[i].key);
- uninit(&t->t);
+ upb_free(a, (void*)t->t.entries[i].key);
+ uninit(&t->t, a);
}
-bool upb_strtable_resize(upb_strtable *t, size_t size_lg2) {
+bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) {
upb_strtable new_table;
upb_strtable_iter i;
- if (!init(&new_table.t, t->t.ctype, size_lg2))
+ upb_check_alloc(&t->t, a);
+
+ if (!init(&new_table.t, t->t.ctype, size_lg2, a))
return false;
upb_strtable_begin(&i, t);
for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) {
- upb_strtable_insert2(
+ upb_strtable_insert3(
&new_table,
upb_strtable_iter_key(&i),
upb_strtable_iter_keylength(&i),
- upb_strtable_iter_value(&i));
+ upb_strtable_iter_value(&i),
+ a);
}
- upb_strtable_uninit(t);
+ upb_strtable_uninit2(t, a);
*t = new_table;
return true;
}
-bool upb_strtable_insert2(upb_strtable *t, const char *k, size_t len,
- upb_value v) {
+bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len,
+ upb_value v, upb_alloc *a) {
lookupkey_t key;
upb_tabkey tabkey;
uint32_t hash;
+ upb_check_alloc(&t->t, a);
+
if (isfull(&t->t)) {
/* Need to resize. New table of double the size, add old elements to it. */
- if (!upb_strtable_resize(t, t->t.size_lg2 + 1)) {
+ if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) {
return false;
}
}
key = strkey2(k, len);
- tabkey = strcopy(key);
+ tabkey = strcopy(key, a);
if (tabkey == 0) return false;
hash = MurmurHash2(key.str.str, key.str.len, 0);
@@ -4347,12 +4630,12 @@ bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
return lookup(&t->t, strkey2(key, len), v, hash, &streql);
}
-bool upb_strtable_remove2(upb_strtable *t, const char *key, size_t len,
- upb_value *val) {
- uint32_t hash = MurmurHash2(key, strlen(key), 0);
+bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
+ upb_value *val, upb_alloc *alloc) {
+ uint32_t hash = MurmurHash2(key, len, 0);
upb_tabkey tabkey;
if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) {
- free((void*)tabkey);
+ upb_free(alloc, (void*)tabkey);
return true;
} else {
return false;
@@ -4379,20 +4662,20 @@ bool upb_strtable_done(const upb_strtable_iter *i) {
upb_tabent_isempty(str_tabent(i));
}
-const char *upb_strtable_iter_key(upb_strtable_iter *i) {
- assert(!upb_strtable_done(i));
+const char *upb_strtable_iter_key(const upb_strtable_iter *i) {
+ UPB_ASSERT(!upb_strtable_done(i));
return upb_tabstr(str_tabent(i)->key, NULL);
}
-size_t upb_strtable_iter_keylength(upb_strtable_iter *i) {
+size_t upb_strtable_iter_keylength(const upb_strtable_iter *i) {
uint32_t len;
- assert(!upb_strtable_done(i));
+ UPB_ASSERT(!upb_strtable_done(i));
upb_tabstr(str_tabent(i)->key, &len);
return len;
}
upb_value upb_strtable_iter_value(const upb_strtable_iter *i) {
- assert(!upb_strtable_done(i));
+ UPB_ASSERT(!upb_strtable_done(i));
return _upb_value_val(str_tabent(i)->val.val, i->t->t.ctype);
}
@@ -4451,26 +4734,26 @@ static void check(upb_inttable *t) {
upb_inttable_iter i;
upb_inttable_begin(&i, t);
for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) {
- assert(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL));
+ UPB_ASSERT(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL));
}
- assert(count == upb_inttable_count(t));
+ UPB_ASSERT(count == upb_inttable_count(t));
}
#endif
}
bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype,
- size_t asize, int hsize_lg2) {
+ size_t asize, int hsize_lg2, upb_alloc *a) {
size_t array_bytes;
- if (!init(&t->t, ctype, hsize_lg2)) return false;
+ if (!init(&t->t, ctype, hsize_lg2, a)) return false;
/* Always make the array part at least 1 long, so that we know key 0
* won't be in the hash part, which simplifies things. */
t->array_size = UPB_MAX(1, asize);
t->array_count = 0;
array_bytes = t->array_size * sizeof(upb_value);
- t->array = malloc(array_bytes);
+ t->array = upb_malloc(a, array_bytes);
if (!t->array) {
- uninit(&t->t);
+ uninit(&t->t, a);
return false;
}
memset(mutable_array(t), 0xff, array_bytes);
@@ -4478,25 +4761,25 @@ bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype,
return true;
}
-bool upb_inttable_init(upb_inttable *t, upb_ctype_t ctype) {
- return upb_inttable_sizedinit(t, ctype, 0, 4);
+bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) {
+ return upb_inttable_sizedinit(t, ctype, 0, 4, a);
}
-void upb_inttable_uninit(upb_inttable *t) {
- uninit(&t->t);
- free(mutable_array(t));
+void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) {
+ uninit(&t->t, a);
+ upb_free(a, mutable_array(t));
}
-bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val) {
- /* XXX: Table can't store value (uint64_t)-1. Need to somehow statically
- * guarantee that this is not necessary, or fix the limitation. */
+bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
+ upb_alloc *a) {
upb_tabval tabval;
tabval.val = val.val;
- UPB_UNUSED(tabval);
- assert(upb_arrhas(tabval));
+ UPB_ASSERT(upb_arrhas(tabval)); /* This will reject (uint64_t)-1. Fix this. */
+
+ upb_check_alloc(&t->t, a);
if (key < t->array_size) {
- assert(!upb_arrhas(t->array[key]));
+ UPB_ASSERT(!upb_arrhas(t->array[key]));
t->array_count++;
mutable_array(t)[key].val = val.val;
} else {
@@ -4504,8 +4787,11 @@ bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val) {
/* Need to resize the hash part, but we re-use the array part. */
size_t i;
upb_table new_table;
- if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1))
+
+ if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1, a)) {
return false;
+ }
+
for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
const upb_tabent *e = &t->t.entries[i];
uint32_t hash;
@@ -4516,9 +4802,9 @@ bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val) {
insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql);
}
- assert(t->t.count == new_table.count);
+ UPB_ASSERT(t->t.count == new_table.count);
- uninit(&t->t);
+ uninit(&t->t, a);
t->t = new_table;
}
insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql);
@@ -4556,27 +4842,28 @@ bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
success = false;
}
} else {
- upb_tabkey removed;
- uint32_t hash = upb_inthash(key);
- success = rm(&t->t, intkey(key), val, &removed, hash, &inteql);
+ success = rm(&t->t, intkey(key), val, NULL, upb_inthash(key), &inteql);
}
check(t);
return success;
}
-bool upb_inttable_push(upb_inttable *t, upb_value val) {
- return upb_inttable_insert(t, upb_inttable_count(t), val);
+bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a) {
+ upb_check_alloc(&t->t, a);
+ return upb_inttable_insert2(t, upb_inttable_count(t), val, a);
}
upb_value upb_inttable_pop(upb_inttable *t) {
upb_value val;
bool ok = upb_inttable_remove(t, upb_inttable_count(t) - 1, &val);
- UPB_ASSERT_VAR(ok, ok);
+ UPB_ASSERT(ok);
return val;
}
-bool upb_inttable_insertptr(upb_inttable *t, const void *key, upb_value val) {
- return upb_inttable_insert(t, (uintptr_t)key, val);
+bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
+ upb_alloc *a) {
+ upb_check_alloc(&t->t, a);
+ return upb_inttable_insert2(t, (uintptr_t)key, val, a);
}
bool upb_inttable_lookupptr(const upb_inttable *t, const void *key,
@@ -4588,77 +4875,74 @@ bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) {
return upb_inttable_remove(t, (uintptr_t)key, val);
}
-void upb_inttable_compact(upb_inttable *t) {
- /* Create a power-of-two histogram of the table keys. */
- int counts[UPB_MAXARRSIZE + 1] = {0};
- uintptr_t max_key = 0;
+void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) {
+ /* A power-of-two histogram of the table keys. */
+ size_t counts[UPB_MAXARRSIZE + 1] = {0};
+
+ /* The max key in each bucket. */
+ uintptr_t max[UPB_MAXARRSIZE + 1] = {0};
+
upb_inttable_iter i;
- size_t arr_size;
- int arr_count;
+ size_t arr_count;
+ int size_lg2;
upb_inttable new_t;
+ upb_check_alloc(&t->t, a);
+
upb_inttable_begin(&i, t);
for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
uintptr_t key = upb_inttable_iter_key(&i);
- if (key > max_key) {
- max_key = key;
- }
- counts[log2ceil(key)]++;
+ int bucket = log2ceil(key);
+ max[bucket] = UPB_MAX(max[bucket], key);
+ counts[bucket]++;
}
- arr_size = 1;
+ /* Find the largest power of two that satisfies the MIN_DENSITY
+ * definition (while actually having some keys). */
arr_count = upb_inttable_count(t);
- if (upb_inttable_count(t) >= max_key * MIN_DENSITY) {
- /* We can put 100% of the entries in the array part. */
- arr_size = max_key + 1;
- } else {
- /* Find the largest power of two that satisfies the MIN_DENSITY
- * definition. */
- int size_lg2;
- for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 1; size_lg2--) {
- arr_size = 1 << size_lg2;
- arr_count -= counts[size_lg2];
- if (arr_count >= arr_size * MIN_DENSITY) {
- break;
- }
+ for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) {
+ if (counts[size_lg2] == 0) {
+ /* We can halve again without losing any entries. */
+ continue;
+ } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) {
+ break;
}
+
+ arr_count -= counts[size_lg2];
}
- /* Array part must always be at least 1 entry large to catch lookups of key
- * 0. Key 0 must always be in the array part because "0" in the hash part
- * denotes an empty entry. */
- arr_size = UPB_MAX(arr_size, 1);
+ UPB_ASSERT(arr_count <= upb_inttable_count(t));
{
/* Insert all elements into new, perfectly-sized table. */
- int hash_count = upb_inttable_count(t) - arr_count;
- int hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
- int hashsize_lg2 = log2ceil(hash_size);
+ size_t arr_size = max[size_lg2] + 1; /* +1 so arr[max] will fit. */
+ size_t hash_count = upb_inttable_count(t) - arr_count;
+ size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
+ size_t hashsize_lg2 = log2ceil(hash_size);
- assert(hash_count >= 0);
- upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2);
+ upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2, a);
upb_inttable_begin(&i, t);
for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
uintptr_t k = upb_inttable_iter_key(&i);
- upb_inttable_insert(&new_t, k, upb_inttable_iter_value(&i));
+ upb_inttable_insert2(&new_t, k, upb_inttable_iter_value(&i), a);
}
- assert(new_t.array_size == arr_size);
- assert(new_t.t.size_lg2 == hashsize_lg2);
+ UPB_ASSERT(new_t.array_size == arr_size);
+ UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2);
}
- upb_inttable_uninit(t);
+ upb_inttable_uninit2(t, a);
*t = new_t;
}
/* Iteration. */
static const upb_tabent *int_tabent(const upb_inttable_iter *i) {
- assert(!i->array_part);
+ UPB_ASSERT(!i->array_part);
return &i->t->t.entries[i->index];
}
static upb_tabval int_arrent(const upb_inttable_iter *i) {
- assert(i->array_part);
+ UPB_ASSERT(i->array_part);
return i->t->array[i->index];
}
@@ -4695,12 +4979,12 @@ bool upb_inttable_done(const upb_inttable_iter *i) {
}
uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) {
- assert(!upb_inttable_done(i));
+ UPB_ASSERT(!upb_inttable_done(i));
return i->array_part ? i->index : int_tabent(i)->key;
}
upb_value upb_inttable_iter_value(const upb_inttable_iter *i) {
- assert(!upb_inttable_done(i));
+ UPB_ASSERT(!upb_inttable_done(i));
return _upb_value_val(
i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val,
i->t->t.ctype);
@@ -4918,10 +5202,23 @@ bool upb_dumptostderr(void *closure, const upb_status* status) {
static void nullz(upb_status *status) {
const char *ellipsis = "...";
size_t len = strlen(ellipsis);
- assert(sizeof(status->msg) > len);
+ UPB_ASSERT(sizeof(status->msg) > len);
memcpy(status->msg + sizeof(status->msg) - len, ellipsis, len);
}
+
+/* upb_upberr *****************************************************************/
+
+upb_errorspace upb_upberr = {"upb error"};
+
+void upb_upberr_setoom(upb_status *status) {
+ status->error_space_ = &upb_upberr;
+ upb_status_seterrmsg(status, "Out of memory");
+}
+
+
+/* upb_status *****************************************************************/
+
void upb_status_clear(upb_status *status) {
if (!status) return;
status->ok_ = true;
@@ -4960,311 +5257,604 @@ void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) {
nullz(status);
}
-void upb_status_seterrcode(upb_status *status, upb_errorspace *space,
- int code) {
- if (!status) return;
- status->ok_ = false;
- status->error_space_ = space;
- status->code_ = code;
- space->set_message(status, code);
-}
-
void upb_status_copy(upb_status *to, const upb_status *from) {
if (!to) return;
*to = *from;
}
-/* This file was generated by upbc (the upb compiler).
+
+
+/* upb_alloc ******************************************************************/
+
+static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize,
+ size_t size) {
+ UPB_UNUSED(alloc);
+ UPB_UNUSED(oldsize);
+ if (size == 0) {
+ free(ptr);
+ return NULL;
+ } else {
+ return realloc(ptr, size);
+ }
+}
+
+upb_alloc upb_alloc_global = {&upb_global_allocfunc};
+
+
+/* upb_arena ******************************************************************/
+
+/* Be conservative and choose 16 in case anyone is using SSE. */
+static const size_t maxalign = 16;
+
+static size_t align_up(size_t size) {
+ return ((size + maxalign - 1) / maxalign) * maxalign;
+}
+
+typedef struct mem_block {
+ struct mem_block *next;
+ size_t size;
+ size_t used;
+ bool owned;
+ /* Data follows. */
+} mem_block;
+
+typedef struct cleanup_ent {
+ struct cleanup_ent *next;
+ upb_cleanup_func *cleanup;
+ void *ud;
+} cleanup_ent;
+
+static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size,
+ bool owned) {
+ mem_block *block = ptr;
+
+ block->next = a->block_head;
+ block->size = size;
+ block->used = align_up(sizeof(mem_block));
+ block->owned = owned;
+
+ a->block_head = block;
+
+ /* TODO(haberman): ASAN poison. */
+}
+
+
+static mem_block *upb_arena_allocblock(upb_arena *a, size_t size) {
+ size_t block_size = UPB_MAX(size, a->next_block_size) + sizeof(mem_block);
+ mem_block *block = upb_malloc(a->block_alloc, block_size);
+
+ if (!block) {
+ return NULL;
+ }
+
+ upb_arena_addblock(a, block, block_size, true);
+ a->next_block_size = UPB_MIN(block_size * 2, a->max_block_size);
+
+ return block;
+}
+
+static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize,
+ size_t size) {
+ upb_arena *a = (upb_arena*)alloc; /* upb_alloc is initial member. */
+ mem_block *block = a->block_head;
+ void *ret;
+
+ if (size == 0) {
+ return NULL; /* We are an arena, don't need individual frees. */
+ }
+
+ size = align_up(size);
+
+ /* TODO(haberman): special-case if this is a realloc of the last alloc? */
+
+ if (!block || block->size - block->used < size) {
+ /* Slow path: have to allocate a new block. */
+ block = upb_arena_allocblock(a, size);
+
+ if (!block) {
+ return NULL; /* Out of memory. */
+ }
+ }
+
+ ret = (char*)block + block->used;
+ block->used += size;
+
+ if (oldsize > 0) {
+ memcpy(ret, ptr, oldsize); /* Preserve existing data. */
+ }
+
+ /* TODO(haberman): ASAN unpoison. */
+
+ a->bytes_allocated += size;
+ return ret;
+}
+
+/* Public Arena API ***********************************************************/
+
+void upb_arena_init(upb_arena *a) {
+ a->alloc.func = &upb_arena_doalloc;
+ a->block_alloc = &upb_alloc_global;
+ a->bytes_allocated = 0;
+ a->next_block_size = 256;
+ a->max_block_size = 16384;
+ a->cleanup_head = NULL;
+ a->block_head = NULL;
+}
+
+void upb_arena_init2(upb_arena *a, void *mem, size_t size, upb_alloc *alloc) {
+ upb_arena_init(a);
+
+ if (size > sizeof(mem_block)) {
+ upb_arena_addblock(a, mem, size, false);
+ }
+
+ if (alloc) {
+ a->block_alloc = alloc;
+ }
+}
+
+void upb_arena_uninit(upb_arena *a) {
+ cleanup_ent *ent = a->cleanup_head;
+ mem_block *block = a->block_head;
+
+ while (ent) {
+ ent->cleanup(ent->ud);
+ ent = ent->next;
+ }
+
+ /* Must do this after running cleanup functions, because this will delete
+ * the memory we store our cleanup entries in! */
+ while (block) {
+ mem_block *next = block->next;
+
+ if (block->owned) {
+ upb_free(a->block_alloc, block);
+ }
+
+ block = next;
+ }
+}
+
+bool upb_arena_addcleanup(upb_arena *a, upb_cleanup_func *func, void *ud) {
+ cleanup_ent *ent = upb_malloc(&a->alloc, sizeof(cleanup_ent));
+ if (!ent) {
+ return false; /* Out of memory. */
+ }
+
+ ent->cleanup = func;
+ ent->ud = ud;
+ ent->next = a->cleanup_head;
+ a->cleanup_head = ent;
+
+ return true;
+}
+
+size_t upb_arena_bytesallocated(const upb_arena *a) {
+ return a->bytes_allocated;
+}
+
+
+/* Standard error functions ***************************************************/
+
+static bool default_err(void *ud, const upb_status *status) {
+ UPB_UNUSED(ud);
+ UPB_UNUSED(status);
+ return false;
+}
+
+static bool write_err_to(void *ud, const upb_status *status) {
+ upb_status *copy_to = ud;
+ upb_status_copy(copy_to, status);
+ return false;
+}
+
+
+/* upb_env ********************************************************************/
+
+void upb_env_initonly(upb_env *e) {
+ e->ok_ = true;
+ e->error_func_ = &default_err;
+ e->error_ud_ = NULL;
+}
+
+void upb_env_init(upb_env *e) {
+ upb_arena_init(&e->arena_);
+ upb_env_initonly(e);
+}
+
+void upb_env_init2(upb_env *e, void *mem, size_t n, upb_alloc *alloc) {
+ upb_arena_init2(&e->arena_, mem, n, alloc);
+ upb_env_initonly(e);
+}
+
+void upb_env_uninit(upb_env *e) {
+ upb_arena_uninit(&e->arena_);
+}
+
+void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud) {
+ e->error_func_ = func;
+ e->error_ud_ = ud;
+}
+
+void upb_env_reporterrorsto(upb_env *e, upb_status *s) {
+ e->error_func_ = &write_err_to;
+ e->error_ud_ = s;
+}
+
+bool upb_env_reporterror(upb_env *e, const upb_status *status) {
+ e->ok_ = false;
+ return e->error_func_(e->error_ud_, status);
+}
+
+void *upb_env_malloc(upb_env *e, size_t size) {
+ return upb_malloc(&e->arena_.alloc, size);
+}
+
+void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size) {
+ return upb_realloc(&e->arena_.alloc, ptr, oldsize, size);
+}
+
+void upb_env_free(upb_env *e, void *ptr) {
+ upb_free(&e->arena_.alloc, ptr);
+}
+
+bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud) {
+ return upb_arena_addcleanup(&e->arena_, func, ud);
+}
+
+size_t upb_env_bytesallocated(const upb_env *e) {
+ return upb_arena_bytesallocated(&e->arena_);
+}
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ * upb/descriptor/descriptor.proto
+ *
* Do not edit -- your changes will be discarded when the file is
* regenerated. */
-static const upb_msgdef msgs[20];
-static const upb_fielddef fields[81];
-static const upb_enumdef enums[4];
+static const upb_msgdef msgs[22];
+static const upb_fielddef fields[105];
+static const upb_enumdef enums[5];
static const upb_tabent strentries[236];
-static const upb_tabent intentries[14];
-static const upb_tabval arrays[232];
+static const upb_tabent intentries[18];
+static const upb_tabval arrays[184];
#ifdef UPB_DEBUG_REFS
-static upb_inttable reftables[212];
+static upb_inttable reftables[264];
#endif
-static const upb_msgdef msgs[20] = {
- UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", 27, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[0], 8, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[0]),&reftables[0], &reftables[1]),
- UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", 4, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[8], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[16]),&reftables[2], &reftables[3]),
- UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[11], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[20]),&reftables[4], &reftables[5]),
- UPB_MSGDEF_INIT("google.protobuf.EnumOptions", 7, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[0], &arrays[15], 8, 1), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[24]),&reftables[6], &reftables[7]),
- UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", 8, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[23], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[28]),&reftables[8], &reftables[9]),
- UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", 6, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[2], &arrays[27], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[32]),&reftables[10], &reftables[11]),
- UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", 19, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[31], 9, 8), UPB_STRTABLE_INIT(8, 15, UPB_CTYPE_PTR, 4, &strentries[36]),&reftables[12], &reftables[13]),
- UPB_MSGDEF_INIT("google.protobuf.FieldOptions", 14, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[4], &arrays[40], 32, 6), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[52]),&reftables[14], &reftables[15]),
- UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", 39, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[72], 12, 11), UPB_STRTABLE_INIT(11, 15, UPB_CTYPE_PTR, 4, &strentries[68]),&reftables[16], &reftables[17]),
- UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[84], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[84]),&reftables[18], &reftables[19]),
- UPB_MSGDEF_INIT("google.protobuf.FileOptions", 21, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[86], 64, 9), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[88]),&reftables[20], &reftables[21]),
- UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 8, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[150], 16, 2), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[104]),&reftables[22], &reftables[23]),
- UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 13, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[166], 5, 4), UPB_STRTABLE_INIT(4, 7, UPB_CTYPE_PTR, 3, &strentries[108]),&reftables[24], &reftables[25]),
- UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 6, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[10], &arrays[171], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[116]),&reftables[26], &reftables[27]),
- UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[175], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[120]),&reftables[28], &reftables[29]),
- UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 6, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[12], &arrays[179], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[124]),&reftables[30], &reftables[31]),
- UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[183], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[128]),&reftables[32], &reftables[33]),
- UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 14, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[185], 5, 4), UPB_STRTABLE_INIT(4, 7, UPB_CTYPE_PTR, 3, &strentries[132]),&reftables[34], &reftables[35]),
- UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 18, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[190], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[140]),&reftables[36], &reftables[37]),
- UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[199], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[156]),&reftables[38], &reftables[39]),
+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", 31, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 39, 15), UPB_STRTABLE_INIT(16, 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[107], 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[115], 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[122], 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[123], 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[125], 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[129], 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[130], 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[132], 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[139], 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[148], 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[81] = {
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "aggregate_value", 8, &msgs[18], NULL, 15, 6, {0},&reftables[40], &reftables[41]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "allow_alias", 2, &msgs[3], NULL, 6, 1, {0},&reftables[42], &reftables[43]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_generic_services", 16, &msgs[10], NULL, 17, 6, {0},&reftables[44], &reftables[45]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "ctype", 1, &msgs[7], (const upb_def*)(&enums[2]), 6, 1, {0},&reftables[46], &reftables[47]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "default_value", 7, &msgs[6], NULL, 16, 7, {0},&reftables[48], &reftables[49]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "dependency", 3, &msgs[8], NULL, 30, 8, {0},&reftables[50], &reftables[51]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[7], NULL, 8, 3, {0},&reftables[52], &reftables[53]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, false, false, false, "double_value", 6, &msgs[18], NULL, 11, 4, {0},&reftables[54], &reftables[55]),
- 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[56], &reftables[57]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 4, &msgs[0], (const upb_def*)(&msgs[2]), 16, 2, {0},&reftables[58], &reftables[59]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 5, &msgs[8], (const upb_def*)(&msgs[2]), 13, 1, {0},&reftables[60], &reftables[61]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "experimental_map_key", 9, &msgs[7], NULL, 10, 5, {0},&reftables[62], &reftables[63]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "extendee", 2, &msgs[6], NULL, 7, 2, {0},&reftables[64], &reftables[65]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 7, &msgs[8], (const upb_def*)(&msgs[6]), 19, 3, {0},&reftables[66], &reftables[67]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 6, &msgs[0], (const upb_def*)(&msgs[6]), 22, 4, {0},&reftables[68], &reftables[69]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension_range", 5, &msgs[0], (const upb_def*)(&msgs[1]), 19, 3, {0},&reftables[70], &reftables[71]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "field", 2, &msgs[0], (const upb_def*)(&msgs[6]), 10, 0, {0},&reftables[72], &reftables[73]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "file", 1, &msgs[9], (const upb_def*)(&msgs[8]), 5, 0, {0},&reftables[74], &reftables[75]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "go_package", 11, &msgs[10], NULL, 14, 5, {0},&reftables[76], &reftables[77]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "identifier_value", 3, &msgs[18], NULL, 6, 1, {0},&reftables[78], &reftables[79]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "input_type", 2, &msgs[12], NULL, 7, 2, {0},&reftables[80], &reftables[81]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, false, false, false, "is_extension", 2, &msgs[19], NULL, 5, 1, {0},&reftables[82], &reftables[83]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generate_equals_and_hash", 20, &msgs[10], NULL, 20, 9, {0},&reftables[84], &reftables[85]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generic_services", 17, &msgs[10], NULL, 18, 7, {0},&reftables[86], &reftables[87]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_multiple_files", 10, &msgs[10], NULL, 13, 4, {0},&reftables[88], &reftables[89]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_outer_classname", 8, &msgs[10], NULL, 9, 2, {0},&reftables[90], &reftables[91]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_package", 1, &msgs[10], NULL, 6, 1, {0},&reftables[92], &reftables[93]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "label", 4, &msgs[6], (const upb_def*)(&enums[0]), 11, 4, {0},&reftables[94], &reftables[95]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "lazy", 5, &msgs[7], NULL, 9, 4, {0},&reftables[96], &reftables[97]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "leading_comments", 3, &msgs[17], NULL, 8, 2, {0},&reftables[98], &reftables[99]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "location", 1, &msgs[16], (const upb_def*)(&msgs[17]), 5, 0, {0},&reftables[100], &reftables[101]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "message_set_wire_format", 1, &msgs[11], NULL, 6, 1, {0},&reftables[102], &reftables[103]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "message_type", 4, &msgs[8], (const upb_def*)(&msgs[0]), 10, 0, {0},&reftables[104], &reftables[105]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "method", 2, &msgs[14], (const upb_def*)(&msgs[12]), 6, 0, {0},&reftables[106], &reftables[107]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[8], NULL, 22, 6, {0},&reftables[108], &reftables[109]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[14], NULL, 8, 2, {0},&reftables[110], &reftables[111]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "name", 2, &msgs[18], (const upb_def*)(&msgs[19]), 5, 0, {0},&reftables[112], &reftables[113]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[4], NULL, 4, 1, {0},&reftables[114], &reftables[115]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 24, 6, {0},&reftables[116], &reftables[117]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[12], NULL, 4, 1, {0},&reftables[118], &reftables[119]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[2], NULL, 8, 2, {0},&reftables[120], &reftables[121]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[6], NULL, 4, 1, {0},&reftables[122], &reftables[123]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, false, false, false, "name_part", 1, &msgs[19], NULL, 2, 0, {0},&reftables[124], &reftables[125]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, false, false, false, "negative_int_value", 5, &msgs[18], NULL, 10, 3, {0},&reftables[126], &reftables[127]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "nested_type", 3, &msgs[0], (const upb_def*)(&msgs[0]), 13, 1, {0},&reftables[128], &reftables[129]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "no_standard_descriptor_accessor", 2, &msgs[11], NULL, 7, 2, {0},&reftables[130], &reftables[131]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 3, &msgs[6], NULL, 10, 3, {0},&reftables[132], &reftables[133]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 2, &msgs[4], NULL, 7, 2, {0},&reftables[134], &reftables[135]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "optimize_for", 9, &msgs[10], (const upb_def*)(&enums[3]), 12, 3, {0},&reftables[136], &reftables[137]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 7, &msgs[0], (const upb_def*)(&msgs[11]), 23, 5, {0},&reftables[138], &reftables[139]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[2], (const upb_def*)(&msgs[3]), 7, 1, {0},&reftables[140], &reftables[141]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[6], (const upb_def*)(&msgs[7]), 3, 0, {0},&reftables[142], &reftables[143]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[4], (const upb_def*)(&msgs[5]), 3, 0, {0},&reftables[144], &reftables[145]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[8], (const upb_def*)(&msgs[10]), 20, 4, {0},&reftables[146], &reftables[147]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[14], (const upb_def*)(&msgs[15]), 7, 1, {0},&reftables[148], &reftables[149]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 4, &msgs[12], (const upb_def*)(&msgs[13]), 3, 0, {0},&reftables[150], &reftables[151]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "output_type", 3, &msgs[12], NULL, 10, 3, {0},&reftables[152], &reftables[153]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "package", 2, &msgs[8], NULL, 25, 7, {0},&reftables[154], &reftables[155]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "packed", 2, &msgs[7], NULL, 7, 2, {0},&reftables[156], &reftables[157]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "path", 1, &msgs[17], NULL, 4, 0, {0},&reftables[158], &reftables[159]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, false, "positive_int_value", 4, &msgs[18], NULL, 9, 2, {0},&reftables[160], &reftables[161]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "public_dependency", 10, &msgs[8], NULL, 35, 9, {0},&reftables[162], &reftables[163]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "py_generic_services", 18, &msgs[10], NULL, 19, 8, {0},&reftables[164], &reftables[165]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "service", 6, &msgs[8], (const upb_def*)(&msgs[14]), 16, 2, {0},&reftables[166], &reftables[167]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "source_code_info", 9, &msgs[8], (const upb_def*)(&msgs[16]), 21, 5, {0},&reftables[168], &reftables[169]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "span", 2, &msgs[17], NULL, 7, 1, {0},&reftables[170], &reftables[171]),
- 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[172], &reftables[173]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[18], NULL, 12, 5, {0},&reftables[174], &reftables[175]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[17], NULL, 11, 3, {0},&reftables[176], &reftables[177]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "type", 5, &msgs[6], (const upb_def*)(&enums[1]), 12, 5, {0},&reftables[178], &reftables[179]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[6], NULL, 13, 6, {0},&reftables[180], &reftables[181]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[5], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[182], &reftables[183]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[15], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[184], &reftables[185]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[3], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[186], &reftables[187]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[13], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[188], &reftables[189]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[10], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[190], &reftables[191]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[11], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[192], &reftables[193]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[7], (const upb_def*)(&msgs[18]), 5, 0, {0},&reftables[194], &reftables[195]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "value", 2, &msgs[2], (const upb_def*)(&msgs[4]), 6, 0, {0},&reftables[196], &reftables[197]),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[7], NULL, 13, 6, {0},&reftables[198], &reftables[199]),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "weak_dependency", 11, &msgs[8], NULL, 38, 10, {0},&reftables[200], &reftables[201]),
+static const upb_fielddef fields[105] = {
+ 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[12], NULL, 8, 3, {0},&reftables[62], &reftables[63]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[8], NULL, 8, 3, {0},&reftables[64], &reftables[65]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[14], NULL, 6, 1, {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", 3, &msgs[4], NULL, 7, 2, {0},&reftables[70], &reftables[71]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[17], NULL, 6, 1, {0},&reftables[72], &reftables[73]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 1, &msgs[6], 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", 4, &msgs[0], (const upb_def*)(&msgs[3]), 18, 2, {0},&reftables[82], &reftables[83]),
+ 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[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_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[3], NULL, 8, 2, {0},&reftables[142], &reftables[143]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[15], NULL, 2, 0, {0},&reftables[144], &reftables[145]),
+ 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[146], &reftables[147]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 32, 8, {0},&reftables[148], &reftables[149]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[5], NULL, 4, 1, {0},&reftables[150], &reftables[151]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[9], NULL, 22, 6, {0},&reftables[152], &reftables[153]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[7], 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[13], 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[16], NULL, 8, 2, {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", 2, &msgs[5], NULL, 7, 2, {0},&reftables[168], &reftables[169]),
+ 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[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", 4, &msgs[13], (const upb_def*)(&msgs[14]), 3, 0, {0},&reftables[184], &reftables[185]),
+ 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[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[5], (const upb_def*)(&msgs[6]), 3, 0, {0},&reftables[190], &reftables[191]),
+ 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[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_UINT64, UPB_INTFMT_VARIABLE, false, false, false, false, "positive_int_value", 4, &msgs[20], NULL, 9, 2, {0},&reftables[202], &reftables[203]),
+ 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[204], &reftables[205]),
+ 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[206], &reftables[207]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "reserved_name", 10, &msgs[0], NULL, 37, 9, {0},&reftables[208], &reftables[209]),
+ 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[210], &reftables[211]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "server_streaming", 6, &msgs[13], NULL, 14, 5, {0},&reftables[212], &reftables[213]),
+ 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[214], &reftables[215]),
+ 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[216], &reftables[217]),
+ 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[218], &reftables[219]),
+ 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[220], &reftables[221]),
+ 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[222], &reftables[223]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[20], NULL, 12, 5, {0},&reftables[224], &reftables[225]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "syntax", 12, &msgs[9], NULL, 39, 11, {0},&reftables[226], &reftables[227]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[19], NULL, 11, 3, {0},&reftables[228], &reftables[229]),
+ 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[230], &reftables[231]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[7], NULL, 13, 6, {0},&reftables[232], &reftables[233]),
+ 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[234], &reftables[235]),
+ 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[236], &reftables[237]),
+ 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[238], &reftables[239]),
+ 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[240], &reftables[241]),
+ 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[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[17], (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, "value", 2, &msgs[3], (const upb_def*)(&msgs[5]), 6, 0, {0},&reftables[248], &reftables[249]),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[8], NULL, 11, 6, {0},&reftables[250], &reftables[251]),
+ 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[252], &reftables[253]),
};
-static const upb_enumdef enums[4] = {
- UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[160]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[202], 4, 3), 0, &reftables[202], &reftables[203]),
- UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_INT32, 5, &strentries[164]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[206], 19, 18), 0, &reftables[204], &reftables[205]),
- UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[196]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[225], 3, 3), 0, &reftables[206], &reftables[207]),
- UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[200]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[228], 4, 3), 0, &reftables[208], &reftables[209]),
+static const upb_enumdef enums[5] = {
+ UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[188]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[151], 4, 3), 0, &reftables[254], &reftables[255]),
+ UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_INT32, 5, &strentries[192]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[155], 19, 18), 0, &reftables[256], &reftables[257]),
+ UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[224]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[174], 3, 3), 0, &reftables[258], &reftables[259]),
+ UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.JSType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[228]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[177], 3, 3), 0, &reftables[260], &reftables[261]),
+ UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[232]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[180], 4, 3), 0, &reftables[262], &reftables[263]),
};
static const upb_tabent strentries[236] = {
- {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL},
+ {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[22]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "reserved_name"), UPB_TABVALUE_PTR_INIT(&fields[82]), NULL},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[52]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[38]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "field"), UPB_TABVALUE_PTR_INIT(&fields[25]), &strentries[12]},
+ {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "extension_range"), UPB_TABVALUE_PTR_INIT(&fields[24]), &strentries[14]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "field"), UPB_TABVALUE_PTR_INIT(&fields[16]), NULL},
- {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "extension_range"), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL},
+ {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "nested_type"), UPB_TABVALUE_PTR_INIT(&fields[60]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "nested_type"), UPB_TABVALUE_PTR_INIT(&fields[44]), NULL},
+ {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "reserved_range"), UPB_TABVALUE_PTR_INIT(&fields[83]), NULL},
+ {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[68]), NULL},
+ {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "oneof_decl"), UPB_TABVALUE_PTR_INIT(&fields[65]), NULL},
+ {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[19]), &strentries[13]},
+ {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[89]), NULL},
+ {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[18]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[88]), NULL},
+ {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[17]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[49]), NULL},
- {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[9]), &strentries[14]},
- {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[66]), NULL},
- {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[8]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "value"), UPB_TABVALUE_PTR_INIT(&fields[102]), NULL},
+ {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[49]), &strentries[26]},
+ {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL},
+ {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[13]), NULL},
+ {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "allow_alias"), UPB_TABVALUE_PTR_INIT(&fields[1]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "value"), UPB_TABVALUE_PTR_INIT(&fields[78]), NULL},
- {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[50]), NULL},
- {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[40]), &strentries[22]},
- {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL},
+ {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[62]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "allow_alias"), UPB_TABVALUE_PTR_INIT(&fields[1]), NULL},
+ {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[53]), &strentries[34]},
+ {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL},
+ {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL},
+ {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "oneof_index"), UPB_TABVALUE_PTR_INIT(&fields[66]), NULL},
+ {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "label"), UPB_TABVALUE_PTR_INIT(&fields[40]), NULL},
+ {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[55]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[47]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[52]), NULL},
- {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[37]), &strentries[30]},
- {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[63]), &strentries[53]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "extendee"), UPB_TABVALUE_PTR_INIT(&fields[21]), NULL},
+ {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "type_name"), UPB_TABVALUE_PTR_INIT(&fields[94]), NULL},
+ {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "json_name"), UPB_TABVALUE_PTR_INIT(&fields[38]), NULL},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "type"), UPB_TABVALUE_PTR_INIT(&fields[93]), &strentries[50]},
+ {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "default_value"), UPB_TABVALUE_PTR_INIT(&fields[7]), NULL},
+ {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL},
+ {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "label"), UPB_TABVALUE_PTR_INIT(&fields[27]), NULL},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "weak"), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[41]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "packed"), UPB_TABVALUE_PTR_INIT(&fields[77]), NULL},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "lazy"), UPB_TABVALUE_PTR_INIT(&fields[41]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[46]), &strentries[49]},
+ {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "ctype"), UPB_TABVALUE_PTR_INIT(&fields[6]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "jstype"), UPB_TABVALUE_PTR_INIT(&fields[39]), NULL},
+ {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "type_name"), UPB_TABVALUE_PTR_INIT(&fields[70]), NULL},
- {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "extendee"), UPB_TABVALUE_PTR_INIT(&fields[12]), NULL},
- {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "type"), UPB_TABVALUE_PTR_INIT(&fields[69]), &strentries[48]},
- {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "default_value"), UPB_TABVALUE_PTR_INIT(&fields[4]), NULL},
- {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[51]), NULL},
- {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "experimental_map_key"), UPB_TABVALUE_PTR_INIT(&fields[11]), &strentries[67]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "weak"), UPB_TABVALUE_PTR_INIT(&fields[79]), NULL},
+ {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[23]), NULL},
+ {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "weak_dependency"), UPB_TABVALUE_PTR_INIT(&fields[104]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[54]), NULL},
+ {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "service"), UPB_TABVALUE_PTR_INIT(&fields[85]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "source_code_info"), UPB_TABVALUE_PTR_INIT(&fields[86]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "packed"), UPB_TABVALUE_PTR_INIT(&fields[58]), NULL},
- {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "lazy"), UPB_TABVALUE_PTR_INIT(&fields[28]), NULL},
+ {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "syntax"), UPB_TABVALUE_PTR_INIT(&fields[91]), NULL},
+ {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "dependency"), UPB_TABVALUE_PTR_INIT(&fields[8]), NULL},
+ {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "message_type"), UPB_TABVALUE_PTR_INIT(&fields[47]), NULL},
+ {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "package"), UPB_TABVALUE_PTR_INIT(&fields[76]), NULL},
+ {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[69]), &strentries[86]},
+ {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[20]), NULL},
+ {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "public_dependency"), UPB_TABVALUE_PTR_INIT(&fields[80]), &strentries[85]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "ctype"), UPB_TABVALUE_PTR_INIT(&fields[3]), NULL},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "file"), UPB_TABVALUE_PTR_INIT(&fields[26]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[6]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[77]), NULL},
- {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[13]), NULL},
- {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "weak_dependency"), UPB_TABVALUE_PTR_INIT(&fields[80]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[34]), NULL},
- {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "service"), UPB_TABVALUE_PTR_INIT(&fields[63]), NULL},
+ {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "cc_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[3]), NULL},
+ {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "csharp_namespace"), UPB_TABVALUE_PTR_INIT(&fields[5]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "source_code_info"), UPB_TABVALUE_PTR_INIT(&fields[64]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "dependency"), UPB_TABVALUE_PTR_INIT(&fields[5]), NULL},
- {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "message_type"), UPB_TABVALUE_PTR_INIT(&fields[32]), NULL},
- {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "package"), UPB_TABVALUE_PTR_INIT(&fields[57]), NULL},
- {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[53]), &strentries[82]},
- {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL},
- {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "public_dependency"), UPB_TABVALUE_PTR_INIT(&fields[61]), &strentries[81]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "file"), UPB_TABVALUE_PTR_INIT(&fields[17]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[75]), NULL},
+ {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "go_package"), UPB_TABVALUE_PTR_INIT(&fields[27]), NULL},
+ {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "java_package"), UPB_TABVALUE_PTR_INIT(&fields[35]), &strentries[120]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "cc_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[2]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "java_multiple_files"), UPB_TABVALUE_PTR_INIT(&fields[24]), NULL},
+ {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "java_outer_classname"), UPB_TABVALUE_PTR_INIT(&fields[34]), NULL},
+ {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[95]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\025", "\000", "\000", "\000", "java_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[23]), &strentries[102]},
- {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "java_generate_equals_and_hash"), UPB_TABVALUE_PTR_INIT(&fields[22]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "java_multiple_files"), UPB_TABVALUE_PTR_INIT(&fields[33]), &strentries[117]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "go_package"), UPB_TABVALUE_PTR_INIT(&fields[18]), NULL},
- {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "java_package"), UPB_TABVALUE_PTR_INIT(&fields[26]), NULL},
- {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "optimize_for"), UPB_TABVALUE_PTR_INIT(&fields[48]), NULL},
- {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "py_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[62]), NULL},
- {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "java_outer_classname"), UPB_TABVALUE_PTR_INIT(&fields[25]), NULL},
- {UPB_TABKEY_STR("\027", "\000", "\000", "\000", "message_set_wire_format"), UPB_TABVALUE_PTR_INIT(&fields[31]), &strentries[106]},
+ {UPB_TABKEY_STR("\025", "\000", "\000", "\000", "java_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[32]), &strentries[118]},
+ {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "java_generate_equals_and_hash"), UPB_TABVALUE_PTR_INIT(&fields[31]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[76]), NULL},
- {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "no_standard_descriptor_accessor"), UPB_TABVALUE_PTR_INIT(&fields[45]), NULL},
+ {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "javanano_use_deprecated_package"), UPB_TABVALUE_PTR_INIT(&fields[37]), &strentries[123]},
+ {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "py_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[81]), NULL},
+ {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "optimize_for"), UPB_TABVALUE_PTR_INIT(&fields[67]), NULL},
+ {UPB_TABKEY_STR("\026", "\000", "\000", "\000", "java_string_check_utf8"), UPB_TABVALUE_PTR_INIT(&fields[36]), NULL},
+ {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[12]), &strentries[119]},
+ {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "objc_class_prefix"), UPB_TABVALUE_PTR_INIT(&fields[64]), NULL},
+ {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "cc_enable_arenas"), UPB_TABVALUE_PTR_INIT(&fields[2]), NULL},
+ {UPB_TABKEY_STR("\027", "\000", "\000", "\000", "message_set_wire_format"), UPB_TABVALUE_PTR_INIT(&fields[46]), &strentries[128]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[39]), NULL},
- {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "input_type"), UPB_TABVALUE_PTR_INIT(&fields[20]), NULL},
+ {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL},
+ {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[9]), NULL},
+ {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "map_entry"), UPB_TABVALUE_PTR_INIT(&fields[45]), NULL},
+ {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "no_standard_descriptor_accessor"), UPB_TABVALUE_PTR_INIT(&fields[61]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "output_type"), UPB_TABVALUE_PTR_INIT(&fields[56]), NULL},
- {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[55]), NULL},
- {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL},
+ {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "client_streaming"), UPB_TABVALUE_PTR_INIT(&fields[4]), NULL},
+ {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "server_streaming"), UPB_TABVALUE_PTR_INIT(&fields[84]), NULL},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[56]), NULL},
+ {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "input_type"), UPB_TABVALUE_PTR_INIT(&fields[29]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "output_type"), UPB_TABVALUE_PTR_INIT(&fields[75]), NULL},
+ {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[70]), NULL},
+ {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL},
+ {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[54]), &strentries[122]},
- {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "method"), UPB_TABVALUE_PTR_INIT(&fields[33]), NULL},
- {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[35]), &strentries[121]},
- {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[72]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[50]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[72]), &strentries[150]},
+ {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "method"), UPB_TABVALUE_PTR_INIT(&fields[48]), NULL},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[57]), &strentries[149]},
+ {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
+ {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "location"), UPB_TABVALUE_PTR_INIT(&fields[30]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "location"), UPB_TABVALUE_PTR_INIT(&fields[44]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "span"), UPB_TABVALUE_PTR_INIT(&fields[65]), &strentries[139]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "trailing_comments"), UPB_TABVALUE_PTR_INIT(&fields[68]), NULL},
- {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "leading_comments"), UPB_TABVALUE_PTR_INIT(&fields[29]), &strentries[137]},
- {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "path"), UPB_TABVALUE_PTR_INIT(&fields[59]), NULL},
- {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "double_value"), UPB_TABVALUE_PTR_INIT(&fields[7]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "span"), UPB_TABVALUE_PTR_INIT(&fields[87]), &strentries[167]},
+ {UPB_TABKEY_STR("\031", "\000", "\000", "\000", "leading_detached_comments"), UPB_TABVALUE_PTR_INIT(&fields[43]), &strentries[165]},
+ {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "trailing_comments"), UPB_TABVALUE_PTR_INIT(&fields[92]), NULL},
+ {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "leading_comments"), UPB_TABVALUE_PTR_INIT(&fields[42]), &strentries[164]},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "path"), UPB_TABVALUE_PTR_INIT(&fields[78]), NULL},
+ {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "double_value"), UPB_TABVALUE_PTR_INIT(&fields[16]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[36]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[51]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "negative_int_value"), UPB_TABVALUE_PTR_INIT(&fields[43]), NULL},
+ {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "negative_int_value"), UPB_TABVALUE_PTR_INIT(&fields[59]), NULL},
{UPB_TABKEY_STR("\017", "\000", "\000", "\000", "aggregate_value"), UPB_TABVALUE_PTR_INIT(&fields[0]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "positive_int_value"), UPB_TABVALUE_PTR_INIT(&fields[60]), NULL},
- {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "identifier_value"), UPB_TABVALUE_PTR_INIT(&fields[19]), NULL},
- {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "string_value"), UPB_TABVALUE_PTR_INIT(&fields[67]), &strentries[154]},
+ {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "positive_int_value"), UPB_TABVALUE_PTR_INIT(&fields[79]), NULL},
+ {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "identifier_value"), UPB_TABVALUE_PTR_INIT(&fields[28]), NULL},
+ {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "string_value"), UPB_TABVALUE_PTR_INIT(&fields[90]), &strentries[182]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "is_extension"), UPB_TABVALUE_PTR_INIT(&fields[21]), NULL},
- {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "name_part"), UPB_TABVALUE_PTR_INIT(&fields[42]), NULL},
- {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REQUIRED"), UPB_TABVALUE_INT_INIT(2), &strentries[162]},
+ {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "is_extension"), UPB_TABVALUE_PTR_INIT(&fields[30]), NULL},
+ {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "name_part"), UPB_TABVALUE_PTR_INIT(&fields[58]), NULL},
+ {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REQUIRED"), UPB_TABVALUE_INT_INIT(2), &strentries[190]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REPEATED"), UPB_TABVALUE_INT_INIT(3), NULL},
{UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_OPTIONAL"), UPB_TABVALUE_INT_INIT(1), NULL},
@@ -5274,17 +5864,17 @@ static const upb_tabent strentries[236] = {
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_STRING"), UPB_TABVALUE_INT_INIT(9), NULL},
- {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_FLOAT"), UPB_TABVALUE_INT_INIT(2), &strentries[193]},
+ {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_FLOAT"), UPB_TABVALUE_INT_INIT(2), &strentries[221]},
{UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_DOUBLE"), UPB_TABVALUE_INT_INIT(1), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT32"), UPB_TABVALUE_INT_INIT(5), NULL},
{UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED32"), UPB_TABVALUE_INT_INIT(15), NULL},
{UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED32"), UPB_TABVALUE_INT_INIT(7), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_MESSAGE"), UPB_TABVALUE_INT_INIT(11), &strentries[194]},
+ {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_MESSAGE"), UPB_TABVALUE_INT_INIT(11), &strentries[222]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT64"), UPB_TABVALUE_INT_INIT(3), &strentries[191]},
+ {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT64"), UPB_TABVALUE_INT_INIT(3), &strentries[219]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
@@ -5292,7 +5882,7 @@ static const upb_tabent strentries[236] = {
{UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_ENUM"), UPB_TABVALUE_INT_INIT(14), NULL},
{UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT32"), UPB_TABVALUE_INT_INIT(13), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT64"), UPB_TABVALUE_INT_INIT(4), &strentries[190]},
+ {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT64"), UPB_TABVALUE_INT_INIT(4), &strentries[218]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED64"), UPB_TABVALUE_INT_INIT(16), NULL},
{UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_BYTES"), UPB_TABVALUE_INT_INIT(12), NULL},
@@ -5302,266 +5892,191 @@ static const upb_tabent strentries[236] = {
{UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT32"), UPB_TABVALUE_INT_INIT(17), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_STR("\004", "\000", "\000", "\000", "CORD"), UPB_TABVALUE_INT_INIT(1), NULL},
- {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "STRING"), UPB_TABVALUE_INT_INIT(0), &strentries[197]},
+ {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "STRING"), UPB_TABVALUE_INT_INIT(0), &strentries[225]},
{UPB_TABKEY_STR("\014", "\000", "\000", "\000", "STRING_PIECE"), UPB_TABVALUE_INT_INIT(2), NULL},
+ {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_NORMAL"), UPB_TABVALUE_INT_INIT(0), NULL},
+ {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_NUMBER"), UPB_TABVALUE_INT_INIT(2), NULL},
+ {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_STRING"), UPB_TABVALUE_INT_INIT(1), NULL},
{UPB_TABKEY_STR("\011", "\000", "\000", "\000", "CODE_SIZE"), UPB_TABVALUE_INT_INIT(2), NULL},
- {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "SPEED"), UPB_TABVALUE_INT_INIT(1), &strentries[203]},
+ {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "SPEED"), UPB_TABVALUE_INT_INIT(1), &strentries[235]},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
{UPB_TABKEY_STR("\014", "\000", "\000", "\000", "LITE_RUNTIME"), UPB_TABVALUE_INT_INIT(3), NULL},
- {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\047", "\000", "\000", "\000", "google.protobuf.SourceCodeInfo.Location"), UPB_TABVALUE_PTR_INIT(&msgs[17]), NULL},
- {UPB_TABKEY_STR("\043", "\000", "\000", "\000", "google.protobuf.UninterpretedOption"), UPB_TABVALUE_PTR_INIT(&msgs[18]), NULL},
- {UPB_TABKEY_STR("\043", "\000", "\000", "\000", "google.protobuf.FileDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[8]), NULL},
- {UPB_TABKEY_STR("\045", "\000", "\000", "\000", "google.protobuf.MethodDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[12]), NULL},
- {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\040", "\000", "\000", "\000", "google.protobuf.EnumValueOptions"), UPB_TABVALUE_PTR_INIT(&msgs[5]), NULL},
- {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "google.protobuf.DescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[0]), &strentries[228]},
- {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\036", "\000", "\000", "\000", "google.protobuf.SourceCodeInfo"), UPB_TABVALUE_PTR_INIT(&msgs[16]), NULL},
- {UPB_TABKEY_STR("\051", "\000", "\000", "\000", "google.protobuf.FieldDescriptorProto.Type"), UPB_TABVALUE_PTR_INIT(&enums[1]), NULL},
- {UPB_TABKEY_STR("\056", "\000", "\000", "\000", "google.protobuf.DescriptorProto.ExtensionRange"), UPB_TABVALUE_PTR_INIT(&msgs[1]), NULL},
- {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_STR("\050", "\000", "\000", "\000", "google.protobuf.EnumValueDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[4]), NULL},
- {UPB_TABKEY_STR("\034", "\000", "\000", "\000", "google.protobuf.FieldOptions"), UPB_TABVALUE_PTR_INIT(&msgs[7]), NULL},
- {UPB_TABKEY_STR("\033", "\000", "\000", "\000", "google.protobuf.FileOptions"), UPB_TABVALUE_PTR_INIT(&msgs[10]), NULL},
- {UPB_TABKEY_STR("\043", "\000", "\000", "\000", "google.protobuf.EnumDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[2]), &strentries[233]},
- {UPB_TABKEY_STR("\052", "\000", "\000", "\000", "google.protobuf.FieldDescriptorProto.Label"), UPB_TABVALUE_PTR_INIT(&enums[0]), NULL},
- {UPB_TABKEY_STR("\046", "\000", "\000", "\000", "google.protobuf.ServiceDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[14]), NULL},
- {UPB_TABKEY_STR("\042", "\000", "\000", "\000", "google.protobuf.FieldOptions.CType"), UPB_TABVALUE_PTR_INIT(&enums[2]), &strentries[229]},
- {UPB_TABKEY_STR("\041", "\000", "\000", "\000", "google.protobuf.FileDescriptorSet"), UPB_TABVALUE_PTR_INIT(&msgs[9]), &strentries[235]},
- {UPB_TABKEY_STR("\033", "\000", "\000", "\000", "google.protobuf.EnumOptions"), UPB_TABVALUE_PTR_INIT(&msgs[3]), NULL},
- {UPB_TABKEY_STR("\044", "\000", "\000", "\000", "google.protobuf.FieldDescriptorProto"), UPB_TABVALUE_PTR_INIT(&msgs[6]), NULL},
- {UPB_TABKEY_STR("\050", "\000", "\000", "\000", "google.protobuf.FileOptions.OptimizeMode"), UPB_TABVALUE_PTR_INIT(&enums[3]), &strentries[221]},
- {UPB_TABKEY_STR("\036", "\000", "\000", "\000", "google.protobuf.ServiceOptions"), UPB_TABVALUE_PTR_INIT(&msgs[15]), NULL},
- {UPB_TABKEY_STR("\036", "\000", "\000", "\000", "google.protobuf.MessageOptions"), UPB_TABVALUE_PTR_INIT(&msgs[11]), NULL},
- {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "google.protobuf.MethodOptions"), UPB_TABVALUE_PTR_INIT(&msgs[13]), &strentries[226]},
- {UPB_TABKEY_STR("\054", "\000", "\000", "\000", "google.protobuf.UninterpretedOption.NamePart"), UPB_TABVALUE_PTR_INIT(&msgs[19]), NULL},
};
-static const upb_tabent intentries[14] = {
+static const upb_tabent intentries[18] = {
+ {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL},
+ {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+ {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL},
+ {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL},
+ {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[95]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[77]), NULL},
+ {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[75]), NULL},
+ {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[76]), NULL},
+ {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL},
+ {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL},
{UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
- {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[72]), NULL},
+ {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
};
-static const upb_tabval arrays[232] = {
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[38]),
- UPB_TABVALUE_PTR_INIT(&fields[16]),
- UPB_TABVALUE_PTR_INIT(&fields[44]),
- UPB_TABVALUE_PTR_INIT(&fields[9]),
- UPB_TABVALUE_PTR_INIT(&fields[15]),
- UPB_TABVALUE_PTR_INIT(&fields[14]),
- UPB_TABVALUE_PTR_INIT(&fields[49]),
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[66]),
- UPB_TABVALUE_PTR_INIT(&fields[8]),
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[40]),
- UPB_TABVALUE_PTR_INIT(&fields[78]),
- UPB_TABVALUE_PTR_INIT(&fields[50]),
- UPB_TABVALUE_EMPTY_INIT,
+static const upb_tabval arrays[184] = {
UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[1]),
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[37]),
- UPB_TABVALUE_PTR_INIT(&fields[47]),
UPB_TABVALUE_PTR_INIT(&fields[52]),
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[41]),
- UPB_TABVALUE_PTR_INIT(&fields[12]),
- UPB_TABVALUE_PTR_INIT(&fields[46]),
- UPB_TABVALUE_PTR_INIT(&fields[27]),
- UPB_TABVALUE_PTR_INIT(&fields[69]),
- UPB_TABVALUE_PTR_INIT(&fields[70]),
- UPB_TABVALUE_PTR_INIT(&fields[4]),
- UPB_TABVALUE_PTR_INIT(&fields[51]),
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[3]),
- UPB_TABVALUE_PTR_INIT(&fields[58]),
- UPB_TABVALUE_PTR_INIT(&fields[6]),
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[28]),
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[11]),
- UPB_TABVALUE_PTR_INIT(&fields[79]),
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[34]),
- UPB_TABVALUE_PTR_INIT(&fields[57]),
- UPB_TABVALUE_PTR_INIT(&fields[5]),
- UPB_TABVALUE_PTR_INIT(&fields[32]),
- UPB_TABVALUE_PTR_INIT(&fields[10]),
- UPB_TABVALUE_PTR_INIT(&fields[63]),
- UPB_TABVALUE_PTR_INIT(&fields[13]),
- UPB_TABVALUE_PTR_INIT(&fields[53]),
- UPB_TABVALUE_PTR_INIT(&fields[64]),
- UPB_TABVALUE_PTR_INIT(&fields[61]),
- UPB_TABVALUE_PTR_INIT(&fields[80]),
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[17]),
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[26]),
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_PTR_INIT(&fields[25]),
- UPB_TABVALUE_PTR_INIT(&fields[48]),
+ UPB_TABVALUE_PTR_INIT(&fields[60]),
+ UPB_TABVALUE_PTR_INIT(&fields[19]),
UPB_TABVALUE_PTR_INIT(&fields[24]),
- UPB_TABVALUE_PTR_INIT(&fields[18]),
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[2]),
- UPB_TABVALUE_PTR_INIT(&fields[23]),
- UPB_TABVALUE_PTR_INIT(&fields[62]),
- UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_PTR_INIT(&fields[22]),
+ UPB_TABVALUE_PTR_INIT(&fields[68]),
+ UPB_TABVALUE_PTR_INIT(&fields[65]),
+ UPB_TABVALUE_PTR_INIT(&fields[83]),
+ UPB_TABVALUE_PTR_INIT(&fields[82]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[89]),
+ UPB_TABVALUE_PTR_INIT(&fields[18]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[88]),
+ UPB_TABVALUE_PTR_INIT(&fields[17]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[49]),
+ UPB_TABVALUE_PTR_INIT(&fields[102]),
+ UPB_TABVALUE_PTR_INIT(&fields[74]),
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[1]),
+ UPB_TABVALUE_PTR_INIT(&fields[13]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[53]),
+ UPB_TABVALUE_PTR_INIT(&fields[62]),
+ UPB_TABVALUE_PTR_INIT(&fields[73]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[15]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[55]),
+ UPB_TABVALUE_PTR_INIT(&fields[21]),
+ UPB_TABVALUE_PTR_INIT(&fields[63]),
+ UPB_TABVALUE_PTR_INIT(&fields[40]),
+ UPB_TABVALUE_PTR_INIT(&fields[93]),
+ UPB_TABVALUE_PTR_INIT(&fields[94]),
+ UPB_TABVALUE_PTR_INIT(&fields[7]),
+ UPB_TABVALUE_PTR_INIT(&fields[71]),
+ UPB_TABVALUE_PTR_INIT(&fields[66]),
+ UPB_TABVALUE_PTR_INIT(&fields[38]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[6]),
+ UPB_TABVALUE_PTR_INIT(&fields[77]),
+ UPB_TABVALUE_PTR_INIT(&fields[10]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[41]),
+ UPB_TABVALUE_PTR_INIT(&fields[39]),
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[103]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[54]),
+ UPB_TABVALUE_PTR_INIT(&fields[76]),
+ UPB_TABVALUE_PTR_INIT(&fields[8]),
+ UPB_TABVALUE_PTR_INIT(&fields[47]),
+ UPB_TABVALUE_PTR_INIT(&fields[20]),
+ UPB_TABVALUE_PTR_INIT(&fields[85]),
+ UPB_TABVALUE_PTR_INIT(&fields[23]),
+ UPB_TABVALUE_PTR_INIT(&fields[69]),
+ UPB_TABVALUE_PTR_INIT(&fields[86]),
+ UPB_TABVALUE_PTR_INIT(&fields[80]),
+ UPB_TABVALUE_PTR_INIT(&fields[104]),
+ UPB_TABVALUE_PTR_INIT(&fields[91]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[26]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[35]),
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[34]),
+ UPB_TABVALUE_PTR_INIT(&fields[67]),
+ UPB_TABVALUE_PTR_INIT(&fields[33]),
+ UPB_TABVALUE_PTR_INIT(&fields[27]),
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[3]),
+ UPB_TABVALUE_PTR_INIT(&fields[32]),
+ UPB_TABVALUE_PTR_INIT(&fields[81]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[31]),
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[12]),
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[36]),
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[2]),
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[64]),
+ UPB_TABVALUE_PTR_INIT(&fields[5]),
+ UPB_TABVALUE_PTR_INIT(&fields[37]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[46]),
+ UPB_TABVALUE_PTR_INIT(&fields[61]),
+ UPB_TABVALUE_PTR_INIT(&fields[9]),
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[31]),
UPB_TABVALUE_PTR_INIT(&fields[45]),
UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[39]),
- UPB_TABVALUE_PTR_INIT(&fields[20]),
UPB_TABVALUE_PTR_INIT(&fields[56]),
- UPB_TABVALUE_PTR_INIT(&fields[55]),
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[29]),
+ UPB_TABVALUE_PTR_INIT(&fields[75]),
+ UPB_TABVALUE_PTR_INIT(&fields[70]),
+ UPB_TABVALUE_PTR_INIT(&fields[4]),
+ UPB_TABVALUE_PTR_INIT(&fields[84]),
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[50]),
UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[35]),
- UPB_TABVALUE_PTR_INIT(&fields[33]),
- UPB_TABVALUE_PTR_INIT(&fields[54]),
+ UPB_TABVALUE_PTR_INIT(&fields[57]),
+ UPB_TABVALUE_PTR_INIT(&fields[48]),
+ UPB_TABVALUE_PTR_INIT(&fields[72]),
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[44]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[78]),
+ UPB_TABVALUE_PTR_INIT(&fields[87]),
+ UPB_TABVALUE_PTR_INIT(&fields[42]),
+ UPB_TABVALUE_PTR_INIT(&fields[92]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[43]),
UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[30]),
UPB_TABVALUE_EMPTY_INIT,
+ UPB_TABVALUE_PTR_INIT(&fields[51]),
+ UPB_TABVALUE_PTR_INIT(&fields[28]),
+ UPB_TABVALUE_PTR_INIT(&fields[79]),
UPB_TABVALUE_PTR_INIT(&fields[59]),
- UPB_TABVALUE_PTR_INIT(&fields[65]),
- UPB_TABVALUE_PTR_INIT(&fields[29]),
- UPB_TABVALUE_PTR_INIT(&fields[68]),
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[36]),
- UPB_TABVALUE_PTR_INIT(&fields[19]),
- UPB_TABVALUE_PTR_INIT(&fields[60]),
- UPB_TABVALUE_PTR_INIT(&fields[43]),
- UPB_TABVALUE_PTR_INIT(&fields[7]),
- UPB_TABVALUE_PTR_INIT(&fields[67]),
+ UPB_TABVALUE_PTR_INIT(&fields[16]),
+ UPB_TABVALUE_PTR_INIT(&fields[90]),
UPB_TABVALUE_PTR_INIT(&fields[0]),
UPB_TABVALUE_EMPTY_INIT,
- UPB_TABVALUE_PTR_INIT(&fields[42]),
- UPB_TABVALUE_PTR_INIT(&fields[21]),
+ UPB_TABVALUE_PTR_INIT(&fields[58]),
+ UPB_TABVALUE_PTR_INIT(&fields[30]),
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_PTR_INIT("LABEL_OPTIONAL"),
UPB_TABVALUE_PTR_INIT("LABEL_REQUIRED"),
@@ -5588,21 +6103,69 @@ static const upb_tabval arrays[232] = {
UPB_TABVALUE_PTR_INIT("STRING"),
UPB_TABVALUE_PTR_INIT("CORD"),
UPB_TABVALUE_PTR_INIT("STRING_PIECE"),
+ UPB_TABVALUE_PTR_INIT("JS_NORMAL"),
+ UPB_TABVALUE_PTR_INIT("JS_STRING"),
+ UPB_TABVALUE_PTR_INIT("JS_NUMBER"),
UPB_TABVALUE_EMPTY_INIT,
UPB_TABVALUE_PTR_INIT("SPEED"),
UPB_TABVALUE_PTR_INIT("CODE_SIZE"),
UPB_TABVALUE_PTR_INIT("LITE_RUNTIME"),
};
-static const upb_symtab symtab = UPB_SYMTAB_INIT(UPB_STRTABLE_INIT(24, 31, UPB_CTYPE_PTR, 5, &strentries[204]), &reftables[210], &reftables[211]);
-
-const upb_symtab *upbdefs_google_protobuf_descriptor(const void *owner) {
- upb_symtab_ref(&symtab, owner);
- return &symtab;
-}
-
#ifdef UPB_DEBUG_REFS
-static upb_inttable reftables[212] = {
+static upb_inttable reftables[264] = {
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+ UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
@@ -5818,6 +6381,45 @@ static upb_inttable reftables[212] = {
};
#endif
+static const upb_msgdef *refm(const upb_msgdef *m, const void *owner) {
+ upb_msgdef_ref(m, owner);
+ return m;
+}
+
+static const upb_enumdef *refe(const upb_enumdef *e, const void *owner) {
+ upb_enumdef_ref(e, owner);
+ return e;
+}
+
+/* Public API. */
+const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_get(const void *owner) { return refm(&msgs[0], owner); }
+const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(const void *owner) { return refm(&msgs[1], owner); }
+const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(const void *owner) { return refm(&msgs[2], owner); }
+const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto_get(const void *owner) { return refm(&msgs[3], owner); }
+const upb_msgdef *upbdefs_google_protobuf_EnumOptions_get(const void *owner) { return refm(&msgs[4], owner); }
+const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto_get(const void *owner) { return refm(&msgs[5], owner); }
+const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions_get(const void *owner) { return refm(&msgs[6], owner); }
+const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto_get(const void *owner) { return refm(&msgs[7], owner); }
+const upb_msgdef *upbdefs_google_protobuf_FieldOptions_get(const void *owner) { return refm(&msgs[8], owner); }
+const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto_get(const void *owner) { return refm(&msgs[9], owner); }
+const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet_get(const void *owner) { return refm(&msgs[10], owner); }
+const upb_msgdef *upbdefs_google_protobuf_FileOptions_get(const void *owner) { return refm(&msgs[11], owner); }
+const upb_msgdef *upbdefs_google_protobuf_MessageOptions_get(const void *owner) { return refm(&msgs[12], owner); }
+const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto_get(const void *owner) { return refm(&msgs[13], owner); }
+const upb_msgdef *upbdefs_google_protobuf_MethodOptions_get(const void *owner) { return refm(&msgs[14], owner); }
+const upb_msgdef *upbdefs_google_protobuf_OneofDescriptorProto_get(const void *owner) { return refm(&msgs[15], owner); }
+const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto_get(const void *owner) { return refm(&msgs[16], owner); }
+const upb_msgdef *upbdefs_google_protobuf_ServiceOptions_get(const void *owner) { return refm(&msgs[17], owner); }
+const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_get(const void *owner) { return refm(&msgs[18], owner); }
+const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location_get(const void *owner) { return refm(&msgs[19], owner); }
+const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_get(const void *owner) { return refm(&msgs[20], owner); }
+const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart_get(const void *owner) { return refm(&msgs[21], owner); }
+
+const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label_get(const void *owner) { return refe(&enums[0], owner); }
+const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type_get(const void *owner) { return refe(&enums[1], owner); }
+const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType_get(const void *owner) { return refe(&enums[2], owner); }
+const upb_enumdef *upbdefs_google_protobuf_FieldOptions_JSType_get(const void *owner) { return refe(&enums[3], owner); }
+const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode_get(const void *owner) { return refe(&enums[4], owner); }
/*
** XXX: The routines in this file that consume a string do not currently
** support having the string span buffers. In the future, as upb_sink and
@@ -5831,14 +6433,10 @@ static upb_inttable reftables[212] = {
#include <stdlib.h>
#include <string.h>
-/* upb_deflist is an internal-only dynamic array for storing a growing list of
- * upb_defs. */
-typedef struct {
- upb_def **defs;
- size_t len;
- size_t size;
- bool owned;
-} upb_deflist;
+/* Compares a NULL-terminated string with a non-NULL-terminated string. */
+static bool upb_streq(const char *str, const char *buf, size_t n) {
+ return strlen(str) == n && memcmp(str, buf, n) == 0;
+}
/* We keep a stack of all the messages scopes we are currently in, as well as
* the top-level file scope. This is necessary to correctly qualify the
@@ -5849,6 +6447,8 @@ typedef struct {
/* Index of the first def that is under this scope. For msgdefs, the
* msgdef itself is at start-1. */
int start;
+ uint32_t oneof_start;
+ uint32_t oneof_index;
} upb_descreader_frame;
/* The maximum number of nested declarations that are allowed, ie.
@@ -5865,9 +6465,11 @@ typedef struct {
struct upb_descreader {
upb_sink sink;
- upb_deflist defs;
+ upb_inttable files;
+ upb_filedef *file; /* The last file in files. */
upb_descreader_frame stack[UPB_MAX_MESSAGE_NESTING];
int stack_len;
+ upb_inttable oneofs;
uint32_t number;
char *name;
@@ -5880,7 +6482,7 @@ struct upb_descreader {
};
static char *upb_strndup(const char *buf, size_t n) {
- char *ret = malloc(n + 1);
+ char *ret = upb_gmalloc(n + 1);
if (!ret) return NULL;
memcpy(ret, buf, n);
ret[n] = '\0';
@@ -5894,9 +6496,12 @@ static char *upb_strndup(const char *buf, size_t n) {
* Caller owns a ref on the returned string. */
static char *upb_join(const char *base, const char *name) {
if (!base || strlen(base) == 0) {
- return upb_strdup(name);
+ return upb_gstrdup(name);
} else {
- char *ret = malloc(strlen(base) + strlen(name) + 2);
+ char *ret = upb_gmalloc(strlen(base) + strlen(name) + 2);
+ if (!ret) {
+ return NULL;
+ }
ret[0] = '\0';
strcat(ret, base);
strcat(ret, ".");
@@ -5905,57 +6510,21 @@ static char *upb_join(const char *base, const char *name) {
}
}
-
-/* upb_deflist ****************************************************************/
-
-void upb_deflist_init(upb_deflist *l) {
- l->size = 0;
- l->defs = NULL;
- l->len = 0;
- l->owned = true;
-}
-
-void upb_deflist_uninit(upb_deflist *l) {
- size_t i;
- if (l->owned)
- for(i = 0; i < l->len; i++)
- upb_def_unref(l->defs[i], l);
- free(l->defs);
-}
-
-bool upb_deflist_push(upb_deflist *l, upb_def *d) {
- if(++l->len >= l->size) {
- size_t new_size = UPB_MAX(l->size, 4);
- new_size *= 2;
- l->defs = realloc(l->defs, new_size * sizeof(void *));
- if (!l->defs) return false;
- l->size = new_size;
- }
- l->defs[l->len - 1] = d;
- return true;
-}
-
-void upb_deflist_donaterefs(upb_deflist *l, void *owner) {
- size_t i;
- assert(l->owned);
- for (i = 0; i < l->len; i++)
- upb_def_donateref(l->defs[i], l, owner);
- l->owned = false;
-}
-
-static upb_def *upb_deflist_last(upb_deflist *l) {
- return l->defs[l->len-1];
-}
-
/* Qualify the defname for all defs starting with offset "start" with "str". */
-static void upb_deflist_qualify(upb_deflist *l, char *str, int32_t start) {
- uint32_t i;
- for (i = start; i < l->len; i++) {
- upb_def *def = l->defs[i];
+static bool upb_descreader_qualify(upb_filedef *f, char *str, int32_t start) {
+ size_t i;
+ for (i = start; i < upb_filedef_defcount(f); i++) {
+ upb_def *def = upb_filedef_mutabledef(f, i);
char *name = upb_join(str, upb_def_fullname(def));
+ if (!name) {
+ /* Need better logic here; at this point we've qualified some names but
+ * not others. */
+ return false;
+ }
upb_def_setfullname(def, name, NULL);
- free(name);
+ upb_gfree(name);
}
+ return true;
}
@@ -5963,63 +6532,178 @@ static void upb_deflist_qualify(upb_deflist *l, char *str, int32_t start) {
static upb_msgdef *upb_descreader_top(upb_descreader *r) {
int index;
- assert(r->stack_len > 1);
+ UPB_ASSERT(r->stack_len > 1);
index = r->stack[r->stack_len-1].start - 1;
- assert(index >= 0);
- return upb_downcast_msgdef_mutable(r->defs.defs[index]);
+ UPB_ASSERT(index >= 0);
+ return upb_downcast_msgdef_mutable(upb_filedef_mutabledef(r->file, index));
}
static upb_def *upb_descreader_last(upb_descreader *r) {
- return upb_deflist_last(&r->defs);
+ return upb_filedef_mutabledef(r->file, upb_filedef_defcount(r->file) - 1);
}
/* Start/end handlers for FileDescriptorProto and DescriptorProto (the two
* entities that have names and can contain sub-definitions. */
void upb_descreader_startcontainer(upb_descreader *r) {
upb_descreader_frame *f = &r->stack[r->stack_len++];
- f->start = r->defs.len;
+ f->start = upb_filedef_defcount(r->file);
+ f->oneof_start = upb_inttable_count(&r->oneofs);
+ f->oneof_index = 0;
f->name = NULL;
}
-void upb_descreader_endcontainer(upb_descreader *r) {
- upb_descreader_frame *f = &r->stack[--r->stack_len];
- upb_deflist_qualify(&r->defs, f->name, f->start);
- free(f->name);
+bool upb_descreader_endcontainer(upb_descreader *r) {
+ upb_descreader_frame *f = &r->stack[r->stack_len - 1];
+
+ while (upb_inttable_count(&r->oneofs) > f->oneof_start) {
+ upb_oneofdef *o = upb_value_getptr(upb_inttable_pop(&r->oneofs));
+ bool ok = upb_msgdef_addoneof(upb_descreader_top(r), o, &r->oneofs, NULL);
+ UPB_ASSERT(ok);
+ }
+
+ if (!upb_descreader_qualify(r->file, f->name, f->start)) {
+ return false;
+ }
+ upb_gfree(f->name);
f->name = NULL;
+
+ r->stack_len--;
+ return true;
}
void upb_descreader_setscopename(upb_descreader *r, char *str) {
upb_descreader_frame *f = &r->stack[r->stack_len-1];
- free(f->name);
+ upb_gfree(f->name);
f->name = str;
}
-/* Handlers for google.protobuf.FileDescriptorProto. */
-static bool file_startmsg(void *r, const void *hd) {
+static upb_oneofdef *upb_descreader_getoneof(upb_descreader *r,
+ uint32_t index) {
+ bool found;
+ upb_value val;
+ upb_descreader_frame *f = &r->stack[r->stack_len-1];
+
+ /* DescriptorProto messages can be nested, so we will see the nested messages
+ * between when we see the FieldDescriptorProto and the OneofDescriptorProto.
+ * We need to preserve the oneofs in between these two things. */
+ index += f->oneof_start;
+
+ while (upb_inttable_count(&r->oneofs) <= index) {
+ upb_inttable_push(&r->oneofs, upb_value_ptr(upb_oneofdef_new(&r->oneofs)));
+ }
+
+ found = upb_inttable_lookup(&r->oneofs, index, &val);
+ UPB_ASSERT(found);
+ return upb_value_getptr(val);
+}
+
+/** Handlers for google.protobuf.FileDescriptorSet. ***************************/
+
+static void *fileset_startfile(void *closure, const void *hd) {
+ upb_descreader *r = closure;
+ UPB_UNUSED(hd);
+ r->file = upb_filedef_new(&r->files);
+ upb_inttable_push(&r->files, upb_value_ptr(r->file));
+ return r;
+}
+
+/** Handlers for google.protobuf.FileDescriptorProto. *************************/
+
+static bool file_start(void *closure, const void *hd) {
+ upb_descreader *r = closure;
UPB_UNUSED(hd);
upb_descreader_startcontainer(r);
return true;
}
-static bool file_endmsg(void *closure, const void *hd, upb_status *status) {
+static bool file_end(void *closure, const void *hd, upb_status *status) {
upb_descreader *r = closure;
UPB_UNUSED(hd);
UPB_UNUSED(status);
- upb_descreader_endcontainer(r);
- return true;
+ return upb_descreader_endcontainer(r);
+}
+
+static size_t file_onname(void *closure, const void *hd, const char *buf,
+ size_t n, const upb_bufhandle *handle) {
+ upb_descreader *r = closure;
+ char *name;
+ bool ok;
+ UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
+
+ name = upb_strndup(buf, n);
+ /* XXX: see comment at the top of the file. */
+ ok = upb_filedef_setname(r->file, name, NULL);
+ upb_gfree(name);
+ UPB_ASSERT(ok);
+ return n;
}
static size_t file_onpackage(void *closure, const void *hd, const char *buf,
size_t n, const upb_bufhandle *handle) {
upb_descreader *r = closure;
+ char *package;
+ bool ok;
+ UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
+
+ package = upb_strndup(buf, n);
+ /* XXX: see comment at the top of the file. */
+ upb_descreader_setscopename(r, package);
+ ok = upb_filedef_setpackage(r->file, package, NULL);
+ UPB_ASSERT(ok);
+ return n;
+}
+
+static size_t file_onsyntax(void *closure, const void *hd, const char *buf,
+ size_t n, const upb_bufhandle *handle) {
+ upb_descreader *r = closure;
+ bool ok;
UPB_UNUSED(hd);
UPB_UNUSED(handle);
/* XXX: see comment at the top of the file. */
- upb_descreader_setscopename(r, upb_strndup(buf, n));
+ if (upb_streq("proto2", buf, n)) {
+ ok = upb_filedef_setsyntax(r->file, UPB_SYNTAX_PROTO2, NULL);
+ } else if (upb_streq("proto3", buf, n)) {
+ ok = upb_filedef_setsyntax(r->file, UPB_SYNTAX_PROTO3, NULL);
+ } else {
+ ok = false;
+ }
+
+ UPB_ASSERT(ok);
return n;
}
-/* Handlers for google.protobuf.EnumValueDescriptorProto. */
+static void *file_startmsg(void *closure, const void *hd) {
+ upb_descreader *r = closure;
+ upb_msgdef *m = upb_msgdef_new(&m);
+ bool ok = upb_filedef_addmsg(r->file, m, &m, NULL);
+ UPB_UNUSED(hd);
+ UPB_ASSERT(ok);
+ return r;
+}
+
+static void *file_startenum(void *closure, const void *hd) {
+ upb_descreader *r = closure;
+ upb_enumdef *e = upb_enumdef_new(&e);
+ bool ok = upb_filedef_addenum(r->file, e, &e, NULL);
+ UPB_UNUSED(hd);
+ UPB_ASSERT(ok);
+ return r;
+}
+
+static void *file_startext(void *closure, const void *hd) {
+ upb_descreader *r = closure;
+ bool ok;
+ r->f = upb_fielddef_new(r);
+ ok = upb_filedef_addext(r->file, r->f, r, NULL);
+ UPB_UNUSED(hd);
+ UPB_ASSERT(ok);
+ return r;
+}
+
+/** Handlers for google.protobuf.EnumValueDescriptorProto. *********************/
+
static bool enumval_startmsg(void *closure, const void *hd) {
upb_descreader *r = closure;
UPB_UNUSED(hd);
@@ -6034,7 +6718,7 @@ static size_t enumval_onname(void *closure, const void *hd, const char *buf,
UPB_UNUSED(hd);
UPB_UNUSED(handle);
/* XXX: see comment at the top of the file. */
- free(r->name);
+ upb_gfree(r->name);
r->name = upb_strndup(buf, n);
r->saw_name = true;
return n;
@@ -6059,20 +6743,12 @@ static bool enumval_endmsg(void *closure, const void *hd, upb_status *status) {
}
e = upb_downcast_enumdef_mutable(upb_descreader_last(r));
upb_enumdef_addval(e, r->name, r->number, status);
- free(r->name);
+ upb_gfree(r->name);
r->name = NULL;
return true;
}
-
-/* Handlers for google.protobuf.EnumDescriptorProto. */
-static bool enum_startmsg(void *closure, const void *hd) {
- upb_descreader *r = closure;
- UPB_UNUSED(hd);
- upb_deflist_push(&r->defs,
- upb_enumdef_upcast_mutable(upb_enumdef_new(&r->defs)));
- return true;
-}
+/** Handlers for google.protobuf.EnumDescriptorProto. *************************/
static bool enum_endmsg(void *closure, const void *hd, upb_status *status) {
upb_descreader *r = closure;
@@ -6099,16 +6775,17 @@ static size_t enum_onname(void *closure, const void *hd, const char *buf,
UPB_UNUSED(handle);
/* XXX: see comment at the top of the file. */
upb_def_setfullname(upb_descreader_last(r), fullname, NULL);
- free(fullname);
+ upb_gfree(fullname);
return n;
}
-/* Handlers for google.protobuf.FieldDescriptorProto */
+/** Handlers for google.protobuf.FieldDescriptorProto *************************/
+
static bool field_startmsg(void *closure, const void *hd) {
upb_descreader *r = closure;
UPB_UNUSED(hd);
- r->f = upb_fielddef_new(&r->defs);
- free(r->default_string);
+ UPB_ASSERT(r->f);
+ upb_gfree(r->default_string);
r->default_string = NULL;
/* fielddefs default to packed, but descriptors default to non-packed. */
@@ -6193,9 +6870,9 @@ static bool field_endmsg(void *closure, const void *hd, upb_status *status) {
UPB_UNUSED(hd);
/* TODO: verify that all required fields were present. */
- assert(upb_fielddef_number(f) != 0);
- assert(upb_fielddef_name(f) != NULL);
- assert((upb_fielddef_subdefname(f) != NULL) == upb_fielddef_hassubdef(f));
+ UPB_ASSERT(upb_fielddef_number(f) != 0);
+ UPB_ASSERT(upb_fielddef_name(f) != NULL);
+ UPB_ASSERT((upb_fielddef_subdefname(f) != NULL) == upb_fielddef_hassubdef(f));
if (r->default_string) {
if (upb_fielddef_issubmsg(f)) {
@@ -6250,10 +6927,11 @@ static bool field_onlabel(void *closure, const void *hd, int32_t val) {
static bool field_onnumber(void *closure, const void *hd, int32_t val) {
upb_descreader *r = closure;
- bool ok = upb_fielddef_setnumber(r->f, val, NULL);
+ bool ok;
UPB_UNUSED(hd);
- UPB_ASSERT_VAR(ok, ok);
+ ok = upb_fielddef_setnumber(r->f, val, NULL);
+ UPB_ASSERT(ok);
return true;
}
@@ -6266,7 +6944,7 @@ static size_t field_onname(void *closure, const void *hd, const char *buf,
/* XXX: see comment at the top of the file. */
upb_fielddef_setname(r->f, name, NULL);
- free(name);
+ upb_gfree(name);
return n;
}
@@ -6279,7 +6957,7 @@ static size_t field_ontypename(void *closure, const void *hd, const char *buf,
/* XXX: see comment at the top of the file. */
upb_fielddef_setsubdefname(r->f, name, NULL);
- free(name);
+ upb_gfree(name);
return n;
}
@@ -6292,7 +6970,7 @@ static size_t field_onextendee(void *closure, const void *hd, const char *buf,
/* XXX: see comment at the top of the file. */
upb_fielddef_setcontainingtypename(r->f, name, NULL);
- free(name);
+ upb_gfree(name);
return n;
}
@@ -6305,23 +6983,49 @@ static size_t field_ondefaultval(void *closure, const void *hd, const char *buf,
/* Have to convert from string to the correct type, but we might not know the
* type yet, so we save it as a string until the end of the field.
* XXX: see comment at the top of the file. */
- free(r->default_string);
+ upb_gfree(r->default_string);
r->default_string = upb_strndup(buf, n);
return n;
}
-/* Handlers for google.protobuf.DescriptorProto (representing a message). */
-static bool msg_startmsg(void *closure, const void *hd) {
+static bool field_ononeofindex(void *closure, const void *hd, int32_t index) {
+ upb_descreader *r = closure;
+ upb_oneofdef *o = upb_descreader_getoneof(r, index);
+ bool ok = upb_oneofdef_addfield(o, r->f, &r->f, NULL);
+ UPB_UNUSED(hd);
+
+ UPB_ASSERT(ok);
+ return true;
+}
+
+/** Handlers for google.protobuf.OneofDescriptorProto. ************************/
+
+static size_t oneof_name(void *closure, const void *hd, const char *buf,
+ size_t n, const upb_bufhandle *handle) {
+ upb_descreader *r = closure;
+ upb_descreader_frame *f = &r->stack[r->stack_len-1];
+ upb_oneofdef *o = upb_descreader_getoneof(r, f->oneof_index++);
+ char *name_null_terminated = upb_strndup(buf, n);
+ bool ok = upb_oneofdef_setname(o, name_null_terminated, NULL);
+ UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
+
+ UPB_ASSERT(ok);
+ free(name_null_terminated);
+ return n;
+}
+
+/** Handlers for google.protobuf.DescriptorProto ******************************/
+
+static bool msg_start(void *closure, const void *hd) {
upb_descreader *r = closure;
UPB_UNUSED(hd);
- upb_deflist_push(&r->defs,
- upb_msgdef_upcast_mutable(upb_msgdef_new(&r->defs)));
upb_descreader_startcontainer(r);
return true;
}
-static bool msg_endmsg(void *closure, const void *hd, upb_status *status) {
+static bool msg_end(void *closure, const void *hd, upb_status *status) {
upb_descreader *r = closure;
upb_msgdef *m = upb_descreader_top(r);
UPB_UNUSED(hd);
@@ -6330,12 +7034,11 @@ static bool msg_endmsg(void *closure, const void *hd, upb_status *status) {
upb_status_seterrmsg(status, "Encountered message with no name.");
return false;
}
- upb_descreader_endcontainer(r);
- return true;
+ return upb_descreader_endcontainer(r);
}
-static size_t msg_onname(void *closure, const void *hd, const char *buf,
- size_t n, const upb_bufhandle *handle) {
+static size_t msg_name(void *closure, const void *hd, const char *buf,
+ size_t n, const upb_bufhandle *handle) {
upb_descreader *r = closure;
upb_msgdef *m = upb_descreader_top(r);
/* XXX: see comment at the top of the file. */
@@ -6348,91 +7051,158 @@ static size_t msg_onname(void *closure, const void *hd, const char *buf,
return n;
}
-static bool msg_onendfield(void *closure, const void *hd) {
+static void *msg_startmsg(void *closure, const void *hd) {
+ upb_descreader *r = closure;
+ upb_msgdef *m = upb_msgdef_new(&m);
+ bool ok = upb_filedef_addmsg(r->file, m, &m, NULL);
+ UPB_UNUSED(hd);
+ UPB_ASSERT(ok);
+ return r;
+}
+
+static void *msg_startext(void *closure, const void *hd) {
+ upb_descreader *r = closure;
+ upb_fielddef *f = upb_fielddef_new(&f);
+ bool ok = upb_filedef_addext(r->file, f, &f, NULL);
+ UPB_UNUSED(hd);
+ UPB_ASSERT(ok);
+ return r;
+}
+
+static void *msg_startfield(void *closure, const void *hd) {
+ upb_descreader *r = closure;
+ r->f = upb_fielddef_new(&r->f);
+ /* We can't add the new field to the message until its name/number are
+ * filled in. */
+ UPB_UNUSED(hd);
+ return r;
+}
+
+static bool msg_endfield(void *closure, const void *hd) {
upb_descreader *r = closure;
upb_msgdef *m = upb_descreader_top(r);
+ bool ok;
UPB_UNUSED(hd);
- upb_msgdef_addfield(m, r->f, &r->defs, NULL);
+ /* Oneof fields are added to the msgdef through their oneof, so don't need to
+ * be added here. */
+ if (upb_fielddef_containingoneof(r->f) == NULL) {
+ ok = upb_msgdef_addfield(m, r->f, &r->f, NULL);
+ UPB_ASSERT(ok);
+ }
r->f = NULL;
return true;
}
-static bool pushextension(void *closure, const void *hd) {
+static bool msg_onmapentry(void *closure, const void *hd, bool mapentry) {
upb_descreader *r = closure;
+ upb_msgdef *m = upb_descreader_top(r);
UPB_UNUSED(hd);
- assert(upb_fielddef_containingtypename(r->f));
- upb_fielddef_setisextension(r->f, true);
- upb_deflist_push(&r->defs, upb_fielddef_upcast_mutable(r->f));
+ upb_msgdef_setmapentry(m, mapentry);
r->f = NULL;
return true;
}
-#define D(name) upbdefs_google_protobuf_ ## name(s)
+
+
+/** Code to register handlers *************************************************/
+
+#define F(msg, field) upbdefs_google_protobuf_ ## msg ## _f_ ## field(m)
static void reghandlers(const void *closure, upb_handlers *h) {
- const upb_symtab *s = closure;
const upb_msgdef *m = upb_handlers_msgdef(h);
+ UPB_UNUSED(closure);
- if (m == D(DescriptorProto)) {
- upb_handlers_setstartmsg(h, &msg_startmsg, NULL);
- upb_handlers_setendmsg(h, &msg_endmsg, NULL);
- upb_handlers_setstring(h, D(DescriptorProto_name), &msg_onname, NULL);
- upb_handlers_setendsubmsg(h, D(DescriptorProto_field), &msg_onendfield,
- NULL);
- upb_handlers_setendsubmsg(h, D(DescriptorProto_extension), &pushextension,
- NULL);
- } else if (m == D(FileDescriptorProto)) {
- upb_handlers_setstartmsg(h, &file_startmsg, NULL);
- upb_handlers_setendmsg(h, &file_endmsg, NULL);
- upb_handlers_setstring(h, D(FileDescriptorProto_package), &file_onpackage,
+ if (upbdefs_google_protobuf_FileDescriptorSet_is(m)) {
+ upb_handlers_setstartsubmsg(h, F(FileDescriptorSet, file),
+ &fileset_startfile, NULL);
+ } else if (upbdefs_google_protobuf_DescriptorProto_is(m)) {
+ upb_handlers_setstartmsg(h, &msg_start, NULL);
+ upb_handlers_setendmsg(h, &msg_end, NULL);
+ upb_handlers_setstring(h, F(DescriptorProto, name), &msg_name, NULL);
+ upb_handlers_setstartsubmsg(h, F(DescriptorProto, extension), &msg_startext,
+ NULL);
+ upb_handlers_setstartsubmsg(h, F(DescriptorProto, nested_type),
+ &msg_startmsg, NULL);
+ upb_handlers_setstartsubmsg(h, F(DescriptorProto, field),
+ &msg_startfield, NULL);
+ upb_handlers_setendsubmsg(h, F(DescriptorProto, field),
+ &msg_endfield, NULL);
+ upb_handlers_setstartsubmsg(h, F(DescriptorProto, enum_type),
+ &file_startenum, NULL);
+ } else if (upbdefs_google_protobuf_FileDescriptorProto_is(m)) {
+ upb_handlers_setstartmsg(h, &file_start, NULL);
+ upb_handlers_setendmsg(h, &file_end, NULL);
+ upb_handlers_setstring(h, F(FileDescriptorProto, name), &file_onname,
+ NULL);
+ upb_handlers_setstring(h, F(FileDescriptorProto, package), &file_onpackage,
NULL);
- upb_handlers_setendsubmsg(h, D(FileDescriptorProto_extension), &pushextension,
- NULL);
- } else if (m == D(EnumValueDescriptorProto)) {
+ upb_handlers_setstring(h, F(FileDescriptorProto, syntax), &file_onsyntax,
+ NULL);
+ upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, message_type),
+ &file_startmsg, NULL);
+ upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, enum_type),
+ &file_startenum, NULL);
+ upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, extension),
+ &file_startext, NULL);
+ } else if (upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)) {
upb_handlers_setstartmsg(h, &enumval_startmsg, NULL);
upb_handlers_setendmsg(h, &enumval_endmsg, NULL);
- upb_handlers_setstring(h, D(EnumValueDescriptorProto_name), &enumval_onname, NULL);
- upb_handlers_setint32(h, D(EnumValueDescriptorProto_number), &enumval_onnumber,
+ upb_handlers_setstring(h, F(EnumValueDescriptorProto, name), &enumval_onname, NULL);
+ upb_handlers_setint32(h, F(EnumValueDescriptorProto, number), &enumval_onnumber,
NULL);
- } else if (m == D(EnumDescriptorProto)) {
- upb_handlers_setstartmsg(h, &enum_startmsg, NULL);
+ } else if (upbdefs_google_protobuf_EnumDescriptorProto_is(m)) {
upb_handlers_setendmsg(h, &enum_endmsg, NULL);
- upb_handlers_setstring(h, D(EnumDescriptorProto_name), &enum_onname, NULL);
- } else if (m == D(FieldDescriptorProto)) {
+ upb_handlers_setstring(h, F(EnumDescriptorProto, name), &enum_onname, NULL);
+ } else if (upbdefs_google_protobuf_FieldDescriptorProto_is(m)) {
upb_handlers_setstartmsg(h, &field_startmsg, NULL);
upb_handlers_setendmsg(h, &field_endmsg, NULL);
- upb_handlers_setint32(h, D(FieldDescriptorProto_type), &field_ontype,
+ upb_handlers_setint32(h, F(FieldDescriptorProto, type), &field_ontype,
NULL);
- upb_handlers_setint32(h, D(FieldDescriptorProto_label), &field_onlabel,
+ upb_handlers_setint32(h, F(FieldDescriptorProto, label), &field_onlabel,
NULL);
- upb_handlers_setint32(h, D(FieldDescriptorProto_number), &field_onnumber,
+ upb_handlers_setint32(h, F(FieldDescriptorProto, number), &field_onnumber,
NULL);
- upb_handlers_setstring(h, D(FieldDescriptorProto_name), &field_onname,
+ upb_handlers_setstring(h, F(FieldDescriptorProto, name), &field_onname,
NULL);
- upb_handlers_setstring(h, D(FieldDescriptorProto_type_name),
+ upb_handlers_setstring(h, F(FieldDescriptorProto, type_name),
&field_ontypename, NULL);
- upb_handlers_setstring(h, D(FieldDescriptorProto_extendee),
+ upb_handlers_setstring(h, F(FieldDescriptorProto, extendee),
&field_onextendee, NULL);
- upb_handlers_setstring(h, D(FieldDescriptorProto_default_value),
+ upb_handlers_setstring(h, F(FieldDescriptorProto, default_value),
&field_ondefaultval, NULL);
- } else if (m == D(FieldOptions)) {
- upb_handlers_setbool(h, D(FieldOptions_lazy), &field_onlazy, NULL);
- upb_handlers_setbool(h, D(FieldOptions_packed), &field_onpacked, NULL);
+ upb_handlers_setint32(h, F(FieldDescriptorProto, oneof_index),
+ &field_ononeofindex, NULL);
+ } else if (upbdefs_google_protobuf_OneofDescriptorProto_is(m)) {
+ upb_handlers_setstring(h, F(OneofDescriptorProto, name), &oneof_name, NULL);
+ } else if (upbdefs_google_protobuf_FieldOptions_is(m)) {
+ upb_handlers_setbool(h, F(FieldOptions, lazy), &field_onlazy, NULL);
+ upb_handlers_setbool(h, F(FieldOptions, packed), &field_onpacked, NULL);
+ } else if (upbdefs_google_protobuf_MessageOptions_is(m)) {
+ upb_handlers_setbool(h, F(MessageOptions, map_entry), &msg_onmapentry, NULL);
}
+
+ UPB_ASSERT(upb_ok(upb_handlers_status(h)));
}
-#undef D
+#undef F
void descreader_cleanup(void *_r) {
upb_descreader *r = _r;
- free(r->name);
- upb_deflist_uninit(&r->defs);
- free(r->default_string);
+ size_t i;
+
+ for (i = 0; i < upb_descreader_filecount(r); i++) {
+ upb_filedef_unref(upb_descreader_file(r, i), &r->files);
+ }
+
+ upb_gfree(r->name);
+ upb_inttable_uninit(&r->files);
+ upb_inttable_uninit(&r->oneofs);
+ upb_gfree(r->default_string);
while (r->stack_len > 0) {
upb_descreader_frame *f = &r->stack[--r->stack_len];
- free(f->name);
+ upb_gfree(f->name);
}
}
@@ -6445,7 +7215,8 @@ upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h) {
return NULL;
}
- upb_deflist_init(&r->defs);
+ upb_inttable_init(&r->files, UPB_CTYPE_PTR);
+ upb_inttable_init(&r->oneofs, UPB_CTYPE_PTR);
upb_sink_reset(upb_descreader_input(r), h, r);
r->stack_len = 0;
r->name = NULL;
@@ -6454,10 +7225,17 @@ upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h) {
return r;
}
-upb_def **upb_descreader_getdefs(upb_descreader *r, void *owner, int *n) {
- *n = r->defs.len;
- upb_deflist_donaterefs(&r->defs, owner);
- return r->defs.defs;
+size_t upb_descreader_filecount(const upb_descreader *r) {
+ return upb_inttable_count(&r->files);
+}
+
+upb_filedef *upb_descreader_file(const upb_descreader *r, size_t i) {
+ upb_value v;
+ if (upb_inttable_lookup(&r->files, i, &v)) {
+ return upb_value_getptr(v);
+ } else {
+ return NULL;
+ }
}
upb_sink *upb_descreader_input(upb_descreader *r) {
@@ -6465,10 +7243,9 @@ upb_sink *upb_descreader_input(upb_descreader *r) {
}
const upb_handlers *upb_descreader_newhandlers(const void *owner) {
- const upb_symtab *s = upbdefs_google_protobuf_descriptor(&s);
- const upb_handlers *h = upb_handlers_newfrozen(
- upbdefs_google_protobuf_FileDescriptorSet(s), owner, reghandlers, s);
- upb_symtab_unref(s, &s);
+ const upb_msgdef *m = upbdefs_google_protobuf_FileDescriptorSet_get(&m);
+ const upb_handlers *h = upb_handlers_newfrozen(m, owner, reghandlers, NULL);
+ upb_msgdef_unref(m, &m);
return h;
}
/*
@@ -6502,8 +7279,8 @@ static void freegroup(upb_refcounted *r) {
#ifdef UPB_USE_JIT_X64
upb_pbdecoder_freejit(g);
#endif
- free(g->bytecode);
- free(g);
+ upb_gfree(g->bytecode);
+ upb_gfree(g);
}
static void visitgroup(const upb_refcounted *r, upb_refcounted_visit *visit,
@@ -6518,7 +7295,7 @@ static void visitgroup(const upb_refcounted *r, upb_refcounted_visit *visit,
}
mgroup *newgroup(const void *owner) {
- mgroup *g = malloc(sizeof(*g));
+ mgroup *g = upb_gmalloc(sizeof(*g));
static const struct upb_refcounted_vtbl vtbl = {visitgroup, freegroup};
upb_refcounted_init(mgroup_upcast_mutable(g), &vtbl, owner);
upb_inttable_init(&g->methods, UPB_CTYPE_PTR);
@@ -6538,7 +7315,7 @@ static void freemethod(upb_refcounted *r) {
}
upb_inttable_uninit(&method->dispatch);
- free(method);
+ upb_gfree(method);
}
static void visitmethod(const upb_refcounted *r, upb_refcounted_visit *visit,
@@ -6550,7 +7327,7 @@ static void visitmethod(const upb_refcounted *r, upb_refcounted_visit *visit,
static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers,
mgroup *group) {
static const struct upb_refcounted_vtbl vtbl = {visitmethod, freemethod};
- upb_pbdecodermethod *ret = malloc(sizeof(*ret));
+ upb_pbdecodermethod *ret = upb_gmalloc(sizeof(*ret));
upb_refcounted_init(upb_pbdecodermethod_upcast_mutable(ret), &vtbl, &ret);
upb_byteshandler_init(&ret->input_handler_);
@@ -6613,7 +7390,7 @@ typedef struct {
} compiler;
static compiler *newcompiler(mgroup *group, bool lazy) {
- compiler *ret = malloc(sizeof(*ret));
+ compiler *ret = upb_gmalloc(sizeof(*ret));
int i;
ret->group = group;
@@ -6626,7 +7403,7 @@ static compiler *newcompiler(mgroup *group, bool lazy) {
}
static void freecompiler(compiler *c) {
- free(c);
+ upb_gfree(c);
}
const size_t ptr_words = sizeof(void*) / sizeof(uint32_t);
@@ -6654,7 +7431,7 @@ bool op_has_longofs(int32_t instruction) {
case OP_TAGN:
return false;
default:
- assert(false);
+ UPB_ASSERT(false);
return false;
}
}
@@ -6673,7 +7450,7 @@ static void setofs(uint32_t *instruction, int32_t ofs) {
} else {
*instruction = (*instruction & ~0xff00) | ((ofs & 0xff) << 8);
}
- assert(getofs(*instruction) == ofs); /* Would fail in cases of overflow. */
+ UPB_ASSERT(getofs(*instruction) == ofs); /* Would fail in cases of overflow. */
}
static uint32_t pcofs(compiler *c) { return c->pc - c->group->bytecode; }
@@ -6685,7 +7462,7 @@ static void label(compiler *c, unsigned int label) {
int val;
uint32_t *codep;
- assert(label < MAXLABEL);
+ UPB_ASSERT(label < MAXLABEL);
val = c->fwd_labels[label];
codep = (val == EMPTYLABEL) ? NULL : c->group->bytecode + val;
while (codep) {
@@ -6706,7 +7483,7 @@ static void label(compiler *c, unsigned int label) {
* The returned value is the offset that should be written into the instruction.
*/
static int32_t labelref(compiler *c, int label) {
- assert(label < MAXLABEL);
+ UPB_ASSERT(label < MAXLABEL);
if (label == LABEL_DISPATCH) {
/* No resolving required. */
return 0;
@@ -6730,7 +7507,8 @@ static void put32(compiler *c, uint32_t v) {
size_t oldsize = g->bytecode_end - g->bytecode;
size_t newsize = UPB_MAX(oldsize * 2, 64);
/* TODO(haberman): handle OOM. */
- g->bytecode = realloc(g->bytecode, newsize * sizeof(uint32_t));
+ g->bytecode = upb_grealloc(g->bytecode, oldsize * sizeof(uint32_t),
+ newsize * sizeof(uint32_t));
g->bytecode_end = g->bytecode + newsize;
c->pc = g->bytecode + ofs;
}
@@ -6805,7 +7583,7 @@ static void putop(compiler *c, opcode op, ...) {
int label = va_arg(ap, int);
uint64_t tag = va_arg(ap, uint64_t);
uint32_t instruction = op | (tag << 16);
- assert(tag <= 0xffff);
+ UPB_ASSERT(tag <= 0xffff);
setofs(&instruction, labelref(c, label));
put32(c, instruction);
break;
@@ -6942,7 +7720,7 @@ static uint64_t get_encoded_tag(const upb_fielddef *f, int wire_type) {
uint32_t tag = (upb_fielddef_number(f) << 3) | wire_type;
uint64_t encoded_tag = upb_vencode32(tag);
/* No tag should be greater than 5 bytes. */
- assert(encoded_tag <= 0xffffffffff);
+ UPB_ASSERT(encoded_tag <= 0xffffffffff);
return encoded_tag;
}
@@ -6965,7 +7743,7 @@ static void putchecktag(compiler *c, const upb_fielddef *f,
static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
upb_selector_t selector;
bool ok = upb_handlers_getselector(f, type, &selector);
- UPB_ASSERT_VAR(ok, ok);
+ UPB_ASSERT(ok);
return selector;
}
@@ -6977,7 +7755,7 @@ static uint64_t repack(uint64_t dispatch, int new_wt2) {
uint8_t wt1;
uint8_t old_wt2;
upb_pbdecoder_unpackdispatch(dispatch, &ofs, &wt1, &old_wt2);
- assert(old_wt2 == NO_WIRE_TYPE); /* wt2 should not be set yet. */
+ UPB_ASSERT(old_wt2 == NO_WIRE_TYPE); /* wt2 should not be set yet. */
return upb_pbdecoder_packdispatch(ofs, wt1, new_wt2);
}
@@ -7067,7 +7845,12 @@ static void generate_msgfield(compiler *c, const upb_fielddef *f,
if (!sub_m) {
/* Don't emit any code for this field at all; it will be parsed as an
- * unknown field. */
+ * unknown field.
+ *
+ * TODO(haberman): we should change this to parse it as a string field
+ * instead. It will probably be faster, but more importantly, once we
+ * start vending unknown fields, a field shouldn't be treated as unknown
+ * just because it doesn't have subhandlers registered. */
return;
}
@@ -7174,7 +7957,7 @@ static void generate_primitivefield(compiler *c, const upb_fielddef *f,
* setting in the fielddef. This will favor (in speed) whichever was
* specified. */
- assert((int)parse_type >= 0 && parse_type <= OP_MAX);
+ UPB_ASSERT((int)parse_type >= 0 && parse_type <= OP_MAX);
sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
wire_type = upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
if (upb_fielddef_isseq(f)) {
@@ -7216,7 +7999,7 @@ static void compile_method(compiler *c, upb_pbdecodermethod *method) {
upb_msg_field_iter i;
upb_value val;
- assert(method);
+ UPB_ASSERT(method);
/* Clear all entries in the dispatch table. */
upb_inttable_uninit(&method->dispatch);
@@ -7364,7 +8147,7 @@ const mgroup *mgroup_new(const upb_handlers *dest, bool allowjit, bool lazy,
compiler *c;
UPB_UNUSED(allowjit);
- assert(upb_handlers_isfrozen(dest));
+ UPB_ASSERT(upb_handlers_isfrozen(dest));
g = newgroup(owner);
c = newcompiler(g, lazy);
@@ -7384,11 +8167,16 @@ const mgroup *mgroup_new(const upb_handlers *dest, bool allowjit, bool lazy,
#ifdef UPB_DUMP_BYTECODE
{
- FILE *f = fopen("/tmp/upb-bytecode", "wb");
- assert(f);
+ FILE *f = fopen("/tmp/upb-bytecode", "w");
+ UPB_ASSERT(f);
dumpbc(g->bytecode, g->bytecode_end, stderr);
dumpbc(g->bytecode, g->bytecode_end, f);
fclose(f);
+
+ f = fopen("/tmp/upb-bytecode.bin", "wb");
+ UPB_ASSERT(f);
+ fwrite(g->bytecode, 1, g->bytecode_end - g->bytecode, f);
+ fclose(f);
}
#endif
@@ -7436,7 +8224,7 @@ const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod(
upb_inttable_push(&c->groups, upb_value_constptr(g));
ok = upb_inttable_lookupptr(&g->methods, opts->handlers, &v);
- UPB_ASSERT_VAR(ok, ok);
+ UPB_ASSERT(ok);
return upb_value_getptr(v);
}
@@ -7488,6 +8276,11 @@ static const char *kUnterminatedVarint = "Unterminated varint.";
static opcode halt = OP_HALT;
+/* A dummy character we can point to when the user passes us a NULL buffer.
+ * We need this because in C (NULL + 0) and (NULL - NULL) are undefined
+ * behavior, which would invalidate functions like curbufleft(). */
+static const char dummy_char;
+
/* Whether an op consumes any of the input buffer. */
static bool consumes_input(opcode op) {
switch (op) {
@@ -7564,7 +8357,7 @@ void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) {
/* How many bytes can be safely read from d->ptr without reading past end-of-buf
* or past the current delimited end. */
static size_t curbufleft(const upb_pbdecoder *d) {
- assert(d->data_end >= d->ptr);
+ UPB_ASSERT(d->data_end >= d->ptr);
return d->data_end - d->ptr;
}
@@ -7585,7 +8378,7 @@ size_t delim_remaining(const upb_pbdecoder *d) {
/* Advances d->ptr. */
static void advance(upb_pbdecoder *d, size_t len) {
- assert(curbufleft(d) >= len);
+ UPB_ASSERT(curbufleft(d) >= len);
d->ptr += len;
}
@@ -7618,7 +8411,7 @@ static void switchtobuf(upb_pbdecoder *d, const char *buf, const char *end) {
}
static void advancetobuf(upb_pbdecoder *d, const char *buf, size_t len) {
- assert(curbufleft(d) == 0);
+ UPB_ASSERT(curbufleft(d) == 0);
d->bufstart_ofs += (d->end - d->buf);
switchtobuf(d, buf, buf + len);
}
@@ -7627,7 +8420,7 @@ static void checkpoint(upb_pbdecoder *d) {
/* The assertion here is in the interests of efficiency, not correctness.
* We are trying to ensure that we don't checkpoint() more often than
* necessary. */
- assert(d->checkpoint != d->ptr);
+ UPB_ASSERT(d->checkpoint != d->ptr);
d->checkpoint = d->ptr;
}
@@ -7638,12 +8431,12 @@ static void checkpoint(upb_pbdecoder *d) {
* won't actually be read.
*/
static int32_t skip(upb_pbdecoder *d, size_t bytes) {
- assert(!in_residual_buf(d, d->ptr) || d->size_param == 0);
- assert(d->skip == 0);
+ UPB_ASSERT(!in_residual_buf(d, d->ptr) || d->size_param == 0);
+ UPB_ASSERT(d->skip == 0);
if (bytes > delim_remaining(d)) {
seterr(d, "Skipped value extended beyond enclosing submessage.");
return upb_pbdecoder_suspend(d);
- } else if (bufleft(d) > bytes) {
+ } else if (bufleft(d) >= bytes) {
/* Skipped data is all in current buffer, and more is still available. */
advance(d, bytes);
d->skip = 0;
@@ -7665,36 +8458,60 @@ int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
size_t size, const upb_bufhandle *handle) {
UPB_UNUSED(p); /* Useless; just for the benefit of the JIT. */
- d->buf_param = buf;
+ /* d->skip and d->residual_end could probably elegantly be represented
+ * as a single variable, to more easily represent this invariant. */
+ UPB_ASSERT(!(d->skip && d->residual_end > d->residual));
+
+ /* We need to remember the original size_param, so that the value we return
+ * is relative to it, even if we do some skipping first. */
d->size_param = size;
d->handle = handle;
+ /* Have to handle this case specially (ie. not with skip()) because the user
+ * is allowed to pass a NULL buffer here, which won't allow us to safely
+ * calculate a d->end or use our normal functions like curbufleft(). */
+ if (d->skip && d->skip >= size) {
+ d->skip -= size;
+ d->bufstart_ofs += size;
+ buf = &dummy_char;
+ size = 0;
+
+ /* We can't just return now, because we might need to execute some ops
+ * like CHECKDELIM, which could call some callbacks and pop the stack. */
+ }
+
+ /* We need to pretend that this was the actual buffer param, since some of the
+ * calculations assume that d->ptr/d->buf is relative to this. */
+ d->buf_param = buf;
+
+ if (!buf) {
+ /* NULL buf is ok if its entire span is covered by the "skip" above, but
+ * by this point we know that "skip" doesn't cover the buffer. */
+ seterr(d, "Passed NULL buffer over non-skippable region.");
+ return upb_pbdecoder_suspend(d);
+ }
+
if (d->residual_end > d->residual) {
/* We have residual bytes from the last buffer. */
- assert(d->ptr == d->residual);
+ UPB_ASSERT(d->ptr == d->residual);
} else {
switchtobuf(d, buf, buf + size);
}
d->checkpoint = d->ptr;
+ /* Handle skips that don't cover the whole buffer (as above). */
if (d->skip) {
size_t skip_bytes = d->skip;
d->skip = 0;
CHECK_RETURN(skip(d, skip_bytes));
- d->checkpoint = d->ptr;
- }
-
- if (!buf) {
- /* NULL buf is ok if its entire span is covered by the "skip" above, but
- * by this point we know that "skip" doesn't cover the buffer. */
- seterr(d, "Passed NULL buffer over non-skippable region.");
- return upb_pbdecoder_suspend(d);
+ checkpoint(d);
}
+ /* If we're inside an unknown group, continue to parse unknown values. */
if (d->top->groupnum < 0) {
CHECK_RETURN(upb_pbdecoder_skipunknown(d, -1, 0));
- d->checkpoint = d->ptr;
+ checkpoint(d);
}
return DECODE_OK;
@@ -7709,15 +8526,14 @@ size_t upb_pbdecoder_suspend(upb_pbdecoder *d) {
d->ptr = d->residual;
return 0;
} else {
- size_t consumed;
- assert(!in_residual_buf(d, d->checkpoint));
- assert(d->buf == d->buf_param);
+ size_t ret = d->size_param - (d->end - d->checkpoint);
+ UPB_ASSERT(!in_residual_buf(d, d->checkpoint));
+ UPB_ASSERT(d->buf == d->buf_param || d->buf == &dummy_char);
- consumed = d->checkpoint - d->buf;
- d->bufstart_ofs += consumed;
+ d->bufstart_ofs += (d->checkpoint - d->buf);
d->residual_end = d->residual;
switchtobuf(d, d->residual, d->residual_end);
- return consumed;
+ return ret;
}
}
@@ -7732,7 +8548,7 @@ static size_t suspend_save(upb_pbdecoder *d) {
if (d->checkpoint == d->residual) {
/* Checkpoint was in residual buf; append user byte(s) to residual buf. */
- assert((d->residual_end - d->residual) + d->size_param <=
+ UPB_ASSERT((d->residual_end - d->residual) + d->size_param <=
sizeof(d->residual));
if (!in_residual_buf(d, d->ptr)) {
d->bufstart_ofs -= (d->residual_end - d->residual);
@@ -7742,11 +8558,11 @@ static size_t suspend_save(upb_pbdecoder *d) {
} else {
/* Checkpoint was in user buf; old residual bytes not needed. */
size_t save;
- assert(!in_residual_buf(d, d->checkpoint));
+ UPB_ASSERT(!in_residual_buf(d, d->checkpoint));
d->ptr = d->checkpoint;
save = curbufleft(d);
- assert(save <= sizeof(d->residual));
+ UPB_ASSERT(save <= sizeof(d->residual));
memcpy(d->residual, d->ptr, save);
d->residual_end = d->residual + save;
d->bufstart_ofs = offset(d);
@@ -7760,7 +8576,7 @@ static size_t suspend_save(upb_pbdecoder *d) {
* Requires that this many bytes are available in the current buffer. */
UPB_FORCEINLINE static void consumebytes(upb_pbdecoder *d, void *buf,
size_t bytes) {
- assert(bytes <= curbufleft(d));
+ UPB_ASSERT(bytes <= curbufleft(d));
memcpy(buf, d->ptr, bytes);
advance(d, bytes);
}
@@ -7773,7 +8589,7 @@ UPB_NOINLINE static int32_t getbytes_slow(upb_pbdecoder *d, void *buf,
const size_t avail = curbufleft(d);
consumebytes(d, buf, avail);
bytes -= avail;
- assert(bytes > 0);
+ UPB_ASSERT(bytes > 0);
if (in_residual_buf(d, d->ptr)) {
advancetobuf(d, d->buf_param, d->size_param);
}
@@ -7835,8 +8651,7 @@ UPB_NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d,
int bitpos;
*u64 = 0;
for(bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) {
- int32_t ret = getbytes(d, &byte, 1);
- if (ret >= 0) return ret;
+ CHECK_RETURN(getbytes(d, &byte, 1));
*u64 |= (uint64_t)(byte & 0x7F) << bitpos;
}
if(bitpos == 70 && (byte & 0x80)) {
@@ -7957,7 +8772,7 @@ UPB_NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d,
if (read == bytes && data == expected) {
/* Advance past matched bytes. */
int32_t ok = getbytes(d, &data, read);
- UPB_ASSERT_VAR(ok, ok < 0);
+ UPB_ASSERT(ok < 0);
return DECODE_OK;
} else if (read < bytes && memcmp(&data, &expected, read) == 0) {
return suspend_save(d);
@@ -8032,7 +8847,7 @@ have_tag:
static void goto_endmsg(upb_pbdecoder *d) {
upb_value v;
bool found = upb_inttable_lookup32(d->top->dispatch, DISPATCH_ENDMSG, &v);
- UPB_ASSERT_VAR(found, found);
+ UPB_ASSERT(found);
d->pc = d->top->base + upb_value_getuint64(v);
}
@@ -8066,7 +8881,7 @@ static int32_t dispatch(upb_pbdecoder *d) {
} else if (wire_type == ((v >> 8) & 0xff)) {
bool found =
upb_inttable_lookup(dispatch, fieldnum + UPB_MAX_FIELDNUMBER, &val);
- UPB_ASSERT_VAR(found, found);
+ UPB_ASSERT(found);
d->pc = d->top->base + upb_value_getuint64(val);
return DECODE_OK;
}
@@ -8078,7 +8893,7 @@ static int32_t dispatch(upb_pbdecoder *d) {
* can re-check the delimited end. */
d->last--; /* Necessary if we get suspended */
d->pc = d->last;
- assert(getop(*d->last) == OP_CHECKDELIM);
+ UPB_ASSERT(getop(*d->last) == OP_CHECKDELIM);
/* Unknown field or ENDGROUP. */
retval = upb_pbdecoder_skipunknown(d, fieldnum, wire_type);
@@ -8096,7 +8911,7 @@ static int32_t dispatch(upb_pbdecoder *d) {
/* Callers know that the stack is more than one deep because the opcodes that
* call this only occur after PUSH operations. */
upb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) {
- assert(d->top != d->stack);
+ UPB_ASSERT(d->top != d->stack);
return d->top - 1;
}
@@ -8128,7 +8943,7 @@ size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group,
op = getop(instruction);
arg = instruction >> 8;
longofs = arg;
- assert(d->ptr != d->residual_end);
+ UPB_ASSERT(d->ptr != d->residual_end);
UPB_UNUSED(group);
#ifdef UPB_DUMP_BYTECODE
fprintf(stderr, "s_ofs=%d buf_ofs=%d data_rem=%d buf_rem=%d delim_rem=%d "
@@ -8203,7 +9018,7 @@ size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group,
} else {
int32_t ret = skip(d, n);
/* This shouldn't return DECODE_OK, because n > len. */
- assert(ret >= 0);
+ UPB_ASSERT(ret >= 0);
return ret;
}
}
@@ -8225,7 +9040,7 @@ size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group,
d->top->groupnum = *d->pc++;
)
VMCASE(OP_POP,
- assert(d->top > d->stack);
+ UPB_ASSERT(d->top > d->stack);
decoder_pop(d);
)
VMCASE(OP_PUSHLENDELIM,
@@ -8241,7 +9056,7 @@ size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group,
/* We are guaranteed of this assert because we never allow ourselves to
* consume bytes beyond data_end, which covers delim_end when non-NULL.
*/
- assert(!(d->delim_end && d->ptr > d->delim_end));
+ UPB_ASSERT(!(d->delim_end && d->ptr > d->delim_end));
if (d->ptr == d->delim_end)
d->pc += longofs;
)
@@ -8250,7 +9065,7 @@ size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group,
d->pc += longofs;
)
VMCASE(OP_RET,
- assert(d->call_len > 0);
+ UPB_ASSERT(d->call_len > 0);
d->pc = d->callstack[--d->call_len];
)
VMCASE(OP_BRANCH,
@@ -8377,7 +9192,7 @@ bool upb_pbdecoder_end(void *closure, const void *handler_data) {
if (p != method->code_base.ptr) p--;
if (getop(*p) == OP_CHECKDELIM) {
/* Rewind from OP_TAG* to OP_CHECKDELIM. */
- assert(getop(*d->pc) == OP_TAG1 ||
+ UPB_ASSERT(getop(*d->pc) == OP_TAG1 ||
getop(*d->pc) == OP_TAG2 ||
getop(*d->pc) == OP_TAGN ||
getop(*d->pc) == OP_DISPATCH);
@@ -8436,11 +9251,12 @@ upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m,
d->env = e;
d->limit = d->stack + default_max_nesting - 1;
d->stack_size = default_max_nesting;
+ d->status = NULL;
upb_pbdecoder_reset(d);
upb_bytessink_reset(&d->input_, &m->input_handler_, d);
- assert(sink);
+ UPB_ASSERT(sink);
if (d->method_->dest_handlers_) {
if (sink->handlers != d->method_->dest_handlers_)
return NULL;
@@ -8448,7 +9264,8 @@ upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m,
upb_sink_reset(&d->top->sink, sink->handlers, sink->closure);
/* If this fails, increase the value in decoder.h. */
- assert(upb_env_bytesallocated(e) - size_before <= UPB_PB_DECODER_SIZE);
+ UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(e) - size_before <=
+ UPB_PB_DECODER_SIZE);
return d;
}
@@ -8469,7 +9286,7 @@ size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d) {
}
bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) {
- assert(d->top >= d->stack);
+ UPB_ASSERT(d->top >= d->stack);
if (max < (size_t)(d->top - d->stack)) {
/* Can't set a limit smaller than what we are currently at. */
@@ -8557,7 +9374,6 @@ bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) {
*/
-#include <stdlib.h>
/* The output buffer is divided into segments; a segment is a string of data
* that is "ready to go" -- it does not need any varint lengths inserted into
@@ -8629,7 +9445,7 @@ struct upb_pb_encoder {
/* TODO(haberman): handle pushback */
static void putbuf(upb_pb_encoder *e, const char *buf, size_t len) {
size_t n = upb_bytessink_putbuf(e->output_, e->subc, buf, len, NULL);
- UPB_ASSERT_VAR(n, n == len);
+ UPB_ASSERT(n == len);
}
static upb_pb_encoder_segment *top(upb_pb_encoder *e) {
@@ -8669,7 +9485,7 @@ static bool reserve(upb_pb_encoder *e, size_t bytes) {
/* Call when "bytes" bytes have been writte at e->ptr. The caller *must* have
* previously called reserve() with at least this many bytes. */
static void encoder_advance(upb_pb_encoder *e, size_t bytes) {
- assert((size_t)(e->limit - e->ptr) >= bytes);
+ UPB_ASSERT((size_t)(e->limit - e->ptr) >= bytes);
e->ptr += bytes;
}
@@ -8704,7 +9520,7 @@ static bool encode_bytes(upb_pb_encoder *e, const void *data, size_t len) {
* length. */
static void accumulate(upb_pb_encoder *e) {
size_t run_len;
- assert(e->ptr >= e->runbegin);
+ UPB_ASSERT(e->ptr >= e->runbegin);
run_len = e->ptr - e->runbegin;
e->segptr->seglen += run_len;
top(e)->msglen += run_len;
@@ -8802,12 +9618,12 @@ static void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt,
upb_handlerattr *attr) {
uint32_t n = upb_fielddef_number(f);
- tag_t *tag = malloc(sizeof(tag_t));
+ tag_t *tag = upb_gmalloc(sizeof(tag_t));
tag->bytes = upb_vencode64((n << 3) | wt, tag->tag);
upb_handlerattr_init(attr);
upb_handlerattr_sethandlerdata(attr, tag);
- upb_handlers_addcleanup(h, tag, free);
+ upb_handlers_addcleanup(h, tag, upb_gfree);
}
static bool encode_tag(upb_pb_encoder *e, const tag_t *tag) {
@@ -9059,19 +9875,17 @@ upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h,
e->ptr = e->buf;
/* If this fails, increase the value in encoder.h. */
- assert(upb_env_bytesallocated(env) - size_before <= UPB_PB_ENCODER_SIZE);
+ UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <=
+ UPB_PB_ENCODER_SIZE);
return e;
}
upb_sink *upb_pb_encoder_input(upb_pb_encoder *e) { return &e->input_; }
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n,
- void *owner, upb_status *status) {
+upb_filedef **upb_loaddescriptor(const char *buf, size_t n, const void *owner,
+ upb_status *status) {
/* Create handlers. */
const upb_pbdecodermethod *decoder_m;
const upb_handlers *reader_h = upb_descreader_newhandlers(&reader_h);
@@ -9080,8 +9894,8 @@ upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n,
upb_pbdecoder *decoder;
upb_descreader *reader;
bool ok;
- upb_def **ret = NULL;
- upb_def **defs;
+ size_t i;
+ upb_filedef **ret = NULL;
upb_pbdecodermethodopts_init(&opts, reader_h);
decoder_m = upb_pbdecodermethod_new(&opts, &decoder_m);
@@ -9093,12 +9907,24 @@ upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n,
decoder = upb_pbdecoder_create(&env, decoder_m, upb_descreader_input(reader));
/* Push input data. */
- ok = upb_bufsrc_putbuf(str, len, upb_pbdecoder_input(decoder));
+ ok = upb_bufsrc_putbuf(buf, n, upb_pbdecoder_input(decoder));
+
+ if (!ok) {
+ goto cleanup;
+ }
+
+ ret = upb_gmalloc(sizeof (*ret) * (upb_descreader_filecount(reader) + 1));
+
+ if (!ret) {
+ goto cleanup;
+ }
- if (!ok) goto cleanup;
- defs = upb_descreader_getdefs(reader, owner, n);
- ret = malloc(sizeof(upb_def*) * (*n));
- memcpy(ret, defs, sizeof(upb_def*) * (*n));
+ for (i = 0; i < upb_descreader_filecount(reader); i++) {
+ ret[i] = upb_descreader_file(reader, i);
+ upb_filedef_ref(ret[i], owner);
+ }
+
+ ret[i] = NULL;
cleanup:
upb_env_uninit(&env);
@@ -9106,51 +9932,6 @@ cleanup:
upb_pbdecodermethod_unref(decoder_m, &decoder_m);
return ret;
}
-
-bool upb_load_descriptor_into_symtab(upb_symtab *s, const char *str, size_t len,
- upb_status *status) {
- int n;
- bool success;
- upb_def **defs = upb_load_defs_from_descriptor(str, len, &n, &defs, status);
- if (!defs) return false;
- success = upb_symtab_add(s, defs, n, &defs, status);
- free(defs);
- return success;
-}
-
-char *upb_readfile(const char *filename, size_t *len) {
- long size;
- char *buf;
- FILE *f = fopen(filename, "rb");
- if(!f) return NULL;
- if(fseek(f, 0, SEEK_END) != 0) goto error;
- size = ftell(f);
- if(size < 0) goto error;
- if(fseek(f, 0, SEEK_SET) != 0) goto error;
- buf = malloc(size + 1);
- if(size && fread(buf, size, 1, f) != 1) goto error;
- fclose(f);
- if (len) *len = size;
- return buf;
-
-error:
- fclose(f);
- return NULL;
-}
-
-bool upb_load_descriptor_file_into_symtab(upb_symtab *symtab, const char *fname,
- upb_status *status) {
- size_t len;
- bool success;
- char *data = upb_readfile(fname, &len);
- if (!data) {
- if (status) upb_status_seterrf(status, "Couldn't read file: %s", fname);
- return false;
- }
- success = upb_load_descriptor_into_symtab(symtab, data, len, status);
- free(data);
- return success;
-}
/*
* upb::pb::TextPrinter
*
@@ -9164,7 +9945,6 @@ bool upb_load_descriptor_file_into_symtab(upb_symtab *symtab, const char *fname,
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
@@ -9260,14 +10040,14 @@ bool putf(upb_textprinter *p, const char *fmt, ...) {
va_end(args_copy);
/* + 1 for NULL terminator (vsprintf() requires it even if we don't). */
- str = malloc(len + 1);
+ str = upb_gmalloc(len + 1);
if (!str) return false;
written = vsprintf(str, fmt, args);
va_end(args);
- UPB_ASSERT_VAR(written, written == len);
+ UPB_ASSERT(written == len);
ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL);
- free(str);
+ upb_gfree(str);
return ok;
}
@@ -9636,12 +10416,11 @@ upb_decoderet upb_vdecode_max8_wright(upb_decoderet r) {
** - handling of keys/escape-sequences/etc that span input buffers.
*/
-#include <stdio.h>
-#include <stdint.h>
#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
#define UPB_JSON_MAX_DEPTH 64
@@ -9654,6 +10433,9 @@ typedef struct {
const upb_msgdef *m;
const upb_fielddef *f;
+ /* The table mapping json name to fielddef for this message. */
+ upb_strtable *name_table;
+
/* We are in a repeated-field context, ready to emit mapentries as
* submessages. This flag alters the start-of-object (open-brace) behavior to
* begin a sequence of mapentry messages rather than a single submessage. */
@@ -9674,7 +10456,7 @@ typedef struct {
struct upb_json_parser {
upb_env *env;
- upb_byteshandler input_handler_;
+ const upb_json_parsermethod *method;
upb_bytessink input_;
/* Stack to track the JSON scopes we are in. */
@@ -9709,6 +10491,19 @@ struct upb_json_parser {
uint32_t digit;
};
+struct upb_json_parsermethod {
+ upb_refcounted base;
+
+ upb_byteshandler input_handler_;
+
+ /* Mainly for the purposes of refcounting, so all the fielddefs we point
+ * to stay alive. */
+ const upb_msgdef *msg;
+
+ /* Keys are upb_msgdef*, values are upb_strtable (json_name -> fielddef) */
+ upb_inttable name_tables;
+};
+
#define PARSER_CHECK_RETURN(x) if (!(x)) return false
/* Used to signal that a capture has been suspended. */
@@ -9718,7 +10513,7 @@ static upb_selector_t getsel_for_handlertype(upb_json_parser *p,
upb_handlertype_t type) {
upb_selector_t sel;
bool ok = upb_handlers_getselector(p->top->f, type, &sel);
- UPB_ASSERT_VAR(ok, ok);
+ UPB_ASSERT(ok);
return sel;
}
@@ -9737,6 +10532,13 @@ static bool check_stack(upb_json_parser *p) {
return true;
}
+static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) {
+ upb_value v;
+ bool ok = upb_inttable_lookupptr(&p->method->name_tables, frame->m, &v);
+ UPB_ASSERT(ok);
+ frame->name_table = upb_value_getptr(v);
+}
+
/* There are GCC/Clang built-ins for overflow checking which we could start
* using if there was any performance benefit to it. */
@@ -9856,7 +10658,7 @@ otherchar:
val = b64lookup(ptr[0]) << 18 |
b64lookup(ptr[1]) << 12;
- assert(!(val & 0x80000000));
+ UPB_ASSERT(!(val & 0x80000000));
output = val >> 16;
upb_sink_putstring(&p->top->sink, sel, &output, 1, NULL);
return true;
@@ -9910,9 +10712,8 @@ badpadding:
* the true value in a contiguous buffer. */
static void assert_accumulate_empty(upb_json_parser *p) {
- UPB_UNUSED(p);
- assert(p->accumulated == NULL);
- assert(p->accumulated_len == 0);
+ UPB_ASSERT(p->accumulated == NULL);
+ UPB_ASSERT(p->accumulated_len == 0);
}
static void accumulate_clear(upb_json_parser *p) {
@@ -9978,7 +10779,7 @@ static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
* call, and writes the length to *len. This with point either to the input
* buffer or a temporary accumulate buffer. */
static const char *accumulate_getptr(upb_json_parser *p, size_t *len) {
- assert(p->accumulated);
+ UPB_ASSERT(p->accumulated);
*len = p->accumulated_len;
return p->accumulated;
}
@@ -10016,7 +10817,7 @@ enum {
* the end. */
static void multipart_startaccum(upb_json_parser *p) {
assert_accumulate_empty(p);
- assert(p->multipart_state == MULTIPART_INACTIVE);
+ UPB_ASSERT(p->multipart_state == MULTIPART_INACTIVE);
p->multipart_state = MULTIPART_ACCUMULATE;
}
@@ -10024,7 +10825,7 @@ static void multipart_startaccum(upb_json_parser *p) {
* value with the given selector. */
static void multipart_start(upb_json_parser *p, upb_selector_t sel) {
assert_accumulate_empty(p);
- assert(p->multipart_state == MULTIPART_INACTIVE);
+ UPB_ASSERT(p->multipart_state == MULTIPART_INACTIVE);
p->multipart_state = MULTIPART_PUSHEAGERLY;
p->string_selector = sel;
}
@@ -10057,7 +10858,7 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
/* Note: this invalidates the accumulate buffer! Call only after reading its
* contents. */
static void multipart_end(upb_json_parser *p) {
- assert(p->multipart_state != MULTIPART_INACTIVE);
+ UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE);
p->multipart_state = MULTIPART_INACTIVE;
accumulate_clear(p);
}
@@ -10070,13 +10871,13 @@ static void multipart_end(upb_json_parser *p) {
* region. */
static void capture_begin(upb_json_parser *p, const char *ptr) {
- assert(p->multipart_state != MULTIPART_INACTIVE);
- assert(p->capture == NULL);
+ UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE);
+ UPB_ASSERT(p->capture == NULL);
p->capture = ptr;
}
static bool capture_end(upb_json_parser *p, const char *ptr) {
- assert(p->capture);
+ UPB_ASSERT(p->capture);
if (multipart_text(p, p->capture, ptr - p->capture, true)) {
p->capture = NULL;
return true;
@@ -10109,7 +10910,7 @@ static void capture_suspend(upb_json_parser *p, const char **ptr) {
static void capture_resume(upb_json_parser *p, const char *ptr) {
if (p->capture) {
- assert(p->capture == &suspend_capture);
+ UPB_ASSERT(p->capture == &suspend_capture);
p->capture = ptr;
}
}
@@ -10131,7 +10932,7 @@ static char escape_char(char in) {
case '"': return '"';
case '\\': return '\\';
default:
- assert(0);
+ UPB_ASSERT(0);
return 'x';
}
}
@@ -10155,7 +10956,7 @@ static void hexdigit(upb_json_parser *p, const char *ptr) {
} else if (ch >= 'a' && ch <= 'f') {
p->digit += ((ch - 'a') + 10);
} else {
- assert(ch >= 'A' && ch <= 'F');
+ UPB_ASSERT(ch >= 'A' && ch <= 'F');
p->digit += ((ch - 'A') + 10);
}
}
@@ -10286,7 +11087,7 @@ static bool parse_number(upb_json_parser *p) {
break;
}
default:
- assert(false);
+ UPB_ASSERT(false);
}
multipart_end(p);
@@ -10312,13 +11113,13 @@ static bool parser_putbool(upb_json_parser *p, bool val) {
}
ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val);
- UPB_ASSERT_VAR(ok, ok);
+ UPB_ASSERT(ok);
return true;
}
static bool start_stringval(upb_json_parser *p) {
- assert(p->top->f);
+ UPB_ASSERT(p->top->f);
if (upb_fielddef_isstring(p->top->f)) {
upb_jsonparser_frame *inner;
@@ -10333,6 +11134,7 @@ static bool start_stringval(upb_json_parser *p) {
upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
inner->m = p->top->m;
inner->f = p->top->f;
+ inner->name_table = NULL;
inner->is_map = false;
inner->is_mapentry = false;
p->top = inner;
@@ -10379,8 +11181,8 @@ static bool end_stringval(upb_json_parser *p) {
case UPB_TYPE_STRING: {
upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(&p->top->sink, sel);
p->top--;
+ upb_sink_endstr(&p->top->sink, sel);
break;
}
@@ -10407,7 +11209,7 @@ static bool end_stringval(upb_json_parser *p) {
}
default:
- assert(false);
+ UPB_ASSERT(false);
upb_status_seterrmsg(&p->status, "Internal error in JSON decoder");
upb_env_reporterror(p->env, &p->status);
ok = false;
@@ -10420,7 +11222,7 @@ static bool end_stringval(upb_json_parser *p) {
}
static void start_member(upb_json_parser *p) {
- assert(!p->top->f);
+ UPB_ASSERT(!p->top->f);
multipart_startaccum(p);
}
@@ -10478,7 +11280,7 @@ static bool parse_mapentry_key(upb_json_parser *p) {
sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
upb_sink_putstring(&subsink, sel, buf, len, NULL);
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(&subsink, sel);
+ upb_sink_endstr(&p->top->sink, sel);
multipart_end(p);
break;
}
@@ -10519,6 +11321,7 @@ static bool handle_mapentry(upb_json_parser *p) {
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
inner->m = mapentrymsg;
+ inner->name_table = NULL;
inner->mapfield = mapfield;
inner->is_map = false;
@@ -10548,27 +11351,27 @@ static bool handle_mapentry(upb_json_parser *p) {
}
static bool end_membername(upb_json_parser *p) {
- assert(!p->top->f);
+ UPB_ASSERT(!p->top->f);
if (p->top->is_map) {
return handle_mapentry(p);
} else {
size_t len;
const char *buf = accumulate_getptr(p, &len);
- const upb_fielddef *f = upb_msgdef_ntof(p->top->m, buf, len);
+ upb_value v;
+
+ if (upb_strtable_lookup2(p->top->name_table, buf, len, &v)) {
+ p->top->f = upb_value_getconstptr(v);
+ multipart_end(p);
- if (!f) {
+ return true;
+ } else {
/* TODO(haberman): Ignore unknown fields if requested/configured to do
* so. */
upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf);
upb_env_reporterror(p->env, &p->status);
return false;
}
-
- p->top->f = f;
- multipart_end(p);
-
- return true;
}
}
@@ -10580,7 +11383,7 @@ static void end_member(upb_json_parser *p) {
bool ok;
const upb_fielddef *mapfield;
- assert(p->top > p->stack);
+ UPB_ASSERT(p->top > p->stack);
/* send ENDMSG on submsg. */
upb_sink_endmsg(&p->top->sink, &s);
mapfield = p->top->mapfield;
@@ -10588,7 +11391,7 @@ static void end_member(upb_json_parser *p) {
/* send ENDSUBMSG in repeated-field-of-mapentries frame. */
p->top--;
ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
- UPB_ASSERT_VAR(ok, ok);
+ UPB_ASSERT(ok);
upb_sink_endsubmsg(&p->top->sink, sel);
}
@@ -10596,7 +11399,7 @@ static void end_member(upb_json_parser *p) {
}
static bool start_subobject(upb_json_parser *p) {
- assert(p->top->f);
+ UPB_ASSERT(p->top->f);
if (upb_fielddef_ismap(p->top->f)) {
upb_jsonparser_frame *inner;
@@ -10610,6 +11413,7 @@ static bool start_subobject(upb_json_parser *p) {
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
upb_sink_startseq(&p->top->sink, sel, &inner->sink);
inner->m = upb_fielddef_msgsubdef(p->top->f);
+ inner->name_table = NULL;
inner->mapfield = p->top->f;
inner->f = NULL;
inner->is_map = true;
@@ -10630,6 +11434,7 @@ static bool start_subobject(upb_json_parser *p) {
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
inner->m = upb_fielddef_msgsubdef(p->top->f);
+ set_name_table(p, inner);
inner->f = NULL;
inner->is_map = false;
inner->is_mapentry = false;
@@ -10663,7 +11468,7 @@ static bool start_array(upb_json_parser *p) {
upb_jsonparser_frame *inner;
upb_selector_t sel;
- assert(p->top->f);
+ UPB_ASSERT(p->top->f);
if (!upb_fielddef_isseq(p->top->f)) {
upb_status_seterrf(&p->status,
@@ -10679,6 +11484,7 @@ static bool start_array(upb_json_parser *p) {
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
upb_sink_startseq(&p->top->sink, sel, &inner->sink);
inner->m = p->top->m;
+ inner->name_table = NULL;
inner->f = p->top->f;
inner->is_map = false;
inner->is_mapentry = false;
@@ -10690,7 +11496,7 @@ static bool start_array(upb_json_parser *p) {
static void end_array(upb_json_parser *p) {
upb_selector_t sel;
- assert(p->top > p->stack);
+ UPB_ASSERT(p->top > p->stack);
p->top--;
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
@@ -10736,11 +11542,11 @@ static void end_object(upb_json_parser *p) {
* final state once, when the closing '"' is seen. */
-#line 1218 "upb/json/parser.rl"
+#line 1244 "upb/json/parser.rl"
-#line 1130 "upb/json/parser.c"
+#line 1156 "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,
@@ -10889,7 +11695,7 @@ static const int json_en_value_machine = 27;
static const int json_en_main = 1;
-#line 1221 "upb/json/parser.rl"
+#line 1247 "upb/json/parser.rl"
size_t parse(void *closure, const void *hd, const char *buf, size_t size,
const upb_bufhandle *handle) {
@@ -10911,7 +11717,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size,
capture_resume(parser, buf);
-#line 1301 "upb/json/parser.c"
+#line 1327 "upb/json/parser.c"
{
int _klen;
unsigned int _trans;
@@ -10986,118 +11792,118 @@ _match:
switch ( *_acts++ )
{
case 0:
-#line 1133 "upb/json/parser.rl"
+#line 1159 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 1:
-#line 1134 "upb/json/parser.rl"
+#line 1160 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 10; goto _again;} }
break;
case 2:
-#line 1138 "upb/json/parser.rl"
+#line 1164 "upb/json/parser.rl"
{ start_text(parser, p); }
break;
case 3:
-#line 1139 "upb/json/parser.rl"
+#line 1165 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_text(parser, p)); }
break;
case 4:
-#line 1145 "upb/json/parser.rl"
+#line 1171 "upb/json/parser.rl"
{ start_hex(parser); }
break;
case 5:
-#line 1146 "upb/json/parser.rl"
+#line 1172 "upb/json/parser.rl"
{ hexdigit(parser, p); }
break;
case 6:
-#line 1147 "upb/json/parser.rl"
+#line 1173 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_hex(parser)); }
break;
case 7:
-#line 1153 "upb/json/parser.rl"
+#line 1179 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(escape(parser, p)); }
break;
case 8:
-#line 1159 "upb/json/parser.rl"
+#line 1185 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 9:
-#line 1162 "upb/json/parser.rl"
+#line 1188 "upb/json/parser.rl"
{ {stack[top++] = cs; cs = 19; goto _again;} }
break;
case 10:
-#line 1164 "upb/json/parser.rl"
+#line 1190 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 27; goto _again;} }
break;
case 11:
-#line 1169 "upb/json/parser.rl"
+#line 1195 "upb/json/parser.rl"
{ start_member(parser); }
break;
case 12:
-#line 1170 "upb/json/parser.rl"
+#line 1196 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_membername(parser)); }
break;
case 13:
-#line 1173 "upb/json/parser.rl"
+#line 1199 "upb/json/parser.rl"
{ end_member(parser); }
break;
case 14:
-#line 1179 "upb/json/parser.rl"
+#line 1205 "upb/json/parser.rl"
{ start_object(parser); }
break;
case 15:
-#line 1182 "upb/json/parser.rl"
+#line 1208 "upb/json/parser.rl"
{ end_object(parser); }
break;
case 16:
-#line 1188 "upb/json/parser.rl"
+#line 1214 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_array(parser)); }
break;
case 17:
-#line 1192 "upb/json/parser.rl"
+#line 1218 "upb/json/parser.rl"
{ end_array(parser); }
break;
case 18:
-#line 1197 "upb/json/parser.rl"
+#line 1223 "upb/json/parser.rl"
{ start_number(parser, p); }
break;
case 19:
-#line 1198 "upb/json/parser.rl"
+#line 1224 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); }
break;
case 20:
-#line 1200 "upb/json/parser.rl"
+#line 1226 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_stringval(parser)); }
break;
case 21:
-#line 1201 "upb/json/parser.rl"
+#line 1227 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_stringval(parser)); }
break;
case 22:
-#line 1203 "upb/json/parser.rl"
+#line 1229 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(parser_putbool(parser, true)); }
break;
case 23:
-#line 1205 "upb/json/parser.rl"
+#line 1231 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(parser_putbool(parser, false)); }
break;
case 24:
-#line 1207 "upb/json/parser.rl"
+#line 1233 "upb/json/parser.rl"
{ /* null value */ }
break;
case 25:
-#line 1209 "upb/json/parser.rl"
+#line 1235 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_subobject(parser)); }
break;
case 26:
-#line 1210 "upb/json/parser.rl"
+#line 1236 "upb/json/parser.rl"
{ end_subobject(parser); }
break;
case 27:
-#line 1215 "upb/json/parser.rl"
+#line 1241 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
-#line 1487 "upb/json/parser.c"
+#line 1513 "upb/json/parser.c"
}
}
@@ -11110,10 +11916,10 @@ _again:
_out: {}
}
-#line 1242 "upb/json/parser.rl"
+#line 1268 "upb/json/parser.rl"
if (p != pe) {
- upb_status_seterrf(&parser->status, "Parse error at %s\n", p);
+ upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p);
upb_env_reporterror(parser->env, &parser->status);
} else {
capture_suspend(parser, &p);
@@ -11151,13 +11957,13 @@ static void json_parser_reset(upb_json_parser *p) {
/* Emit Ragel initialization of the parser. */
-#line 1541 "upb/json/parser.c"
+#line 1567 "upb/json/parser.c"
{
cs = json_start;
top = 0;
}
-#line 1282 "upb/json/parser.rl"
+#line 1308 "upb/json/parser.rl"
p->current_state = cs;
p->parser_top = top;
accumulate_clear(p);
@@ -11167,10 +11973,84 @@ static void json_parser_reset(upb_json_parser *p) {
upb_status_clear(&p->status);
}
+static void visit_json_parsermethod(const upb_refcounted *r,
+ upb_refcounted_visit *visit,
+ void *closure) {
+ const upb_json_parsermethod *method = (upb_json_parsermethod*)r;
+ visit(r, upb_msgdef_upcast2(method->msg), closure);
+}
+
+static void free_json_parsermethod(upb_refcounted *r) {
+ upb_json_parsermethod *method = (upb_json_parsermethod*)r;
+
+ upb_inttable_iter i;
+ upb_inttable_begin(&i, &method->name_tables);
+ for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+ upb_value val = upb_inttable_iter_value(&i);
+ upb_strtable *t = upb_value_getptr(val);
+ upb_strtable_uninit(t);
+ upb_gfree(t);
+ }
+
+ upb_inttable_uninit(&method->name_tables);
+
+ upb_gfree(r);
+}
+
+static void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* md) {
+ upb_msg_field_iter i;
+ upb_strtable *t;
+
+ /* It would be nice to stack-allocate this, but protobufs do not limit the
+ * length of fields to any reasonable limit. */
+ char *buf = NULL;
+ size_t len = 0;
+
+ if (upb_inttable_lookupptr(&m->name_tables, md, NULL)) {
+ return;
+ }
+
+ /* TODO(haberman): handle malloc failure. */
+ t = upb_gmalloc(sizeof(*t));
+ upb_strtable_init(t, UPB_CTYPE_CONSTPTR);
+ upb_inttable_insertptr(&m->name_tables, md, upb_value_ptr(t));
+
+ for(upb_msg_field_begin(&i, md);
+ !upb_msg_field_done(&i);
+ upb_msg_field_next(&i)) {
+ const upb_fielddef *f = upb_msg_iter_field(&i);
+
+ /* Add an entry for the JSON name. */
+ size_t field_len = upb_fielddef_getjsonname(f, buf, len);
+ if (field_len > len) {
+ size_t len2;
+ buf = upb_grealloc(buf, 0, field_len);
+ len = field_len;
+ len2 = upb_fielddef_getjsonname(f, buf, len);
+ UPB_ASSERT(len == len2);
+ }
+ upb_strtable_insert(t, buf, upb_value_constptr(f));
+
+ if (strcmp(buf, upb_fielddef_name(f)) != 0) {
+ /* Since the JSON name is different from the regular field name, add an
+ * entry for the raw name (compliant proto3 JSON parsers must accept
+ * both). */
+ upb_strtable_insert(t, upb_fielddef_name(f), upb_value_constptr(f));
+ }
+
+ if (upb_fielddef_issubmsg(f)) {
+ add_jsonname_table(m, upb_fielddef_msgsubdef(f));
+ }
+ }
+
+ upb_gfree(buf);
+}
/* Public API *****************************************************************/
-upb_json_parser *upb_json_parser_create(upb_env *env, upb_sink *output) {
+upb_json_parser *upb_json_parser_create(upb_env *env,
+ const upb_json_parsermethod *method,
+ upb_sink *output) {
#ifndef NDEBUG
const size_t size_before = upb_env_bytesallocated(env);
#endif
@@ -11178,35 +12058,59 @@ upb_json_parser *upb_json_parser_create(upb_env *env, upb_sink *output) {
if (!p) return false;
p->env = env;
+ p->method = method;
p->limit = p->stack + UPB_JSON_MAX_DEPTH;
p->accumulate_buf = NULL;
p->accumulate_buf_size = 0;
- upb_byteshandler_init(&p->input_handler_);
- upb_byteshandler_setstring(&p->input_handler_, parse, NULL);
- upb_byteshandler_setendstr(&p->input_handler_, end, NULL);
- upb_bytessink_reset(&p->input_, &p->input_handler_, p);
+ upb_bytessink_reset(&p->input_, &method->input_handler_, p);
json_parser_reset(p);
upb_sink_reset(&p->top->sink, output->handlers, output->closure);
p->top->m = upb_handlers_msgdef(output->handlers);
+ set_name_table(p, p->top);
/* If this fails, uncomment and increase the value in parser.h. */
/* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */
- assert(upb_env_bytesallocated(env) - size_before <= UPB_JSON_PARSER_SIZE);
+ UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <=
+ UPB_JSON_PARSER_SIZE);
return p;
}
upb_bytessink *upb_json_parser_input(upb_json_parser *p) {
return &p->input_;
}
+
+upb_json_parsermethod *upb_json_parsermethod_new(const upb_msgdef* md,
+ const void* owner) {
+ static const struct upb_refcounted_vtbl vtbl = {visit_json_parsermethod,
+ free_json_parsermethod};
+ upb_json_parsermethod *ret = upb_gmalloc(sizeof(*ret));
+ upb_refcounted_init(upb_json_parsermethod_upcast_mutable(ret), &vtbl, owner);
+
+ ret->msg = md;
+ upb_ref2(md, ret);
+
+ upb_byteshandler_init(&ret->input_handler_);
+ upb_byteshandler_setstring(&ret->input_handler_, parse, ret);
+ upb_byteshandler_setendstr(&ret->input_handler_, end, ret);
+
+ upb_inttable_init(&ret->name_tables, UPB_CTYPE_PTR);
+
+ add_jsonname_table(ret, md);
+
+ return ret;
+}
+
+const upb_byteshandler *upb_json_parsermethod_inputhandler(
+ const upb_json_parsermethod *m) {
+ return &m->input_handler_;
+}
/*
** This currently uses snprintf() to format primitives, and could be optimized
** further.
*/
-#include <stdlib.h>
-#include <stdio.h>
#include <string.h>
#include <stdint.h>
@@ -11233,15 +12137,34 @@ struct upb_json_printer {
/* StringPiece; a pointer plus a length. */
typedef struct {
- const char *ptr;
+ char *ptr;
size_t len;
} strpc;
-strpc *newstrpc(upb_handlers *h, const upb_fielddef *f) {
- strpc *ret = malloc(sizeof(*ret));
- ret->ptr = upb_fielddef_name(f);
- ret->len = strlen(ret->ptr);
- upb_handlers_addcleanup(h, ret, free);
+void freestrpc(void *ptr) {
+ strpc *pc = ptr;
+ upb_gfree(pc->ptr);
+ upb_gfree(pc);
+}
+
+/* Convert fielddef name to JSON name and return as a string piece. */
+strpc *newstrpc(upb_handlers *h, const upb_fielddef *f,
+ bool preserve_fieldnames) {
+ /* TODO(haberman): handle malloc failure. */
+ strpc *ret = upb_gmalloc(sizeof(*ret));
+ if (preserve_fieldnames) {
+ ret->ptr = upb_gstrdup(upb_fielddef_name(f));
+ ret->len = strlen(ret->ptr);
+ } else {
+ size_t len;
+ ret->len = upb_fielddef_getjsonname(f, NULL, 0);
+ ret->ptr = upb_gmalloc(ret->len);
+ len = upb_fielddef_getjsonname(f, ret->ptr, ret->len);
+ UPB_ASSERT(len == ret->len);
+ ret->len--; /* NULL */
+ }
+
+ upb_handlers_addcleanup(h, ret, freestrpc);
return ret;
}
@@ -11251,7 +12174,7 @@ static void print_data(
upb_json_printer *p, const char *buf, unsigned int len) {
/* TODO: Will need to change if we support pushback from the sink. */
size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL);
- UPB_ASSERT_VAR(n, n == len);
+ UPB_ASSERT(n == len);
}
static void print_comma(upb_json_printer *p) {
@@ -11272,7 +12195,7 @@ UPB_INLINE bool is_json_escaped(char c) {
return uc < kControlCharLimit || uc == '"' || uc == '\\';
}
-UPB_INLINE char* json_nice_escape(char c) {
+UPB_INLINE const char* json_nice_escape(char c) {
switch (c) {
case '"': return "\\\"";
case '\\': return "\\\\";
@@ -11601,7 +12524,7 @@ static size_t putbytes(void *closure, const void *handler_data, const char *str,
while (remaining > 2) {
/* TODO(haberman): handle encoded lengths > sizeof(data) */
- UPB_ASSERT_VAR(limit, (limit - to) >= 4);
+ UPB_ASSERT((limit - to) >= 4);
to[0] = base64[from[0] >> 2];
to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
@@ -11745,11 +12668,12 @@ static size_t mapkey_bytes(void *closure, const void *handler_data,
static void set_enum_hd(upb_handlers *h,
const upb_fielddef *f,
+ bool preserve_fieldnames,
upb_handlerattr *attr) {
- EnumHandlerData *hd = malloc(sizeof(EnumHandlerData));
+ EnumHandlerData *hd = upb_gmalloc(sizeof(EnumHandlerData));
hd->enumdef = (const upb_enumdef *)upb_fielddef_subdef(f);
- hd->keyname = newstrpc(h, f);
- upb_handlers_addcleanup(h, hd, free);
+ hd->keyname = newstrpc(h, f, preserve_fieldnames);
+ upb_handlers_addcleanup(h, hd, upb_gfree);
upb_handlerattr_sethandlerdata(attr, hd);
}
@@ -11765,7 +12689,8 @@ static void set_enum_hd(upb_handlers *h,
* our sources that emit mapentry messages do so canonically (with one key
* field, and then one value field), so this is not a pressing concern at the
* moment. */
-void printer_sethandlers_mapentry(const void *closure, upb_handlers *h) {
+void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames,
+ upb_handlers *h) {
const upb_msgdef *md = upb_handlers_msgdef(h);
/* A mapentry message is printed simply as '"key": value'. Rather than
@@ -11803,7 +12728,7 @@ void printer_sethandlers_mapentry(const void *closure, upb_handlers *h) {
upb_handlers_setstring(h, key_field, mapkey_bytes, &empty_attr);
break;
default:
- assert(false);
+ UPB_ASSERT(false);
break;
}
@@ -11839,7 +12764,7 @@ void printer_sethandlers_mapentry(const void *closure, upb_handlers *h) {
break;
case UPB_TYPE_ENUM: {
upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER;
- set_enum_hd(h, value_field, &enum_attr);
+ set_enum_hd(h, value_field, preserve_fieldnames, &enum_attr);
upb_handlers_setint32(h, value_field, mapvalue_enum, &enum_attr);
upb_handlerattr_uninit(&enum_attr);
break;
@@ -11858,13 +12783,13 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
bool is_mapentry = upb_msgdef_mapentry(md);
upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
upb_msg_field_iter i;
-
- UPB_UNUSED(closure);
+ const bool *preserve_fieldnames_ptr = closure;
+ const bool preserve_fieldnames = *preserve_fieldnames_ptr;
if (is_mapentry) {
/* mapentry messages are sufficiently different that we handle them
* separately. */
- printer_sethandlers_mapentry(closure, h);
+ printer_sethandlers_mapentry(closure, preserve_fieldnames, h);
return;
}
@@ -11885,7 +12810,8 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
const upb_fielddef *f = upb_msg_iter_field(&i);
upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER;
- upb_handlerattr_sethandlerdata(&name_attr, newstrpc(h, f));
+ upb_handlerattr_sethandlerdata(&name_attr,
+ newstrpc(h, f, preserve_fieldnames));
if (upb_fielddef_ismap(f)) {
upb_handlers_setstartseq(h, f, startmap, &name_attr);
@@ -11908,7 +12834,7 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
* option later to control this behavior, but we will wait for a real
* need first. */
upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER;
- set_enum_hd(h, f, &enum_attr);
+ set_enum_hd(h, f, preserve_fieldnames, &enum_attr);
if (upb_fielddef_isseq(f)) {
upb_handlers_setint32(h, f, repeated_enum, &enum_attr);
@@ -11976,7 +12902,8 @@ upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
upb_sink_reset(&p->input_, h, p);
/* If this fails, increase the value in printer.h. */
- assert(upb_env_bytesallocated(e) - size_before <= UPB_JSON_PRINTER_SIZE);
+ UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(e) - size_before <=
+ UPB_JSON_PRINTER_SIZE);
return p;
}
@@ -11985,6 +12912,8 @@ upb_sink *upb_json_printer_input(upb_json_printer *p) {
}
const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
+ bool preserve_fieldnames,
const void *owner) {
- return upb_handlers_newfrozen(md, owner, printer_sethandlers, NULL);
+ return upb_handlers_newfrozen(
+ md, owner, printer_sethandlers, &preserve_fieldnames);
}
diff --git a/php/ext/google/protobuf/upb.h b/php/ext/google/protobuf/upb.h
index 073faf41..c83b0e03 100644
--- a/php/ext/google/protobuf/upb.h
+++ b/php/ext/google/protobuf/upb.h
@@ -5,6 +5,7 @@
**
** - 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.
@@ -54,14 +55,19 @@
** store pointers or integers of at least 32 bits (upb isn't really useful on
** systems where sizeof(void*) < 4).
**
-** The table must be homogeneous (all values of the same type). In debug
+** 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 <assert.h>
+// php.h intentionally defined NDEBUG. We have to define this macro in order to
+// be used together with php.h
+#ifndef NDEBUG
+#define NDEBUG
+#endif
+
#include <stdint.h>
#include <string.h>
/*
@@ -79,6 +85,18 @@
#include <stdbool.h>
#include <stddef.h>
+#ifdef __cplusplus
+namespace upb {
+class Allocator;
+class Arena;
+class Environment;
+class ErrorSpace;
+class Status;
+template <int N> class InlinedArena;
+template <int N> class InlinedEnvironment;
+}
+#endif
+
/* UPB_INLINE: inline if possible, emit standalone code if required. */
#ifdef __cplusplus
#define UPB_INLINE inline
@@ -146,6 +164,7 @@
#define UPB_ASSERT_STDLAYOUT(type) \
static_assert(std::is_standard_layout<type>::value, \
#type " must be standard layout");
+#define UPB_FINAL final
#else /* !defined(UPB_CXX11) */
#define UPB_DISALLOW_COPY_AND_ASSIGN(class_name) \
class_name(const class_name&); \
@@ -155,6 +174,7 @@
~class_name(); \
UPB_DISALLOW_COPY_AND_ASSIGN(class_name)
#define UPB_ASSERT_STDLAYOUT(type)
+#define UPB_FINAL
#endif
/* UPB_DECLARE_TYPE()
@@ -193,13 +213,15 @@
template <> \
class Pointer<cppname> : public PointerBase<cppname, cppbase> { \
public: \
- explicit Pointer(cppname* ptr) : PointerBase(ptr) {} \
+ explicit Pointer(cppname* ptr) \
+ : PointerBase<cppname, cppbase>(ptr) {} \
}; \
template <> \
class Pointer<const cppname> \
: public PointerBase<const cppname, const cppbase> { \
public: \
- explicit Pointer(const cppname* ptr) : PointerBase(ptr) {} \
+ explicit Pointer(const cppname* ptr) \
+ : PointerBase<const cppname, const cppbase>(ptr) {} \
}; \
}
@@ -211,13 +233,15 @@
template <> \
class Pointer<cppname> : public PointerBase2<cppname, cppbase, cppbase2> { \
public: \
- explicit Pointer(cppname* ptr) : PointerBase2(ptr) {} \
+ explicit Pointer(cppname* ptr) \
+ : PointerBase2<cppname, cppbase, cppbase2>(ptr) {} \
}; \
template <> \
class Pointer<const cppname> \
: public PointerBase2<const cppname, const cppbase, const cppbase2> { \
public: \
- explicit Pointer(const cppname* ptr) : PointerBase2(ptr) {} \
+ explicit Pointer(const cppname* ptr) \
+ : PointerBase2<const cppname, const cppbase, const cppbase2>(ptr) {} \
}; \
}
@@ -244,14 +268,22 @@
#define UPB_UNUSED(var) (void)var
-/* For asserting something about a variable when the variable is not used for
- * anything else. This prevents "unused variable" warnings when compiling in
- * debug mode. */
-#define UPB_ASSERT_VAR(var, predicate) UPB_UNUSED(var); assert(predicate)
+/* UPB_ASSERT(): in release mode, we use the expression without letting it be
+ * evaluated. This prevents "unused variable" warnings. */
+#ifdef NDEBUG
+#define UPB_ASSERT(expr) do {} while (false && (expr))
+#else
+#define UPB_ASSERT(expr) assert(expr)
+#endif
+
+/* UPB_ASSERT_DEBUGVAR(): assert that uses functions or variables that only
+ * exist in debug mode. This turns into regular assert. */
+#define UPB_ASSERT_DEBUGVAR(expr) assert(expr)
/* Generic function type. */
typedef void upb_func();
+
/* C++ Casts ******************************************************************/
#ifdef __cplusplus
@@ -329,243 +361,430 @@ class PointerBase2 : public PointerBase<T, Base> {
#endif
-/* upb::reffed_ptr ************************************************************/
+/* upb::ErrorSpace ************************************************************/
+
+/* A upb::ErrorSpace represents some domain of possible error values. This lets
+ * upb::Status attach specific error codes to operations, like POSIX/C errno,
+ * Win32 error codes, etc. Clients who want to know the very specific error
+ * code can check the error space and then know the type of the integer code.
+ *
+ * NOTE: upb::ErrorSpace is currently not used and should be considered
+ * experimental. It is important primarily in cases where upb is performing
+ * I/O, but upb doesn't currently have any components that do this. */
+
+UPB_DECLARE_TYPE(upb::ErrorSpace, upb_errorspace)
#ifdef __cplusplus
+class upb::ErrorSpace {
+#else
+struct upb_errorspace {
+#endif
+ const char *name;
+};
-#include <algorithm> /* For std::swap(). */
-namespace upb {
+/* upb::Status ****************************************************************/
-/* Provides RAII semantics for upb refcounted objects. Each reffed_ptr owns a
- * ref on whatever object it points to (if any). */
-template <class T> class reffed_ptr {
+/* upb::Status represents a success or failure status and error message.
+ * It owns no resources and allocates no memory, so it should work
+ * even in OOM situations. */
+UPB_DECLARE_TYPE(upb::Status, upb_status)
+
+/* The maximum length of an error message before it will get truncated. */
+#define UPB_STATUS_MAX_MESSAGE 128
+
+UPB_BEGIN_EXTERN_C
+
+const char *upb_status_errmsg(const upb_status *status);
+bool upb_ok(const upb_status *status);
+upb_errorspace *upb_status_errspace(const upb_status *status);
+int upb_status_errcode(const upb_status *status);
+
+/* Any of the functions that write to a status object allow status to be NULL,
+ * to support use cases where the function's caller does not care about the
+ * status message. */
+void upb_status_clear(upb_status *status);
+void upb_status_seterrmsg(upb_status *status, const char *msg);
+void upb_status_seterrf(upb_status *status, const char *fmt, ...);
+void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args);
+void upb_status_copy(upb_status *to, const upb_status *from);
+
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+class upb::Status {
public:
- reffed_ptr() : ptr_(NULL) {}
+ Status() { upb_status_clear(this); }
- /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */
- template <class U>
- reffed_ptr(U* val, const void* ref_donor = NULL)
- : ptr_(upb::upcast(val)) {
- if (ref_donor) {
- assert(ptr_);
- ptr_->DonateRef(ref_donor, this);
- } else if (ptr_) {
- ptr_->Ref(this);
- }
- }
+ /* Returns true if there is no error. */
+ bool ok() const { return upb_ok(this); }
- template <class U>
- reffed_ptr(const reffed_ptr<U>& other)
- : ptr_(upb::upcast(other.get())) {
- if (ptr_) ptr_->Ref(this);
- }
+ /* Optional error space and code, useful if the caller wants to
+ * programmatically check the specific kind of error. */
+ ErrorSpace* error_space() { return upb_status_errspace(this); }
+ int error_code() const { return upb_status_errcode(this); }
- ~reffed_ptr() { if (ptr_) ptr_->Unref(this); }
+ /* The returned string is invalidated by any other call into the status. */
+ const char *error_message() const { return upb_status_errmsg(this); }
- template <class U>
- reffed_ptr& operator=(const reffed_ptr<U>& other) {
- reset(other.get());
- return *this;
+ /* The error message will be truncated if it is longer than
+ * UPB_STATUS_MAX_MESSAGE-4. */
+ void SetErrorMessage(const char* msg) { upb_status_seterrmsg(this, msg); }
+ void SetFormattedErrorMessage(const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ upb_status_vseterrf(this, fmt, args);
+ va_end(args);
}
- reffed_ptr& operator=(const reffed_ptr& other) {
- reset(other.get());
- return *this;
- }
+ /* Resets the status to a successful state with no message. */
+ void Clear() { upb_status_clear(this); }
- /* TODO(haberman): add C++11 move construction/assignment for greater
- * efficiency. */
+ void CopyFrom(const Status& other) { upb_status_copy(this, &other); }
- void swap(reffed_ptr& other) {
- if (ptr_ == other.ptr_) {
- return;
- }
+ private:
+ UPB_DISALLOW_COPY_AND_ASSIGN(Status)
+#else
+struct upb_status {
+#endif
+ bool ok_;
- if (ptr_) ptr_->DonateRef(this, &other);
- if (other.ptr_) other.ptr_->DonateRef(&other, this);
- std::swap(ptr_, other.ptr_);
- }
+ /* Specific status code defined by some error space (optional). */
+ int code_;
+ upb_errorspace *error_space_;
- T& operator*() const {
- assert(ptr_);
- return *ptr_;
- }
+ /* TODO(haberman): add file/line of error? */
- T* operator->() const {
- assert(ptr_);
- return ptr_;
- }
+ /* Error message; NULL-terminated. */
+ char msg[UPB_STATUS_MAX_MESSAGE];
+};
- T* get() const { return ptr_; }
+#define UPB_STATUS_INIT {true, 0, NULL, {0}}
- /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */
- template <class U>
- void reset(U* ptr = NULL, const void* ref_donor = NULL) {
- reffed_ptr(ptr, ref_donor).swap(*this);
- }
- template <class U>
- reffed_ptr<U> down_cast() {
- return reffed_ptr<U>(upb::down_cast<U*>(get()));
- }
+/** Built-in error spaces. ****************************************************/
- template <class U>
- reffed_ptr<U> dyn_cast() {
- return reffed_ptr<U>(upb::dyn_cast<U*>(get()));
- }
+/* Errors raised by upb that we want to be able to detect programmatically. */
+typedef enum {
+ UPB_NOMEM /* Can't reuse ENOMEM because it is POSIX, not ISO C. */
+} upb_errcode_t;
- /* Plain release() is unsafe; if we were the only owner, it would leak the
- * object. Instead we provide this: */
- T* ReleaseTo(const void* new_owner) {
- T* ret = NULL;
- ptr_->DonateRef(this, new_owner);
- std::swap(ret, ptr_);
- return ret;
- }
+extern upb_errorspace upb_upberr;
+
+void upb_upberr_setoom(upb_status *s);
+
+/* Since errno is defined by standard C, we define an error space for it in
+ * core upb. Other error spaces should be defined in other, platform-specific
+ * modules. */
+
+extern upb_errorspace upb_errnoerr;
+
+
+/** upb::Allocator ************************************************************/
+
+/* A upb::Allocator is a possibly-stateful allocator object.
+ *
+ * It could either be an arena allocator (which doesn't require individual
+ * free() calls) or a regular malloc() (which does). The client must therefore
+ * free memory unless it knows that the allocator is an arena allocator. */
+UPB_DECLARE_TYPE(upb::Allocator, upb_alloc)
+
+/* A malloc()/free() function.
+ * If "size" is 0 then the function acts like free(), otherwise it acts like
+ * realloc(). Only "oldsize" bytes from a previous allocation are preserved. */
+typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize,
+ size_t size);
+
+#ifdef __cplusplus
+
+class upb::Allocator UPB_FINAL {
+ public:
+ Allocator() {}
private:
- T* ptr_;
+ UPB_DISALLOW_COPY_AND_ASSIGN(Allocator)
+
+ public:
+#else
+struct upb_alloc {
+#endif /* __cplusplus */
+ upb_alloc_func *func;
};
-} /* namespace upb */
+UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) {
+ UPB_ASSERT(size > 0);
+ return alloc->func(alloc, NULL, 0, size);
+}
-#endif /* __cplusplus */
+UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize,
+ size_t size) {
+ UPB_ASSERT(size > 0);
+ return alloc->func(alloc, ptr, oldsize, size);
+}
+UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) {
+ alloc->func(alloc, ptr, 0, 0);
+}
-/* upb::Status ****************************************************************/
+/* The global allocator used by upb. Uses the standard malloc()/free(). */
-#ifdef __cplusplus
-namespace upb {
-class ErrorSpace;
-class Status;
+extern upb_alloc upb_alloc_global;
+
+/* Functions that hard-code the global malloc.
+ *
+ * We still get benefit because we can put custom logic into our global
+ * allocator, like injecting out-of-memory faults in debug/testing builds. */
+
+UPB_INLINE void *upb_gmalloc(size_t size) {
+ return upb_malloc(&upb_alloc_global, size);
}
-#endif
-UPB_DECLARE_TYPE(upb::ErrorSpace, upb_errorspace)
-UPB_DECLARE_TYPE(upb::Status, upb_status)
+UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) {
+ return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
+}
-/* The maximum length of an error message before it will get truncated. */
-#define UPB_STATUS_MAX_MESSAGE 128
+UPB_INLINE void upb_gfree(void *ptr) {
+ upb_free(&upb_alloc_global, ptr);
+}
-/* An error callback function is used to report errors from some component.
- * The function can return "true" to indicate that the component should try
- * to recover and proceed, but this is not always possible. */
-typedef bool upb_errcb_t(void *closure, const upb_status* status);
+/* upb::Arena *****************************************************************/
+
+/* upb::Arena is a specific allocator implementation that uses arena allocation.
+ * The user provides an allocator that will be used to allocate the underlying
+ * arena blocks. Arenas by nature do not require the individual allocations
+ * to be freed. However the Arena does allow users to register cleanup
+ * functions that will run when the arena is destroyed.
+ *
+ * A upb::Arena is *not* thread-safe.
+ *
+ * You could write a thread-safe arena allocator that satisfies the
+ * upb::Allocator interface, but it would not be as efficient for the
+ * single-threaded case. */
+UPB_DECLARE_TYPE(upb::Arena, upb_arena)
+
+typedef void upb_cleanup_func(void *ud);
+
+#define UPB_ARENA_BLOCK_OVERHEAD (sizeof(size_t)*4)
+
+UPB_BEGIN_EXTERN_C
+
+void upb_arena_init(upb_arena *a);
+void upb_arena_init2(upb_arena *a, void *mem, size_t n, upb_alloc *alloc);
+void upb_arena_uninit(upb_arena *a);
+upb_alloc *upb_arena_alloc(upb_arena *a);
+bool upb_arena_addcleanup(upb_arena *a, upb_cleanup_func *func, void *ud);
+size_t upb_arena_bytesallocated(const upb_arena *a);
+void upb_arena_setnextblocksize(upb_arena *a, size_t size);
+void upb_arena_setmaxblocksize(upb_arena *a, size_t size);
+
+UPB_END_EXTERN_C
#ifdef __cplusplus
-class upb::ErrorSpace {
+
+class upb::Arena {
+ public:
+ /* A simple arena with no initial memory block and the default allocator. */
+ Arena() { upb_arena_init(this); }
+
+ /* Constructs an arena with the given initial block which allocates blocks
+ * with the given allocator. The given allocator must outlive the Arena.
+ *
+ * If you pass NULL for the allocator it will default to the global allocator
+ * upb_alloc_global, and NULL/0 for the initial block will cause there to be
+ * no initial block. */
+ Arena(void *mem, size_t len, Allocator* a) {
+ upb_arena_init2(this, mem, len, a);
+ }
+
+ ~Arena() { upb_arena_uninit(this); }
+
+ /* Sets the size of the next block the Arena will request (unless the
+ * requested allocation is larger). Each block will double in size until the
+ * max limit is reached. */
+ void SetNextBlockSize(size_t size) { upb_arena_setnextblocksize(this, size); }
+
+ /* Sets the maximum block size. No blocks larger than this will be requested
+ * from the underlying allocator unless individual arena allocations are
+ * larger. */
+ void SetMaxBlockSize(size_t size) { upb_arena_setmaxblocksize(this, size); }
+
+ /* Allows this arena to be used as a generic allocator.
+ *
+ * The arena does not need free() calls so when using Arena as an allocator
+ * it is safe to skip them. However they are no-ops so there is no harm in
+ * calling free() either. */
+ Allocator* allocator() { return upb_arena_alloc(this); }
+
+ /* Add a cleanup function to run when the arena is destroyed.
+ * Returns false on out-of-memory. */
+ bool AddCleanup(upb_cleanup_func* func, void* ud) {
+ return upb_arena_addcleanup(this, func, ud);
+ }
+
+ /* Total number of bytes that have been allocated. It is undefined what
+ * Realloc() does to this counter. */
+ size_t BytesAllocated() const {
+ return upb_arena_bytesallocated(this);
+ }
+
+ private:
+ UPB_DISALLOW_COPY_AND_ASSIGN(Arena)
+
#else
-struct upb_errorspace {
-#endif
- const char *name;
- /* Should the error message in the status object according to this code. */
- void (*set_message)(upb_status* status, int code);
+struct upb_arena {
+#endif /* __cplusplus */
+ /* We implement the allocator interface.
+ * This must be the first member of upb_arena! */
+ upb_alloc alloc;
+
+ /* Allocator to allocate arena blocks. We are responsible for freeing these
+ * when we are destroyed. */
+ upb_alloc *block_alloc;
+
+ size_t bytes_allocated;
+ size_t next_block_size;
+ size_t max_block_size;
+
+ /* Linked list of blocks. Points to an arena_block, defined in env.c */
+ void *block_head;
+
+ /* Cleanup entries. Pointer to a cleanup_ent, defined in env.c */
+ void *cleanup_head;
+
+ /* For future expansion, since the size of this struct is exposed to users. */
+ void *future1;
+ void *future2;
};
-#ifdef __cplusplus
-/* Object representing a success or failure status.
- * It owns no resources and allocates no memory, so it should work
- * even in OOM situations. */
+/* upb::Environment ***********************************************************/
-class upb::Status {
- public:
- Status();
+/* A upb::Environment provides a means for injecting malloc and an
+ * error-reporting callback into encoders/decoders. This allows them to be
+ * independent of nearly all assumptions about their actual environment.
+ *
+ * It is also a container for allocating the encoders/decoders themselves that
+ * insulates clients from knowing their actual size. This provides ABI
+ * compatibility even if the size of the objects change. And this allows the
+ * structure definitions to be in the .c files instead of the .h files, making
+ * the .h files smaller and more readable.
+ *
+ * We might want to consider renaming this to "Pipeline" if/when the concept of
+ * a pipeline element becomes more formalized. */
+UPB_DECLARE_TYPE(upb::Environment, upb_env)
- /* Returns true if there is no error. */
- bool ok() const;
+/* A function that receives an error report from an encoder or decoder. The
+ * callback can return true to request that the error should be recovered, but
+ * if the error is not recoverable this has no effect. */
+typedef bool upb_error_func(void *ud, const upb_status *status);
- /* Optional error space and code, useful if the caller wants to
- * programmatically check the specific kind of error. */
- ErrorSpace* error_space();
- int code() const;
+UPB_BEGIN_EXTERN_C
- const char *error_message() const;
+void upb_env_init(upb_env *e);
+void upb_env_init2(upb_env *e, void *mem, size_t n, upb_alloc *alloc);
+void upb_env_uninit(upb_env *e);
- /* The error message will be truncated if it is longer than
- * UPB_STATUS_MAX_MESSAGE-4. */
- void SetErrorMessage(const char* msg);
- void SetFormattedErrorMessage(const char* fmt, ...);
+void upb_env_initonly(upb_env *e);
- /* If there is no error message already, this will use the ErrorSpace to
- * populate the error message for this code. The caller can still call
- * SetErrorMessage() to give a more specific message. */
- void SetErrorCode(ErrorSpace* space, int code);
+upb_arena *upb_env_arena(upb_env *e);
+bool upb_env_ok(const upb_env *e);
+void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud);
- /* Resets the status to a successful state with no message. */
- void Clear();
+/* Convenience wrappers around the methods of the contained arena. */
+void upb_env_reporterrorsto(upb_env *e, upb_status *s);
+bool upb_env_reporterror(upb_env *e, const upb_status *s);
+void *upb_env_malloc(upb_env *e, size_t size);
+void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size);
+void upb_env_free(upb_env *e, void *ptr);
+bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud);
+size_t upb_env_bytesallocated(const upb_env *e);
- void CopyFrom(const Status& other);
+UPB_END_EXTERN_C
+
+#ifdef __cplusplus
+
+class upb::Environment {
+ public:
+ /* The given Arena must outlive this environment. */
+ Environment() { upb_env_initonly(this); }
+
+ Environment(void *mem, size_t len, Allocator *a) : arena_(mem, len, a) {
+ upb_env_initonly(this);
+ }
+
+ Arena* arena() { return upb_env_arena(this); }
+
+ /* Set a custom error reporting function. */
+ void SetErrorFunction(upb_error_func* func, void* ud) {
+ upb_env_seterrorfunc(this, func, ud);
+ }
+
+ /* Set the error reporting function to simply copy the status to the given
+ * status and abort. */
+ void ReportErrorsTo(Status* status) { upb_env_reporterrorsto(this, status); }
+
+ /* Returns true if all allocations and AddCleanup() calls have succeeded,
+ * and no errors were reported with ReportError() (except ones that recovered
+ * successfully). */
+ bool ok() const { return upb_env_ok(this); }
+
+ /* Reports an error to this environment's callback, returning true if
+ * the caller should try to recover. */
+ bool ReportError(const Status* status) {
+ return upb_env_reporterror(this, status);
+ }
private:
- UPB_DISALLOW_COPY_AND_ASSIGN(Status)
+ UPB_DISALLOW_COPY_AND_ASSIGN(Environment)
+
#else
-struct upb_status {
-#endif
+struct upb_env {
+#endif /* __cplusplus */
+ upb_arena arena_;
+ upb_error_func *error_func_;
+ void *error_ud_;
bool ok_;
+};
- /* Specific status code defined by some error space (optional). */
- int code_;
- upb_errorspace *error_space_;
- /* Error message; NULL-terminated. */
- char msg[UPB_STATUS_MAX_MESSAGE];
-};
+/* upb::InlinedArena **********************************************************/
+/* upb::InlinedEnvironment ****************************************************/
-#define UPB_STATUS_INIT {true, 0, NULL, {0}}
+/* upb::InlinedArena and upb::InlinedEnvironment seed their arenas with a
+ * predefined amount of memory. No heap memory will be allocated until the
+ * initial block is exceeded.
+ *
+ * These types only exist in C++ */
#ifdef __cplusplus
-extern "C" {
-#endif
-/* The returned string is invalidated by any other call into the status. */
-const char *upb_status_errmsg(const upb_status *status);
-bool upb_ok(const upb_status *status);
-upb_errorspace *upb_status_errspace(const upb_status *status);
-int upb_status_errcode(const upb_status *status);
+template <int N> class upb::InlinedArena : public upb::Arena {
+ public:
+ InlinedArena() : Arena(initial_block_, N, NULL) {}
+ explicit InlinedArena(Allocator* a) : Arena(initial_block_, N, a) {}
-/* Any of the functions that write to a status object allow status to be NULL,
- * to support use cases where the function's caller does not care about the
- * status message. */
-void upb_status_clear(upb_status *status);
-void upb_status_seterrmsg(upb_status *status, const char *msg);
-void upb_status_seterrf(upb_status *status, const char *fmt, ...);
-void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args);
-void upb_status_seterrcode(upb_status *status, upb_errorspace *space, int code);
-void upb_status_copy(upb_status *to, const upb_status *from);
+ private:
+ UPB_DISALLOW_COPY_AND_ASSIGN(InlinedArena)
-#ifdef __cplusplus
-} /* extern "C" */
+ char initial_block_[N + UPB_ARENA_BLOCK_OVERHEAD];
+};
-namespace upb {
+template <int N> class upb::InlinedEnvironment : public upb::Environment {
+ public:
+ InlinedEnvironment() : Environment(initial_block_, N, NULL) {}
+ explicit InlinedEnvironment(Allocator *a)
+ : Environment(initial_block_, N, a) {}
-/* C++ Wrappers */
-inline Status::Status() { Clear(); }
-inline bool Status::ok() const { return upb_ok(this); }
-inline const char* Status::error_message() const {
- return upb_status_errmsg(this);
-}
-inline void Status::SetErrorMessage(const char* msg) {
- upb_status_seterrmsg(this, msg);
-}
-inline void Status::SetFormattedErrorMessage(const char* fmt, ...) {
- va_list args;
- va_start(args, fmt);
- upb_status_vseterrf(this, fmt, args);
- va_end(args);
-}
-inline void Status::SetErrorCode(ErrorSpace* space, int code) {
- upb_status_seterrcode(this, space, code);
-}
-inline void Status::Clear() { upb_status_clear(this); }
-inline void Status::CopyFrom(const Status& other) {
- upb_status_copy(this, &other);
-}
+ private:
+ UPB_DISALLOW_COPY_AND_ASSIGN(InlinedEnvironment)
+
+ char initial_block_[N + UPB_ARENA_BLOCK_OVERHEAD];
+};
+
+#endif /* __cplusplus */
-} /* namespace upb */
-#endif
#endif /* UPB_H_ */
@@ -607,10 +826,14 @@ typedef struct {
#endif
/* Like strdup(), which isn't always available since it's not ANSI C. */
-char *upb_strdup(const char *s);
+char *upb_strdup(const char *s, upb_alloc *a);
/* Variant that works with a length-delimited rather than NULL-delimited string,
* as supported by strtable. */
-char *upb_strdup2(const char *s, size_t len);
+char *upb_strdup2(const char *s, size_t len, upb_alloc *a);
+
+UPB_INLINE char *upb_gstrdup(const char *s) {
+ return upb_strdup(s, &upb_alloc_global);
+}
UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val,
upb_ctype_t ctype) {
@@ -643,7 +866,7 @@ UPB_INLINE upb_value _upb_value_val(uint64_t val, upb_ctype_t ctype) {
return ret; \
} \
UPB_INLINE type_t upb_value_get ## name(upb_value val) { \
- assert(val.ctype == proto_type); \
+ UPB_ASSERT_DEBUGVAR(val.ctype == proto_type); \
return (type_t)(converter)val.val; \
}
@@ -787,14 +1010,40 @@ typedef struct {
* initialize const hash tables. Then we cast away const when we have to.
*/
const upb_tabent *entries;
+
+#ifndef NDEBUG
+ /* This table's allocator. We make the user pass it in to every relevant
+ * function and only use this to check it in debug mode. We do this solely
+ * to keep upb_table as small as possible. This might seem slightly paranoid
+ * but the plan is to use upb_table for all map fields and extension sets in
+ * a forthcoming message representation, so there could be a lot of these.
+ * If this turns out to be too annoying later, we can change it (since this
+ * is an internal-only header file). */
+ upb_alloc *alloc;
+#endif
} upb_table;
+#ifdef NDEBUG
+# define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \
+ {count, mask, ctype, size_lg2, entries}
+#else
+# ifdef UPB_DEBUG_REFS
+/* At the moment the only mutable tables we statically initialize are debug
+ * ref tables. */
+# define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \
+ {count, mask, ctype, size_lg2, entries, &upb_alloc_debugrefs}
+# else
+# define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \
+ {count, mask, ctype, size_lg2, entries, NULL}
+# endif
+#endif
+
typedef struct {
upb_table t;
} upb_strtable;
#define UPB_STRTABLE_INIT(count, mask, ctype, size_lg2, entries) \
- {{count, mask, ctype, size_lg2, entries}}
+ {UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries)}
#define UPB_EMPTY_STRTABLE_INIT(ctype) \
UPB_STRTABLE_INIT(0, 0, ctype, 0, NULL)
@@ -807,7 +1056,7 @@ typedef struct {
} upb_inttable;
#define UPB_INTTABLE_INIT(count, mask, ctype, size_lg2, ent, a, asize, acount) \
- {{count, mask, ctype, size_lg2, ent}, a, asize, acount}
+ {UPB_TABLE_INIT(count, mask, ctype, size_lg2, ent), a, asize, acount}
#define UPB_EMPTY_INTTABLE_INIT(ctype) \
UPB_INTTABLE_INIT(0, 0, ctype, 0, NULL, NULL, 0, 0)
@@ -847,10 +1096,26 @@ UPB_INLINE bool upb_arrhas(upb_tabval key) {
/* Initialize and uninitialize a table, respectively. If memory allocation
* failed, false is returned that the table is uninitialized. */
-bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype);
-bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype);
-void upb_inttable_uninit(upb_inttable *table);
-void upb_strtable_uninit(upb_strtable *table);
+bool upb_inttable_init2(upb_inttable *table, upb_ctype_t ctype, upb_alloc *a);
+bool upb_strtable_init2(upb_strtable *table, upb_ctype_t ctype, upb_alloc *a);
+void upb_inttable_uninit2(upb_inttable *table, upb_alloc *a);
+void upb_strtable_uninit2(upb_strtable *table, upb_alloc *a);
+
+UPB_INLINE bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype) {
+ return upb_inttable_init2(table, ctype, &upb_alloc_global);
+}
+
+UPB_INLINE bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype) {
+ return upb_strtable_init2(table, ctype, &upb_alloc_global);
+}
+
+UPB_INLINE void upb_inttable_uninit(upb_inttable *table) {
+ upb_inttable_uninit2(table, &upb_alloc_global);
+}
+
+UPB_INLINE void upb_strtable_uninit(upb_strtable *table) {
+ upb_strtable_uninit2(table, &upb_alloc_global);
+}
/* Returns the number of values in the table. */
size_t upb_inttable_count(const upb_inttable *t);
@@ -865,9 +1130,20 @@ UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) {
*
* If a table resize was required but memory allocation failed, false is
* returned and the table is unchanged. */
-bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val);
-bool upb_strtable_insert2(upb_strtable *t, const char *key, size_t len,
- upb_value val);
+bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
+ upb_alloc *a);
+bool upb_strtable_insert3(upb_strtable *t, const char *key, size_t len,
+ upb_value val, upb_alloc *a);
+
+UPB_INLINE bool upb_inttable_insert(upb_inttable *t, uintptr_t key,
+ upb_value val) {
+ return upb_inttable_insert2(t, key, val, &upb_alloc_global);
+}
+
+UPB_INLINE bool upb_strtable_insert2(upb_strtable *t, const char *key,
+ size_t len, upb_value val) {
+ return upb_strtable_insert3(t, key, len, val, &upb_alloc_global);
+}
/* For NULL-terminated strings. */
UPB_INLINE bool upb_strtable_insert(upb_strtable *t, const char *key,
@@ -890,8 +1166,13 @@ UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key,
/* Removes an item from the table. Returns true if the remove was successful,
* and stores the removed item in *val if non-NULL. */
bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val);
-bool upb_strtable_remove2(upb_strtable *t, const char *key, size_t len,
- upb_value *val);
+bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
+ upb_value *val, upb_alloc *alloc);
+
+UPB_INLINE bool upb_strtable_remove2(upb_strtable *t, const char *key,
+ size_t len, upb_value *val) {
+ return upb_strtable_remove3(t, key, len, val, &upb_alloc_global);
+}
/* For NULL-terminated strings. */
UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key,
@@ -906,19 +1187,33 @@ bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val);
/* Handy routines for treating an inttable like a stack. May not be mixed with
* other insert/remove calls. */
-bool upb_inttable_push(upb_inttable *t, upb_value val);
+bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a);
upb_value upb_inttable_pop(upb_inttable *t);
+UPB_INLINE bool upb_inttable_push(upb_inttable *t, upb_value val) {
+ return upb_inttable_push2(t, val, &upb_alloc_global);
+}
+
/* Convenience routines for inttables with pointer keys. */
-bool upb_inttable_insertptr(upb_inttable *t, const void *key, upb_value val);
+bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
+ upb_alloc *a);
bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val);
bool upb_inttable_lookupptr(
const upb_inttable *t, const void *key, upb_value *val);
+UPB_INLINE bool upb_inttable_insertptr(upb_inttable *t, const void *key,
+ upb_value val) {
+ return upb_inttable_insertptr2(t, key, val, &upb_alloc_global);
+}
+
/* Optimizes the table for the current set of entries, for both memory use and
* lookup time. Client should call this after all entries have been inserted;
* inserting more entries is legal, but will likely require a table resize. */
-void upb_inttable_compact(upb_inttable *t);
+void upb_inttable_compact2(upb_inttable *t, upb_alloc *a);
+
+UPB_INLINE void upb_inttable_compact(upb_inttable *t) {
+ upb_inttable_compact2(t, &upb_alloc_global);
+}
/* A special-case inlinable version of the lookup routine for 32-bit
* integers. */
@@ -947,7 +1242,7 @@ UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key,
}
/* Exposed for testing only. */
-bool upb_strtable_resize(upb_strtable *t, size_t size_lg2);
+bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a);
/* Iterators ******************************************************************/
@@ -992,8 +1287,8 @@ typedef struct {
void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t);
void upb_strtable_next(upb_strtable_iter *i);
bool upb_strtable_done(const upb_strtable_iter *i);
-const char *upb_strtable_iter_key(upb_strtable_iter *i);
-size_t upb_strtable_iter_keylength(upb_strtable_iter *i);
+const char *upb_strtable_iter_key(const upb_strtable_iter *i);
+size_t upb_strtable_iter_keylength(const upb_strtable_iter *i);
upb_value upb_strtable_iter_value(const upb_strtable_iter *i);
void upb_strtable_iter_setdone(upb_strtable_iter *i);
bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
@@ -1046,7 +1341,10 @@ bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
/* #define UPB_DEBUG_REFS */
#ifdef __cplusplus
-namespace upb { class RefCounted; }
+namespace upb {
+class RefCounted;
+template <class T> class reffed_ptr;
+}
#endif
UPB_DECLARE_TYPE(upb::RefCounted, upb_refcounted)
@@ -1114,10 +1412,12 @@ struct upb_refcounted {
};
#ifdef UPB_DEBUG_REFS
-#define UPB_REFCOUNT_INIT(refs, ref2s) \
- {&static_refcount, NULL, NULL, 0, true, refs, ref2s}
+extern upb_alloc upb_alloc_debugrefs;
+#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \
+ {&static_refcount, NULL, vtbl, 0, true, refs, ref2s}
#else
-#define UPB_REFCOUNT_INIT(refs, ref2s) {&static_refcount, NULL, NULL, 0, true}
+#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \
+ {&static_refcount, NULL, vtbl, 0, true}
#endif
UPB_BEGIN_EXTERN_C
@@ -1250,6 +1550,111 @@ inline void RefCounted::CheckRef(const void *owner) const {
} /* namespace upb */
#endif
+
+/* upb::reffed_ptr ************************************************************/
+
+#ifdef __cplusplus
+
+#include <algorithm> /* For std::swap(). */
+
+/* Provides RAII semantics for upb refcounted objects. Each reffed_ptr owns a
+ * ref on whatever object it points to (if any). */
+template <class T> class upb::reffed_ptr {
+ public:
+ reffed_ptr() : ptr_(NULL) {}
+
+ /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */
+ template <class U>
+ reffed_ptr(U* val, const void* ref_donor = NULL)
+ : ptr_(upb::upcast(val)) {
+ if (ref_donor) {
+ UPB_ASSERT(ptr_);
+ ptr_->DonateRef(ref_donor, this);
+ } else if (ptr_) {
+ ptr_->Ref(this);
+ }
+ }
+
+ template <class U>
+ reffed_ptr(const reffed_ptr<U>& other)
+ : ptr_(upb::upcast(other.get())) {
+ if (ptr_) ptr_->Ref(this);
+ }
+
+ reffed_ptr(const reffed_ptr& other)
+ : ptr_(upb::upcast(other.get())) {
+ if (ptr_) ptr_->Ref(this);
+ }
+
+ ~reffed_ptr() { if (ptr_) ptr_->Unref(this); }
+
+ template <class U>
+ reffed_ptr& operator=(const reffed_ptr<U>& other) {
+ reset(other.get());
+ return *this;
+ }
+
+ reffed_ptr& operator=(const reffed_ptr& other) {
+ reset(other.get());
+ return *this;
+ }
+
+ /* TODO(haberman): add C++11 move construction/assignment for greater
+ * efficiency. */
+
+ void swap(reffed_ptr& other) {
+ if (ptr_ == other.ptr_) {
+ return;
+ }
+
+ if (ptr_) ptr_->DonateRef(this, &other);
+ if (other.ptr_) other.ptr_->DonateRef(&other, this);
+ std::swap(ptr_, other.ptr_);
+ }
+
+ T& operator*() const {
+ UPB_ASSERT(ptr_);
+ return *ptr_;
+ }
+
+ T* operator->() const {
+ UPB_ASSERT(ptr_);
+ return ptr_;
+ }
+
+ T* get() const { return ptr_; }
+
+ /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */
+ template <class U>
+ void reset(U* ptr = NULL, const void* ref_donor = NULL) {
+ reffed_ptr(ptr, ref_donor).swap(*this);
+ }
+
+ template <class U>
+ reffed_ptr<U> down_cast() {
+ return reffed_ptr<U>(upb::down_cast<U*>(get()));
+ }
+
+ template <class U>
+ reffed_ptr<U> dyn_cast() {
+ return reffed_ptr<U>(upb::dyn_cast<U*>(get()));
+ }
+
+ /* Plain release() is unsafe; if we were the only owner, it would leak the
+ * object. Instead we provide this: */
+ T* ReleaseTo(const void* new_owner) {
+ T* ret = NULL;
+ ptr_->DonateRef(this, new_owner);
+ std::swap(ret, ptr_);
+ return ret;
+ }
+
+ private:
+ T* ptr_;
+};
+
+#endif /* __cplusplus */
+
#endif /* UPB_REFCOUNT_H_ */
#ifdef __cplusplus
@@ -1261,12 +1666,17 @@ namespace upb {
class Def;
class EnumDef;
class FieldDef;
+class FileDef;
class MessageDef;
class OneofDef;
}
#endif
UPB_DECLARE_DERIVED_TYPE(upb::Def, upb::RefCounted, upb_def, upb_refcounted)
+UPB_DECLARE_DERIVED_TYPE(upb::OneofDef, upb::RefCounted, upb_oneofdef,
+ upb_refcounted)
+UPB_DECLARE_DERIVED_TYPE(upb::FileDef, upb::RefCounted, upb_filedef,
+ upb_refcounted)
/* The maximum message depth that the type graph can have. This is a resource
* limit for the C stack since we sometimes need to recursively traverse the
@@ -1278,15 +1688,16 @@ UPB_DECLARE_DERIVED_TYPE(upb::Def, upb::RefCounted, upb_def, upb_refcounted)
#define UPB_MAX_MESSAGE_DEPTH 64
-/* upb::Def: base class for defs *********************************************/
+/* upb::Def: base class for top-level defs ***********************************/
-/* All the different kind of defs we support. These correspond 1:1 with
- * declarations in a .proto file. */
+/* All the different kind of defs that can be defined at the top-level and put
+ * in a SymbolTable or appear in a FileDef::defs() list. This excludes some
+ * defs (like oneofs and files). It only includes fields because they can be
+ * defined as extensions. */
typedef enum {
UPB_DEF_MSG,
UPB_DEF_FIELD,
UPB_DEF_ENUM,
- UPB_DEF_ONEOF,
UPB_DEF_SERVICE, /* Not yet implemented. */
UPB_DEF_ANY = -1 /* Wildcard for upb_symtab_get*() */
} upb_deftype_t;
@@ -1309,6 +1720,9 @@ class upb::Def {
/* "fullname" is the def's fully-qualified name (eg. foo.bar.Message). */
const char *full_name() const;
+ /* The final part of a def's name (eg. Message). */
+ const char *name() const;
+
/* The def must be mutable. Caller retains ownership of fullname. Defs are
* not required to have a name; if a def has no name when it is frozen, it
* will remain an anonymous def. On failure, returns false and details in "s"
@@ -1316,6 +1730,11 @@ class upb::Def {
bool set_full_name(const char* fullname, upb::Status* s);
bool set_full_name(const std::string &fullname, upb::Status* s);
+ /* The file in which this def appears. It is not necessary to add a def to a
+ * file (and consequently the accessor may return NULL). Set this by calling
+ * file->Add(def). */
+ FileDef* file() const;
+
/* Freezes the given defs; this validates all constraints and marks the defs
* as frozen (read-only). "defs" may not contain any fielddefs, but fields
* of any msgdefs will be frozen.
@@ -1327,7 +1746,7 @@ class upb::Def {
*
* After this operation succeeds, the finalized defs must only be accessed
* through a const pointer! */
- static bool Freeze(Def* const* defs, int n, Status* status);
+ static bool Freeze(Def* const* defs, size_t n, Status* status);
static bool Freeze(const std::vector<Def*>& defs, Status* status);
private:
@@ -1346,8 +1765,13 @@ UPB_REFCOUNTED_CMETHODS(upb_def, upb_def_upcast)
upb_deftype_t upb_def_type(const upb_def *d);
const char *upb_def_fullname(const upb_def *d);
+const char *upb_def_name(const upb_def *d);
+const upb_filedef *upb_def_file(const upb_def *d);
bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s);
-bool upb_def_freeze(upb_def *const *defs, int n, upb_status *s);
+bool upb_def_freeze(upb_def *const *defs, size_t n, upb_status *s);
+
+/* Temporary API: for internal use only. */
+bool _upb_def_validate(upb_def *const*defs, size_t n, upb_status *s);
UPB_END_EXTERN_C
@@ -1396,7 +1820,7 @@ UPB_END_EXTERN_C
return (upb_##lower *)def; \
} \
UPB_INLINE const upb_##lower *upb_downcast_##lower(const upb_def *def) { \
- assert(upb_def_type(def) == UPB_DEF_##upper); \
+ UPB_ASSERT(upb_def_type(def) == UPB_DEF_##upper); \
return (const upb_##lower *)def; \
} \
UPB_INLINE upb_##lower *upb_dyncast_##lower##_mutable(upb_def *def) { \
@@ -1420,7 +1844,6 @@ UPB_END_EXTERN_C
UPB_DECLARE_DEF_TYPE(upb::FieldDef, fielddef, FIELD)
UPB_DECLARE_DEF_TYPE(upb::MessageDef, msgdef, MSG)
UPB_DECLARE_DEF_TYPE(upb::EnumDef, enumdef, ENUM)
-UPB_DECLARE_DEF_TYPE(upb::OneofDef, oneofdef, ONEOF)
#undef UPB_DECLARE_DEF_TYPE
#undef UPB_DEF_CASTS
@@ -1483,6 +1906,11 @@ typedef enum {
UPB_DESCRIPTOR_TYPE_SINT64 = 18
} upb_descriptortype_t;
+typedef enum {
+ UPB_SYNTAX_PROTO2 = 2,
+ UPB_SYNTAX_PROTO3 = 3
+} upb_syntax_t;
+
/* Maximum field number allowed for FieldDefs. This is an inherent limit of the
* protobuf wire format. */
#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
@@ -1537,6 +1965,27 @@ class upb::FieldDef {
uint32_t number() const; /* Returns 0 if uninitialized. */
bool is_extension() const;
+ /* Copies the JSON name for this field into the given buffer. Returns the
+ * actual size of the JSON name, including the NULL terminator. If the
+ * return value is 0, the JSON name is unset. If the return value is
+ * greater than len, the JSON name was truncated. The buffer is always
+ * NULL-terminated if len > 0.
+ *
+ * The JSON name always defaults to a camelCased version of the regular
+ * name. However if the regular name is unset, the JSON name will be unset
+ * also.
+ */
+ size_t GetJsonName(char* buf, size_t len) const;
+
+ /* Convenience version of the above function which copies the JSON name
+ * into the given string, returning false if the name is not set. */
+ template <class T>
+ bool GetJsonName(T* str) {
+ str->resize(GetJsonName(NULL, 0));
+ GetJsonName(&(*str)[0], str->size());
+ return str->size() > 0;
+ }
+
/* For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false,
* indicates whether this field should have lazy parsing handlers that yield
* the unparsed string for the submessage.
@@ -1557,7 +2006,7 @@ class upb::FieldDef {
* whatever message this field belongs to. Guaranteed to be less than
* f->containing_type()->field_count(). May only be accessed once the def has
* been finalized. */
- int index() const;
+ uint32_t index() const;
/* The MessageDef to which this field belongs.
*
@@ -1589,6 +2038,18 @@ class upb::FieldDef {
bool IsPrimitive() const;
bool IsMap() const;
+ /* Whether this field must be able to explicitly represent presence:
+ *
+ * * This is always false for repeated fields (an empty repeated field is
+ * equivalent to a repeated field with zero entries).
+ *
+ * * This is always true for submessages.
+ *
+ * * For other fields, it depends on the message (see
+ * MessageDef::SetPrimitivesHavePresence())
+ */
+ bool HasPresence() const;
+
/* How integers are encoded. Only meaningful for integer types.
* Defaults to UPB_INTFMT_VARIABLE, and is reset when "type" changes. */
IntegerFormat integer_format() const;
@@ -1690,6 +2151,16 @@ class upb::FieldDef {
bool set_name(const char* name, upb::Status* s);
bool set_name(const std::string& name, upb::Status* s);
+ /* Sets the JSON name to the given string. */
+ /* TODO(haberman): implement. Right now only default json_name (camelCase)
+ * is supported. */
+ bool set_json_name(const char* json_name, upb::Status* s);
+ bool set_json_name(const std::string& name, upb::Status* s);
+
+ /* Clears the JSON name. This will make it revert to its default, which is
+ * a camelCased version of the regular field name. */
+ void clear_json_name();
+
void set_integer_format(IntegerFormat format);
bool set_tag_delimited(bool tag_delimited, upb::Status* s);
@@ -1754,6 +2225,7 @@ const char *upb_fielddef_name(const upb_fielddef *f);
bool upb_fielddef_isextension(const upb_fielddef *f);
bool upb_fielddef_lazy(const upb_fielddef *f);
bool upb_fielddef_packed(const upb_fielddef *f);
+size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len);
const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f);
const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f);
upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f);
@@ -1766,6 +2238,7 @@ bool upb_fielddef_isstring(const upb_fielddef *f);
bool upb_fielddef_isseq(const upb_fielddef *f);
bool upb_fielddef_isprimitive(const upb_fielddef *f);
bool upb_fielddef_ismap(const upb_fielddef *f);
+bool upb_fielddef_haspresence(const upb_fielddef *f);
int64_t upb_fielddef_defaultint64(const upb_fielddef *f);
int32_t upb_fielddef_defaultint32(const upb_fielddef *f);
uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f);
@@ -1787,6 +2260,8 @@ void upb_fielddef_setdescriptortype(upb_fielddef *f, int type);
void upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label);
bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s);
bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s);
+bool upb_fielddef_setjsonname(upb_fielddef *f, const char *name, upb_status *s);
+bool upb_fielddef_clearjsonname(upb_fielddef *f);
bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name,
upb_status *s);
void upb_fielddef_setisextension(upb_fielddef *f, bool is_extension);
@@ -1827,6 +2302,10 @@ UPB_END_EXTERN_C
typedef upb_inttable_iter upb_msg_field_iter;
typedef upb_strtable_iter upb_msg_oneof_iter;
+/* Well-known field tag numbers for map-entry messages. */
+#define UPB_MAPENTRY_KEY 1
+#define UPB_MAPENTRY_VALUE 2
+
#ifdef __cplusplus
/* Structure that describes a single .proto message type.
@@ -1842,6 +2321,7 @@ class upb::MessageDef {
/* Functionality from upb::Def. */
const char* full_name() const;
+ const char* name() const;
bool set_full_name(const char* fullname, Status* s);
bool set_full_name(const std::string& fullname, Status* s);
@@ -1884,6 +2364,16 @@ class upb::MessageDef {
bool AddOneof(OneofDef* o, Status* s);
bool AddOneof(const reffed_ptr<OneofDef>& o, Status* s);
+ upb_syntax_t syntax() const;
+
+ /* Returns false if we don't support this syntax value. */
+ bool set_syntax(upb_syntax_t syntax);
+
+ /* Set this to false to indicate that primitive fields should not have
+ * explicit presence information associated with them. This will affect all
+ * fields added to this message. Defaults to true. */
+ void SetPrimitivesHavePresence(bool have_presence);
+
/* These return NULL if the field is not found. */
FieldDef* FindFieldByNumber(uint32_t number);
FieldDef* FindFieldByName(const char *name, size_t len);
@@ -2069,14 +2559,20 @@ UPB_REFCOUNTED_CMETHODS(upb_msgdef, upb_msgdef_upcast2)
bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status);
+upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner);
const char *upb_msgdef_fullname(const upb_msgdef *m);
-bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, upb_status *s);
+const char *upb_msgdef_name(const upb_msgdef *m);
+int upb_msgdef_numoneofs(const upb_msgdef *m);
+upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m);
-upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner);
bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor,
upb_status *s);
bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
upb_status *s);
+bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, upb_status *s);
+void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry);
+bool upb_msgdef_mapentry(const upb_msgdef *m);
+bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax);
/* Field lookup in a couple of different variations:
* - itof = int to field
@@ -2118,18 +2614,21 @@ UPB_INLINE upb_oneofdef *upb_msgdef_ntoo_mutable(upb_msgdef *m,
return (upb_oneofdef *)upb_msgdef_ntoo(m, name, len);
}
-void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry);
-bool upb_msgdef_mapentry(const upb_msgdef *m);
+/* Lookup of either field or oneof by name. Returns whether either was found.
+ * If the return is true, then the found def will be set, and the non-found
+ * one set to NULL. */
+bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
+ const upb_fielddef **f, const upb_oneofdef **o);
-/* Well-known field tag numbers for map-entry messages. */
-#define UPB_MAPENTRY_KEY 1
-#define UPB_MAPENTRY_VALUE 2
-
-const upb_oneofdef *upb_msgdef_findoneof(const upb_msgdef *m,
- const char *name);
-int upb_msgdef_numoneofs(const upb_msgdef *m);
+UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name,
+ const upb_fielddef **f,
+ const upb_oneofdef **o) {
+ return upb_msgdef_lookupname(m, name, strlen(name), f, o);
+}
-/* upb_msg_field_iter i;
+/* Iteration over fields and oneofs. For example:
+ *
+ * upb_msg_field_iter i;
* for(upb_msg_field_begin(&i, m);
* !upb_msg_field_done(&i);
* upb_msg_field_next(&i)) {
@@ -2175,6 +2674,7 @@ class upb::EnumDef {
/* Functionality from upb::Def. */
const char* full_name() const;
+ const char* name() const;
bool set_full_name(const char* fullname, Status* s);
bool set_full_name(const std::string& fullname, Status* s);
@@ -2249,6 +2749,7 @@ bool upb_enumdef_freeze(upb_enumdef *e, upb_status *status);
/* From upb_def. */
const char *upb_enumdef_fullname(const upb_enumdef *e);
+const char *upb_enumdef_name(const upb_enumdef *e);
bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname,
upb_status *s);
@@ -2290,8 +2791,7 @@ typedef upb_inttable_iter upb_oneof_iter;
#ifdef __cplusplus
-/* Class that represents a oneof. Its base class is upb::Def (convert with
- * upb::upcast()). */
+/* Class that represents a oneof. */
class upb::OneofDef {
public:
/* Returns NULL if memory allocation failed. */
@@ -2300,9 +2800,6 @@ class upb::OneofDef {
/* upb::RefCounted methods like Ref()/Unref(). */
UPB_REFCOUNTED_CPPMETHODS
- /* Functionality from upb::Def. */
- const char* full_name() const;
-
/* Returns the MessageDef that owns this OneofDef. */
const MessageDef* containing_type() const;
@@ -2310,6 +2807,7 @@ class upb::OneofDef {
* by name once added to a message def. */
const char* name() const;
bool set_name(const char* name, Status* s);
+ bool set_name(const std::string& name, Status* s);
/* Returns the number of fields currently defined in the oneof. */
int field_count() const;
@@ -2403,7 +2901,7 @@ upb_oneofdef *upb_oneofdef_new(const void *owner);
upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner);
/* Include upb_refcounted methods like upb_oneofdef_ref(). */
-UPB_REFCOUNTED_CMETHODS(upb_oneofdef, upb_oneofdef_upcast2)
+UPB_REFCOUNTED_CMETHODS(upb_oneofdef, upb_oneofdef_upcast)
const char *upb_oneofdef_name(const upb_oneofdef *o);
bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s);
@@ -2439,10 +2937,124 @@ void upb_oneof_iter_setdone(upb_oneof_iter *iter);
UPB_END_EXTERN_C
+
+/* upb::FileDef ***************************************************************/
+
+#ifdef __cplusplus
+
+/* Class that represents a .proto file with some things defined in it.
+ *
+ * Many users won't care about FileDefs, but they are necessary if you want to
+ * read the values of file-level options. */
+class upb::FileDef {
+ public:
+ /* Returns NULL if memory allocation failed. */
+ static reffed_ptr<FileDef> New();
+
+ /* upb::RefCounted methods like Ref()/Unref(). */
+ UPB_REFCOUNTED_CPPMETHODS
+
+ /* Get/set name of the file (eg. "foo/bar.proto"). */
+ const char* name() const;
+ bool set_name(const char* name, Status* s);
+ bool set_name(const std::string& name, Status* s);
+
+ /* Package name for definitions inside the file (eg. "foo.bar"). */
+ const char* package() const;
+ bool set_package(const char* package, Status* s);
+
+ /* Syntax for the file. Defaults to proto2. */
+ upb_syntax_t syntax() const;
+ void set_syntax(upb_syntax_t syntax);
+
+ /* Get the list of defs from the file. These are returned in the order that
+ * they were added to the FileDef. */
+ int def_count() const;
+ const Def* def(int index) const;
+ Def* def(int index);
+
+ /* Get the list of dependencies from the file. These are returned in the
+ * order that they were added to the FileDef. */
+ int dependency_count() const;
+ const FileDef* dependency(int index) const;
+
+ /* Adds defs to this file. The def must not already belong to another
+ * file.
+ *
+ * Note: this does *not* ensure that this def's name is unique in this file!
+ * Use a SymbolTable if you want to check this property. Especially since
+ * properly checking uniqueness would require a check across *all* files
+ * (including dependencies). */
+ bool AddDef(Def* def, Status* s);
+ bool AddMessage(MessageDef* m, Status* s);
+ bool AddEnum(EnumDef* e, Status* s);
+ bool AddExtension(FieldDef* f, Status* s);
+
+ /* Adds a dependency of this file. */
+ bool AddDependency(const FileDef* file);
+
+ /* Freezes this FileDef and all messages/enums under it. All subdefs must be
+ * resolved and all messages/enums must validate. Returns true if this
+ * succeeded.
+ *
+ * TODO(haberman): should we care whether the file's dependencies are frozen
+ * already? */
+ bool Freeze(Status* s);
+
+ private:
+ UPB_DISALLOW_POD_OPS(FileDef, upb::FileDef)
+};
+
+#endif
+
+UPB_BEGIN_EXTERN_C
+
+upb_filedef *upb_filedef_new(const void *owner);
+
+/* Include upb_refcounted methods like upb_msgdef_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_filedef, upb_filedef_upcast)
+
+const char *upb_filedef_name(const upb_filedef *f);
+const char *upb_filedef_package(const upb_filedef *f);
+upb_syntax_t upb_filedef_syntax(const upb_filedef *f);
+size_t upb_filedef_defcount(const upb_filedef *f);
+size_t upb_filedef_depcount(const upb_filedef *f);
+const upb_def *upb_filedef_def(const upb_filedef *f, size_t i);
+const upb_filedef *upb_filedef_dep(const upb_filedef *f, size_t i);
+
+bool upb_filedef_freeze(upb_filedef *f, upb_status *s);
+bool upb_filedef_setname(upb_filedef *f, const char *name, upb_status *s);
+bool upb_filedef_setpackage(upb_filedef *f, const char *package, upb_status *s);
+bool upb_filedef_setsyntax(upb_filedef *f, upb_syntax_t syntax, upb_status *s);
+
+bool upb_filedef_adddef(upb_filedef *f, upb_def *def, const void *ref_donor,
+ upb_status *s);
+bool upb_filedef_adddep(upb_filedef *f, const upb_filedef *dep);
+
+UPB_INLINE bool upb_filedef_addmsg(upb_filedef *f, upb_msgdef *m,
+ const void *ref_donor, upb_status *s) {
+ return upb_filedef_adddef(f, upb_msgdef_upcast_mutable(m), ref_donor, s);
+}
+
+UPB_INLINE bool upb_filedef_addenum(upb_filedef *f, upb_enumdef *e,
+ const void *ref_donor, upb_status *s) {
+ return upb_filedef_adddef(f, upb_enumdef_upcast_mutable(e), ref_donor, s);
+}
+
+UPB_INLINE bool upb_filedef_addext(upb_filedef *file, upb_fielddef *f,
+ const void *ref_donor, upb_status *s) {
+ return upb_filedef_adddef(file, upb_fielddef_upcast_mutable(f), ref_donor, s);
+}
+UPB_INLINE upb_def *upb_filedef_mutabledef(upb_filedef *f, int i) {
+ return (upb_def*)upb_filedef_def(f, i);
+}
+
+UPB_END_EXTERN_C
+
#ifdef __cplusplus
UPB_INLINE const char* upb_safecstr(const std::string& str) {
- assert(str.size() == std::strlen(str.c_str()));
+ UPB_ASSERT(str.size() == std::strlen(str.c_str()));
return str.c_str();
}
@@ -2454,13 +3066,14 @@ inline Def* Def::Dup(const void* owner) const {
}
inline Def::Type Def::def_type() const { return upb_def_type(this); }
inline const char* Def::full_name() const { return upb_def_fullname(this); }
+inline const char* Def::name() const { return upb_def_name(this); }
inline bool Def::set_full_name(const char* fullname, Status* s) {
return upb_def_setfullname(this, fullname, s);
}
inline bool Def::set_full_name(const std::string& fullname, Status* s) {
return upb_def_setfullname(this, upb_safecstr(fullname), s);
}
-inline bool Def::Freeze(Def* const* defs, int n, Status* status) {
+inline bool Def::Freeze(Def* const* defs, size_t n, Status* status) {
return upb_def_freeze(defs, n, status);
}
inline bool Def::Freeze(const std::vector<Def*>& defs, Status* status) {
@@ -2480,19 +3093,19 @@ inline bool FieldDef::CheckIntegerFormat(int32_t val) {
return upb_fielddef_checkintfmt(val);
}
inline FieldDef::Type FieldDef::ConvertType(int32_t val) {
- assert(CheckType(val));
+ UPB_ASSERT(CheckType(val));
return static_cast<FieldDef::Type>(val);
}
inline FieldDef::Label FieldDef::ConvertLabel(int32_t val) {
- assert(CheckLabel(val));
+ UPB_ASSERT(CheckLabel(val));
return static_cast<FieldDef::Label>(val);
}
inline FieldDef::DescriptorType FieldDef::ConvertDescriptorType(int32_t val) {
- assert(CheckDescriptorType(val));
+ UPB_ASSERT(CheckDescriptorType(val));
return static_cast<FieldDef::DescriptorType>(val);
}
inline FieldDef::IntegerFormat FieldDef::ConvertIntegerFormat(int32_t val) {
- assert(CheckIntegerFormat(val));
+ UPB_ASSERT(CheckIntegerFormat(val));
return static_cast<FieldDef::IntegerFormat>(val);
}
@@ -2527,6 +3140,9 @@ inline const char* FieldDef::name() const { return upb_fielddef_name(this); }
inline bool FieldDef::is_extension() const {
return upb_fielddef_isextension(this);
}
+inline size_t FieldDef::GetJsonName(char* buf, size_t len) const {
+ return upb_fielddef_getjsonname(this, buf, len);
+}
inline bool FieldDef::lazy() const {
return upb_fielddef_lazy(this);
}
@@ -2536,6 +3152,9 @@ inline void FieldDef::set_lazy(bool lazy) {
inline bool FieldDef::packed() const {
return upb_fielddef_packed(this);
}
+inline uint32_t FieldDef::index() const {
+ return upb_fielddef_index(this);
+}
inline void FieldDef::set_packed(bool packed) {
upb_fielddef_setpacked(this, packed);
}
@@ -2557,6 +3176,15 @@ inline bool FieldDef::set_name(const char *name, Status* s) {
inline bool FieldDef::set_name(const std::string& name, Status* s) {
return upb_fielddef_setname(this, upb_safecstr(name), s);
}
+inline bool FieldDef::set_json_name(const char *name, Status* s) {
+ return upb_fielddef_setjsonname(this, name, s);
+}
+inline bool FieldDef::set_json_name(const std::string& name, Status* s) {
+ return upb_fielddef_setjsonname(this, upb_safecstr(name), s);
+}
+inline void FieldDef::clear_json_name() {
+ upb_fielddef_clearjsonname(this);
+}
inline bool FieldDef::set_containing_type_name(const char *name, Status* s) {
return upb_fielddef_setcontainingtypename(this, name, s);
}
@@ -2671,12 +3299,21 @@ inline reffed_ptr<MessageDef> MessageDef::New() {
inline const char *MessageDef::full_name() const {
return upb_msgdef_fullname(this);
}
+inline const char *MessageDef::name() const {
+ return upb_msgdef_name(this);
+}
+inline upb_syntax_t MessageDef::syntax() const {
+ return upb_msgdef_syntax(this);
+}
inline bool MessageDef::set_full_name(const char* fullname, Status* s) {
return upb_msgdef_setfullname(this, fullname, s);
}
inline bool MessageDef::set_full_name(const std::string& fullname, Status* s) {
return upb_msgdef_setfullname(this, upb_safecstr(fullname), s);
}
+inline bool MessageDef::set_syntax(upb_syntax_t syntax) {
+ return upb_msgdef_setsyntax(this, syntax);
+}
inline bool MessageDef::Freeze(Status* status) {
return upb_msgdef_freeze(this, status);
}
@@ -2858,6 +3495,9 @@ inline reffed_ptr<EnumDef> EnumDef::New() {
inline const char* EnumDef::full_name() const {
return upb_enumdef_fullname(this);
}
+inline const char* EnumDef::name() const {
+ return upb_enumdef_name(this);
+}
inline bool EnumDef::set_full_name(const char* fullname, Status* s) {
return upb_enumdef_setfullname(this, fullname, s);
}
@@ -2907,9 +3547,6 @@ inline reffed_ptr<OneofDef> OneofDef::New() {
upb_oneofdef *o = upb_oneofdef_new(&o);
return reffed_ptr<OneofDef>(o, &o);
}
-inline const char* OneofDef::full_name() const {
- return upb_oneofdef_name(this);
-}
inline const MessageDef* OneofDef::containing_type() const {
return upb_oneofdef_containingtype(this);
@@ -2920,6 +3557,9 @@ inline const char* OneofDef::name() const {
inline bool OneofDef::set_name(const char* name, Status* s) {
return upb_oneofdef_setname(this, name, s);
}
+inline bool OneofDef::set_name(const std::string& name, Status* s) {
+ return upb_oneofdef_setname(this, upb_safecstr(name), s);
+}
inline int OneofDef::field_count() const {
return upb_oneofdef_numfields(this);
}
@@ -2988,6 +3628,57 @@ inline bool OneofDef::const_iterator::operator!=(
return !(*this == other);
}
+inline reffed_ptr<FileDef> FileDef::New() {
+ upb_filedef *f = upb_filedef_new(&f);
+ return reffed_ptr<FileDef>(f, &f);
+}
+
+inline const char* FileDef::name() const {
+ return upb_filedef_name(this);
+}
+inline bool FileDef::set_name(const char* name, Status* s) {
+ return upb_filedef_setname(this, name, s);
+}
+inline bool FileDef::set_name(const std::string& name, Status* s) {
+ return upb_filedef_setname(this, upb_safecstr(name), s);
+}
+inline const char* FileDef::package() const {
+ return upb_filedef_package(this);
+}
+inline bool FileDef::set_package(const char* package, Status* s) {
+ return upb_filedef_setpackage(this, package, s);
+}
+inline int FileDef::def_count() const {
+ return upb_filedef_defcount(this);
+}
+inline const Def* FileDef::def(int index) const {
+ return upb_filedef_def(this, index);
+}
+inline Def* FileDef::def(int index) {
+ return const_cast<Def*>(upb_filedef_def(this, index));
+}
+inline int FileDef::dependency_count() const {
+ return upb_filedef_depcount(this);
+}
+inline const FileDef* FileDef::dependency(int index) const {
+ return upb_filedef_dep(this, index);
+}
+inline bool FileDef::AddDef(Def* def, Status* s) {
+ return upb_filedef_adddef(this, def, NULL, s);
+}
+inline bool FileDef::AddMessage(MessageDef* m, Status* s) {
+ return upb_filedef_addmsg(this, m, NULL, s);
+}
+inline bool FileDef::AddEnum(EnumDef* e, Status* s) {
+ return upb_filedef_addenum(this, e, NULL, s);
+}
+inline bool FileDef::AddExtension(FieldDef* f, Status* s) {
+ return upb_filedef_addext(this, f, NULL, s);
+}
+inline bool FileDef::AddDependency(const FileDef* file) {
+ return upb_filedef_adddep(this, file);
+}
+
} /* namespace upb */
#endif
@@ -3026,6 +3717,7 @@ 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
@@ -3035,8 +3727,8 @@ struct upb_def {
bool came_from_user;
};
-#define UPB_DEF_INIT(name, type, refs, ref2s) \
- { UPB_REFCOUNT_INIT(refs, ref2s), name, type, false }
+#define UPB_DEF_INIT(name, type, vtbl, refs, ref2s) \
+ { UPB_REFCOUNT_INIT(vtbl, refs, ref2s), name, NULL, type, false }
/* upb_fielddef ***************************************************************/
@@ -3076,12 +3768,14 @@ struct upb_fielddef {
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, refs, ref2s), defaultval, {msgdef}, \
- {subdef}, NULL, false, false, \
+ 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 \
}
@@ -3097,27 +3791,26 @@ struct upb_msgdef {
/* Tables for looking up fields by number and name. */
upb_inttable itof; /* int to field */
- upb_strtable ntof; /* name to field */
+ upb_strtable ntof; /* name to field/oneof */
- /* Tables for looking up oneofs by name. */
- upb_strtable ntoo; /* name to oneof */
-
- /* Is this a map-entry message?
- * TODO: set this flag properly for static descriptors; regenerate
- * descriptor.upb.c. */
+ /* 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, \
- refs, ref2s) \
+ map_entry, syntax, refs, ref2s) \
{ \
- UPB_DEF_INIT(name, UPB_DEF_MSG, refs, ref2s), selector_count, \
- submsg_field_count, itof, ntof, \
- UPB_EMPTY_STRTABLE_INIT(UPB_CTYPE_PTR), false \
+ UPB_DEF_INIT(name, UPB_DEF_MSG, &upb_fielddef_vtbl, refs, ref2s), \
+ selector_count, submsg_field_count, itof, ntof, map_entry, syntax \
}
@@ -3131,22 +3824,28 @@ struct upb_enumdef {
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, refs, ref2s), ntoi, iton, defaultval }
+ { UPB_DEF_INIT(name, UPB_DEF_ENUM, &upb_enumdef_vtbl, refs, ref2s), ntoi, \
+ iton, defaultval }
/* upb_oneofdef ***************************************************************/
struct upb_oneofdef {
- upb_def base;
+ upb_refcounted base;
+ 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_DEF_INIT(name, UPB_DEF_ENUM, refs, ref2s), ntof, itof }
+ { UPB_REFCOUNT_INIT(&upb_oneofdef_vtbl, refs, ref2s), name, ntof, itof }
/* upb_symtab *****************************************************************/
@@ -3157,9 +3856,18 @@ struct upb_symtab {
upb_strtable symtab;
};
-#define UPB_SYMTAB_INIT(symtab, refs, ref2s) \
- { UPB_REFCOUNT_INIT(refs, ref2s), symtab }
+struct upb_filedef {
+ upb_refcounted base;
+ const char *name;
+ const char *package;
+ upb_syntax_t syntax;
+
+ upb_inttable defs;
+ upb_inttable deps;
+};
+
+extern const struct upb_refcounted_vtbl upb_filedef_vtbl;
#endif /* UPB_STATICINIT_H_ */
/*
@@ -3773,7 +4481,7 @@ template <class T> class Handler {
void AddCleanup(Handlers* h) const {
if (cleanup_func_) {
bool ok = h->AddCleanup(cleanup_data_, cleanup_func_);
- UPB_ASSERT_VAR(ok, ok);
+ UPB_ASSERT(ok);
}
}
@@ -4793,7 +5501,7 @@ struct ConvertParams<BoundFunc5<R, P1, P2, P3, P4, P5, F, I>, T> {
inline bool Handlers::SetValueHandler<vtype>( \
const FieldDef *f, \
const Handlers::utype ## Handler& handler) { \
- assert(!handler.registered_); \
+ UPB_ASSERT(!handler.registered_); \
handler.AddCleanup(this); \
handler.registered_ = true; \
return upb_handlers_set##ltype(this, f, handler.handler_, &handler.attr_); \
@@ -4905,7 +5613,7 @@ inline Handler<T>::Handler(F func)
template <class T>
inline Handler<T>::~Handler() {
- assert(registered_);
+ UPB_ASSERT(registered_);
}
inline HandlerAttributes::HandlerAttributes() { upb_handlerattr_init(this); }
@@ -4991,63 +5699,63 @@ inline bool Handlers::AddCleanup(void *p, upb_handlerfree *func) {
}
inline bool Handlers::SetStartMessageHandler(
const Handlers::StartMessageHandler &handler) {
- assert(!handler.registered_);
+ UPB_ASSERT(!handler.registered_);
handler.registered_ = true;
handler.AddCleanup(this);
return upb_handlers_setstartmsg(this, handler.handler_, &handler.attr_);
}
inline bool Handlers::SetEndMessageHandler(
const Handlers::EndMessageHandler &handler) {
- assert(!handler.registered_);
+ UPB_ASSERT(!handler.registered_);
handler.registered_ = true;
handler.AddCleanup(this);
return upb_handlers_setendmsg(this, handler.handler_, &handler.attr_);
}
inline bool Handlers::SetStartStringHandler(const FieldDef *f,
const StartStringHandler &handler) {
- assert(!handler.registered_);
+ UPB_ASSERT(!handler.registered_);
handler.registered_ = true;
handler.AddCleanup(this);
return upb_handlers_setstartstr(this, f, handler.handler_, &handler.attr_);
}
inline bool Handlers::SetEndStringHandler(const FieldDef *f,
const EndFieldHandler &handler) {
- assert(!handler.registered_);
+ UPB_ASSERT(!handler.registered_);
handler.registered_ = true;
handler.AddCleanup(this);
return upb_handlers_setendstr(this, f, handler.handler_, &handler.attr_);
}
inline bool Handlers::SetStringHandler(const FieldDef *f,
const StringHandler& handler) {
- assert(!handler.registered_);
+ UPB_ASSERT(!handler.registered_);
handler.registered_ = true;
handler.AddCleanup(this);
return upb_handlers_setstring(this, f, handler.handler_, &handler.attr_);
}
inline bool Handlers::SetStartSequenceHandler(
const FieldDef *f, const StartFieldHandler &handler) {
- assert(!handler.registered_);
+ UPB_ASSERT(!handler.registered_);
handler.registered_ = true;
handler.AddCleanup(this);
return upb_handlers_setstartseq(this, f, handler.handler_, &handler.attr_);
}
inline bool Handlers::SetStartSubMessageHandler(
const FieldDef *f, const StartFieldHandler &handler) {
- assert(!handler.registered_);
+ UPB_ASSERT(!handler.registered_);
handler.registered_ = true;
handler.AddCleanup(this);
return upb_handlers_setstartsubmsg(this, f, handler.handler_, &handler.attr_);
}
inline bool Handlers::SetEndSubMessageHandler(const FieldDef *f,
const EndFieldHandler &handler) {
- assert(!handler.registered_);
+ UPB_ASSERT(!handler.registered_);
handler.registered_ = true;
handler.AddCleanup(this);
return upb_handlers_setendsubmsg(this, f, handler.handler_, &handler.attr_);
}
inline bool Handlers::SetEndSequenceHandler(const FieldDef *f,
const EndFieldHandler &handler) {
- assert(!handler.registered_);
+ UPB_ASSERT(!handler.registered_);
handler.registered_ = true;
handler.AddCleanup(this);
return upb_handlers_setendseq(this, f, handler.handler_, &handler.attr_);
@@ -5102,267 +5810,6 @@ inline BytesHandler::~BytesHandler() {}
#endif /* UPB_HANDLERS_H */
/*
-** upb::Environment (upb_env)
-**
-** A upb::Environment provides a means for injecting malloc and an
-** error-reporting callback into encoders/decoders. This allows them to be
-** independent of nearly all assumptions about their actual environment.
-**
-** It is also a container for allocating the encoders/decoders themselves that
-** insulates clients from knowing their actual size. This provides ABI
-** compatibility even if the size of the objects change. And this allows the
-** structure definitions to be in the .c files instead of the .h files, making
-** the .h files smaller and more readable.
-*/
-
-
-#ifndef UPB_ENV_H_
-#define UPB_ENV_H_
-
-#ifdef __cplusplus
-namespace upb {
-class Environment;
-class SeededAllocator;
-}
-#endif
-
-UPB_DECLARE_TYPE(upb::Environment, upb_env)
-UPB_DECLARE_TYPE(upb::SeededAllocator, upb_seededalloc)
-
-typedef void *upb_alloc_func(void *ud, void *ptr, size_t oldsize, size_t size);
-typedef void upb_cleanup_func(void *ud);
-typedef bool upb_error_func(void *ud, const upb_status *status);
-
-#ifdef __cplusplus
-
-/* An environment is *not* thread-safe. */
-class upb::Environment {
- public:
- Environment();
- ~Environment();
-
- /* Set a custom memory allocation function for the environment. May ONLY
- * be called before any calls to Malloc()/Realloc()/AddCleanup() below.
- * If this is not called, the system realloc() function will be used.
- * The given user pointer "ud" will be passed to the allocation function.
- *
- * The allocation function will not receive corresponding "free" calls. it
- * must ensure that the memory is valid for the lifetime of the Environment,
- * but it may be reclaimed any time thereafter. The likely usage is that
- * "ud" points to a stateful allocator, and that the allocator frees all
- * memory, arena-style, when it is destroyed. In this case the allocator must
- * outlive the Environment. Another possibility is that the allocation
- * function returns GC-able memory that is guaranteed to be GC-rooted for the
- * life of the Environment. */
- void SetAllocationFunction(upb_alloc_func* alloc, void* ud);
-
- template<class T>
- void SetAllocator(T* allocator) {
- SetAllocationFunction(allocator->GetAllocationFunction(), allocator);
- }
-
- /* Set a custom error reporting function. */
- void SetErrorFunction(upb_error_func* func, void* ud);
-
- /* Set the error reporting function to simply copy the status to the given
- * status and abort. */
- void ReportErrorsTo(Status* status);
-
- /* Returns true if all allocations and AddCleanup() calls have succeeded,
- * and no errors were reported with ReportError() (except ones that recovered
- * successfully). */
- bool ok() const;
-
- /* Functions for use by encoders/decoders. **********************************/
-
- /* Reports an error to this environment's callback, returning true if
- * the caller should try to recover. */
- bool ReportError(const Status* status);
-
- /* Allocate memory. Uses the environment's allocation function.
- *
- * There is no need to free(). All memory will be freed automatically, but is
- * guaranteed to outlive the Environment. */
- void* Malloc(size_t size);
-
- /* Reallocate memory. Preserves "oldsize" bytes from the existing buffer
- * Requires: oldsize <= existing_size.
- *
- * TODO(haberman): should we also enforce that oldsize <= size? */
- void* Realloc(void* ptr, size_t oldsize, size_t size);
-
- /* Add a cleanup function to run when the environment is destroyed.
- * Returns false on out-of-memory.
- *
- * The first call to AddCleanup() after SetAllocationFunction() is guaranteed
- * to return true -- this makes it possible to robustly set a cleanup handler
- * for a custom allocation function. */
- bool AddCleanup(upb_cleanup_func* func, void* ud);
-
- /* Total number of bytes that have been allocated. It is undefined what
- * Realloc() does to this counter. */
- size_t BytesAllocated() const;
-
- private:
- UPB_DISALLOW_COPY_AND_ASSIGN(Environment)
-
-#else
-struct upb_env {
-#endif /* __cplusplus */
-
- bool ok_;
- size_t bytes_allocated;
-
- /* Alloc function. */
- upb_alloc_func *alloc;
- void *alloc_ud;
-
- /* Error-reporting function. */
- upb_error_func *err;
- void *err_ud;
-
- /* Userdata for default alloc func. */
- void *default_alloc_ud;
-
- /* Cleanup entries. Pointer to a cleanup_ent, defined in env.c */
- void *cleanup_head;
-
- /* For future expansion, since the size of this struct is exposed to users. */
- void *future1;
- void *future2;
-};
-
-UPB_BEGIN_EXTERN_C
-
-void upb_env_init(upb_env *e);
-void upb_env_uninit(upb_env *e);
-void upb_env_setallocfunc(upb_env *e, upb_alloc_func *func, void *ud);
-void upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud);
-void upb_env_reporterrorsto(upb_env *e, upb_status *status);
-bool upb_env_ok(const upb_env *e);
-bool upb_env_reporterror(upb_env *e, const upb_status *status);
-void *upb_env_malloc(upb_env *e, size_t size);
-void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size);
-bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud);
-size_t upb_env_bytesallocated(const upb_env *e);
-
-UPB_END_EXTERN_C
-
-#ifdef __cplusplus
-
-/* An allocator that allocates from an initial memory region (likely the stack)
- * before falling back to another allocator. */
-class upb::SeededAllocator {
- public:
- SeededAllocator(void *mem, size_t len);
- ~SeededAllocator();
-
- /* Set a custom fallback memory allocation function for the allocator, to use
- * once the initial region runs out.
- *
- * May ONLY be called before GetAllocationFunction(). If this is not
- * called, the system realloc() will be the fallback allocator. */
- void SetFallbackAllocator(upb_alloc_func *alloc, void *ud);
-
- /* Gets the allocation function for this allocator. */
- upb_alloc_func* GetAllocationFunction();
-
- private:
- UPB_DISALLOW_COPY_AND_ASSIGN(SeededAllocator)
-
-#else
-struct upb_seededalloc {
-#endif /* __cplusplus */
-
- /* Fallback alloc function. */
- upb_alloc_func *alloc;
- upb_cleanup_func *alloc_cleanup;
- void *alloc_ud;
- bool need_cleanup;
- bool returned_allocfunc;
-
- /* Userdata for default alloc func. */
- void *default_alloc_ud;
-
- /* Pointers for the initial memory region. */
- char *mem_base;
- char *mem_ptr;
- char *mem_limit;
-
- /* For future expansion, since the size of this struct is exposed to users. */
- void *future1;
- void *future2;
-};
-
-UPB_BEGIN_EXTERN_C
-
-void upb_seededalloc_init(upb_seededalloc *a, void *mem, size_t len);
-void upb_seededalloc_uninit(upb_seededalloc *a);
-void upb_seededalloc_setfallbackalloc(upb_seededalloc *a, upb_alloc_func *func,
- void *ud);
-upb_alloc_func *upb_seededalloc_getallocfunc(upb_seededalloc *a);
-
-UPB_END_EXTERN_C
-
-#ifdef __cplusplus
-
-namespace upb {
-
-inline Environment::Environment() {
- upb_env_init(this);
-}
-inline Environment::~Environment() {
- upb_env_uninit(this);
-}
-inline void Environment::SetAllocationFunction(upb_alloc_func *alloc,
- void *ud) {
- upb_env_setallocfunc(this, alloc, ud);
-}
-inline void Environment::SetErrorFunction(upb_error_func *func, void *ud) {
- upb_env_seterrorfunc(this, func, ud);
-}
-inline void Environment::ReportErrorsTo(Status* status) {
- upb_env_reporterrorsto(this, status);
-}
-inline bool Environment::ok() const {
- return upb_env_ok(this);
-}
-inline bool Environment::ReportError(const Status* status) {
- return upb_env_reporterror(this, status);
-}
-inline void *Environment::Malloc(size_t size) {
- return upb_env_malloc(this, size);
-}
-inline void *Environment::Realloc(void *ptr, size_t oldsize, size_t size) {
- return upb_env_realloc(this, ptr, oldsize, size);
-}
-inline bool Environment::AddCleanup(upb_cleanup_func *func, void *ud) {
- return upb_env_addcleanup(this, func, ud);
-}
-inline size_t Environment::BytesAllocated() const {
- return upb_env_bytesallocated(this);
-}
-
-inline SeededAllocator::SeededAllocator(void *mem, size_t len) {
- upb_seededalloc_init(this, mem, len);
-}
-inline SeededAllocator::~SeededAllocator() {
- upb_seededalloc_uninit(this);
-}
-inline void SeededAllocator::SetFallbackAllocator(upb_alloc_func *alloc,
- void *ud) {
- upb_seededalloc_setfallbackalloc(this, alloc, ud);
-}
-inline upb_alloc_func *SeededAllocator::GetAllocationFunction() {
- return upb_seededalloc_getallocfunc(this);
-}
-
-} /* namespace upb */
-
-#endif /* __cplusplus */
-
-#endif /* UPB_ENV_H_ */
-/*
** upb::Sink (upb_sink)
** upb::BytesSink (upb_bytessink)
**
@@ -6066,12 +6513,17 @@ class upb::SymbolTable {
* only a few messages are changing. We may want to add a way of adding a
* tree of frozen defs to the symtab (perhaps an alternate constructor where
* you pass the root of the tree?) */
- bool Add(Def*const* defs, int n, void* ref_donor, upb_status* status);
+ bool Add(Def*const* defs, size_t n, void* ref_donor, Status* status);
bool Add(const std::vector<Def*>& defs, void *owner, Status* status) {
return Add((Def*const*)&defs[0], defs.size(), owner, status);
}
+ /* Resolves all subdefs for messages in this file and attempts to freeze the
+ * file. If this succeeds, adds all the symbols to this SymbolTable
+ * (replacing any existing ones with the same names). */
+ bool AddFile(FileDef* file, Status* s);
+
private:
UPB_DISALLOW_POD_OPS(SymbolTable, upb::SymbolTable)
};
@@ -6092,8 +6544,9 @@ const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base,
const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym);
const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym);
const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym);
-bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor,
- upb_status *status);
+bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, size_t n,
+ void *ref_donor, upb_status *status);
+bool upb_symtab_addfile(upb_symtab *s, upb_filedef *file, upb_status* status);
/* upb_symtab_iter i;
* for(upb_symtab_begin(&i, s, type); !upb_symtab_done(&i);
@@ -6135,9 +6588,12 @@ inline const MessageDef *SymbolTable::LookupMessage(const char *sym) const {
return upb_symtab_lookupmsg(this, sym);
}
inline bool SymbolTable::Add(
- Def*const* defs, int n, void* ref_donor, upb_status* status) {
+ Def*const* defs, size_t n, void* ref_donor, Status* status) {
return upb_symtab_add(this, (upb_def*const*)defs, n, ref_donor, status);
}
+inline bool SymbolTable::AddFile(FileDef* file, Status* s) {
+ return upb_symtab_addfile(this, file, s);
+}
} /* namespace upb */
#endif
@@ -6181,14 +6637,9 @@ class upb::descriptor::Reader {
/* The reader's input; this is where descriptor.proto data should be sent. */
Sink* input();
- /* Returns an array of all defs that have been parsed, and transfers ownership
- * of them to "owner". The number of defs is stored in *n. Ownership of the
- * returned array is retained and is invalidated by any other call into
- * Reader.
- *
- * These defs are not frozen or resolved; they are ready to be added to a
- * symtab. */
- upb::Def** GetDefs(void* owner, int* n);
+ /* Use to get the FileDefs that have been parsed. */
+ size_t file_count() const;
+ FileDef* file(size_t i) const;
/* Builds and returns handlers for the reader, owned by "owner." */
static Handlers* NewHandlers(const void* owner);
@@ -6204,7 +6655,8 @@ UPB_BEGIN_EXTERN_C
/* C API. */
upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h);
upb_sink *upb_descreader_input(upb_descreader *r);
-upb_def **upb_descreader_getdefs(upb_descreader *r, void *owner, int *n);
+size_t upb_descreader_filecount(const upb_descreader *r);
+upb_filedef *upb_descreader_file(const upb_descreader *r, size_t i);
const upb_handlers *upb_descreader_newhandlers(const void *owner);
UPB_END_EXTERN_C
@@ -6217,8 +6669,11 @@ inline Reader* Reader::Create(Environment* e, const Handlers *h) {
return upb_descreader_create(e, h);
}
inline Sink* Reader::input() { return upb_descreader_input(this); }
-inline upb::Def** Reader::GetDefs(void* owner, int* n) {
- return upb_descreader_getdefs(this, owner, n);
+inline size_t Reader::file_count() const {
+ return upb_descreader_filecount(this);
+}
+inline FileDef* Reader::file(size_t i) const {
+ return upb_descreader_file(this, i);
}
} /* namespace descriptor */
} /* namespace upb */
@@ -6231,519 +6686,290 @@ inline upb::Def** Reader::GetDefs(void* owner, int* n) {
* actually storing protobufs. It only contains *defs* which
* let you reflect over a protobuf *schema*.
*/
-/* This file was generated by upbc (the upb compiler).
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ * upb/descriptor/descriptor.proto
+ *
* Do not edit -- your changes will be discarded when the file is
* regenerated. */
-#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_
-#define GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_
+#ifndef UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_
+#define UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_
-#ifdef __cplusplus
UPB_BEGIN_EXTERN_C
-#endif
/* Enums */
typedef enum {
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_OPTIONAL = 1,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REQUIRED = 2,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED = 3
+ google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1,
+ google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2,
+ google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3
} google_protobuf_FieldDescriptorProto_Label;
typedef enum {
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE = 1,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT = 2,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64 = 3,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64 = 4,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 = 5,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64 = 6,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32 = 7,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL = 8,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING = 9,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP = 10,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE = 11,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES = 12,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32 = 13,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM = 14,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32 = 15,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64 = 16,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32 = 17,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64 = 18
+ google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1,
+ google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2,
+ google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3,
+ google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4,
+ google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5,
+ google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6,
+ google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7,
+ google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8,
+ google_protobuf_FieldDescriptorProto_TYPE_STRING = 9,
+ google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10,
+ google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11,
+ google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12,
+ google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13,
+ google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14,
+ google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15,
+ google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16,
+ google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17,
+ google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18
} google_protobuf_FieldDescriptorProto_Type;
typedef enum {
- GOOGLE_PROTOBUF_FIELDOPTIONS_STRING = 0,
- GOOGLE_PROTOBUF_FIELDOPTIONS_CORD = 1,
- GOOGLE_PROTOBUF_FIELDOPTIONS_STRING_PIECE = 2
+ google_protobuf_FieldOptions_STRING = 0,
+ google_protobuf_FieldOptions_CORD = 1,
+ google_protobuf_FieldOptions_STRING_PIECE = 2
} google_protobuf_FieldOptions_CType;
typedef enum {
- GOOGLE_PROTOBUF_FILEOPTIONS_SPEED = 1,
- GOOGLE_PROTOBUF_FILEOPTIONS_CODE_SIZE = 2,
- GOOGLE_PROTOBUF_FILEOPTIONS_LITE_RUNTIME = 3
+ google_protobuf_FieldOptions_JS_NORMAL = 0,
+ google_protobuf_FieldOptions_JS_STRING = 1,
+ google_protobuf_FieldOptions_JS_NUMBER = 2
+} google_protobuf_FieldOptions_JSType;
+
+typedef enum {
+ google_protobuf_FileOptions_SPEED = 1,
+ google_protobuf_FileOptions_CODE_SIZE = 2,
+ google_protobuf_FileOptions_LITE_RUNTIME = 3
} google_protobuf_FileOptions_OptimizeMode;
-/* Selectors */
-
-/* google.protobuf.DescriptorProto */
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSUBMSG 3
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 4
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSUBMSG 5
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSUBMSG 6
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_STARTSUBMSG 7
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSEQ 8
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSEQ 9
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSUBMSG 10
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSEQ 11
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSEQ 12
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSUBMSG 13
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 14
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 15
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 16
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSEQ 17
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSEQ 18
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSUBMSG 19
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSEQ 20
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSEQ 21
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSUBMSG 22
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_ENDSUBMSG 23
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STRING 24
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STARTSTR 25
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_ENDSTR 26
-
-/* google.protobuf.DescriptorProto.ExtensionRange */
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START_INT32 2
-#define SEL_GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END_INT32 3
-
-/* google.protobuf.EnumDescriptorProto */
-#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 3
-#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSEQ 4
-#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSEQ 5
-#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSUBMSG 6
-#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 7
-#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STRING 8
-#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STARTSTR 9
-#define SEL_GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_ENDSTR 10
-
-/* google.protobuf.EnumOptions */
-#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3
-#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4
-#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
-#define SEL_GOOGLE_PROTOBUF_ENUMOPTIONS_ALLOW_ALIAS_BOOL 6
-
-/* google.protobuf.EnumValueDescriptorProto */
-#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3
-#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STRING 4
-#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STARTSTR 5
-#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_ENDSTR 6
-#define SEL_GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_INT32 7
-
-/* google.protobuf.EnumValueOptions */
-#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3
-#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4
-#define SEL_GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
-
-/* google.protobuf.FieldDescriptorProto */
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STRING 4
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STARTSTR 5
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_ENDSTR 6
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STRING 7
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STARTSTR 8
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_ENDSTR 9
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_INT32 10
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_INT32 11
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 12
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STRING 13
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STARTSTR 14
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_ENDSTR 15
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STRING 16
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STARTSTR 17
-#define SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_ENDSTR 18
-
-/* google.protobuf.FieldOptions */
-#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3
-#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4
-#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
-#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE_INT32 6
-#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED_BOOL 7
-#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED_BOOL 8
-#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_LAZY_BOOL 9
-#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STRING 10
-#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STARTSTR 11
-#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_ENDSTR 12
-#define SEL_GOOGLE_PROTOBUF_FIELDOPTIONS_WEAK_BOOL 13
-
-/* google.protobuf.FileDescriptorProto */
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 3
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSUBMSG 4
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSUBMSG 5
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 6
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_STARTSUBMSG 7
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSEQ 8
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSEQ 9
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSUBMSG 10
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 11
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 12
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 13
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSEQ 14
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSEQ 15
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSUBMSG 16
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSEQ 17
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSEQ 18
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSUBMSG 19
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 20
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_ENDSUBMSG 21
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STRING 22
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STARTSTR 23
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_ENDSTR 24
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STRING 25
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STARTSTR 26
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_ENDSTR 27
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSEQ 28
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSEQ 29
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STRING 30
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSTR 31
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSTR 32
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_STARTSEQ 33
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_ENDSEQ 34
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_INT32 35
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_STARTSEQ 36
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_ENDSEQ 37
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_INT32 38
-
-/* google.protobuf.FileDescriptorSet */
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSEQ 3
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSEQ 4
-#define SEL_GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSUBMSG 5
-
-/* google.protobuf.FileOptions */
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STRING 6
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STARTSTR 7
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_ENDSTR 8
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STRING 9
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STARTSTR 10
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_ENDSTR 11
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_INT32 12
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_BOOL 13
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_STRING 14
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_STARTSTR 15
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_ENDSTR 16
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES_BOOL 17
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES_BOOL 18
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES_BOOL 19
-#define SEL_GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH_BOOL 20
-
-/* google.protobuf.MessageOptions */
-#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3
-#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4
-#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
-#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT_BOOL 6
-#define SEL_GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR_BOOL 7
-
-/* google.protobuf.MethodDescriptorProto */
-#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3
-#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STRING 4
-#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STARTSTR 5
-#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_ENDSTR 6
-#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STRING 7
-#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STARTSTR 8
-#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_ENDSTR 9
-#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STRING 10
-#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STARTSTR 11
-#define SEL_GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_ENDSTR 12
-
-/* google.protobuf.MethodOptions */
-#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3
-#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4
-#define SEL_GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
-
-/* google.protobuf.ServiceDescriptorProto */
-#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 3
-#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSEQ 4
-#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSEQ 5
-#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSUBMSG 6
-#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 7
-#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STRING 8
-#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STARTSTR 9
-#define SEL_GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_ENDSTR 10
-
-/* google.protobuf.ServiceOptions */
-#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3
-#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4
-#define SEL_GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
-
-/* google.protobuf.SourceCodeInfo */
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSEQ 3
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSEQ 4
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSUBMSG 5
-
-/* google.protobuf.SourceCodeInfo.Location */
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_STARTSEQ 2
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_ENDSEQ 3
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_INT32 4
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_STARTSEQ 5
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_ENDSEQ 6
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_INT32 7
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_STRING 8
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_STARTSTR 9
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_ENDSTR 10
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_STRING 11
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_STARTSTR 12
-#define SEL_GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_ENDSTR 13
-
-/* google.protobuf.UninterpretedOption */
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSUBMSG 2
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSEQ 3
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSEQ 4
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSUBMSG 5
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STRING 6
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STARTSTR 7
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_ENDSTR 8
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_UINT64 9
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_INT64 10
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_DOUBLE 11
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STRING 12
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STARTSTR 13
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_ENDSTR 14
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STRING 15
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STARTSTR 16
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_ENDSTR 17
-
-/* google.protobuf.UninterpretedOption.NamePart */
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STRING 2
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STARTSTR 3
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_ENDSTR 4
-#define SEL_GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION_BOOL 5
-
-const upb_symtab *upbdefs_google_protobuf_descriptor(const void *owner);
-
-/* MessageDefs */
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_DescriptorProto(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto.ExtensionRange");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumDescriptorProto");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumOptions(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumOptions");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumValueDescriptorProto");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumValueOptions");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FieldDescriptorProto");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FieldOptions(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FieldOptions");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorProto");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorSet");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileOptions(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileOptions");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MessageOptions(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MessageOptions");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MethodDescriptorProto");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MethodOptions(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MethodOptions");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.ServiceDescriptorProto");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_ServiceOptions(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.ServiceOptions");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo.Location");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption");
- assert(m);
- return m;
-}
-UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart(const upb_symtab *s) {
- const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption.NamePart");
- assert(m);
- return m;
-}
-
-
-/* EnumDefs */
-UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label(const upb_symtab *s) {
- const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldDescriptorProto.Label");
- assert(e);
- return e;
-}
-UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type(const upb_symtab *s) {
- const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldDescriptorProto.Type");
- assert(e);
- return e;
-}
-UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType(const upb_symtab *s) {
- const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldOptions.CType");
- assert(e);
- return e;
-}
-UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode(const upb_symtab *s) {
- const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FileOptions.OptimizeMode");
- assert(e);
- return e;
-}
-
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_end(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto_ExtensionRange(s), 2); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_start(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto_ExtensionRange(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_enum_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 4); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 6); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_extension_range(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 5); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_field(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 2); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_nested_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 3); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 7); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 3); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 2); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_allow_alias(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumOptions(s), 2); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumOptions(s), 999); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_number(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 2); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 3); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueOptions(s), 999); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_default_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 7); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_extendee(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 2); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_label(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 4); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_number(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 3); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 8); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 5); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_type_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 6); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_ctype(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_deprecated(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 3); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_experimental_map_key(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 9); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_lazy(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 5); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_packed(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 2); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 999); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_weak(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 10); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 3); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_enum_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 5); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 7); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_message_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 4); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 8); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 2); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_public_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 10); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_service(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 6); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_source_code_info(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 9); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_weak_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 11); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorSet_file(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorSet(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_cc_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 16); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_go_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 11); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_generate_equals_and_hash(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 20); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 17); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_multiple_files(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 10); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_outer_classname(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 8); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_optimize_for(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 9); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_py_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 18); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 999); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_message_set_wire_format(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_no_standard_descriptor_accessor(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 2); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 999); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_input_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 2); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 4); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_output_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 3); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodOptions(s), 999); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_method(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 2); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 3); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceOptions(s), 999); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_leading_comments(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 3); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_path(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_span(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 2); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_trailing_comments(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 4); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_location(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_is_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption_NamePart(s), 2); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_name_part(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption_NamePart(s), 1); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_aggregate_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 8); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_double_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 6); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_identifier_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 3); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 2); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_negative_int_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 5); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_positive_int_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 4); }
-UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_string_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 7); }
+/* MessageDefs: call these functions to get a ref to a msgdef. */
+const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_EnumOptions_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_FieldOptions_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_FileOptions_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_MessageOptions_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_MethodOptions_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_OneofDescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_ServiceOptions_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_get(const void *owner);
+const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart_get(const void *owner);
+
+/* EnumDefs: call these functions to get a ref to an enumdef. */
+const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label_get(const void *owner);
+const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type_get(const void *owner);
+const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType_get(const void *owner);
+const upb_enumdef *upbdefs_google_protobuf_FieldOptions_JSType_get(const void *owner);
+const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode_get(const void *owner);
+
+/* Functions to test whether this message is of a certain type. */
+UPB_INLINE bool upbdefs_google_protobuf_DescriptorProto_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.DescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.DescriptorProto.ExtensionRange") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.DescriptorProto.ReservedRange") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_EnumDescriptorProto_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumDescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_EnumOptions_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumOptions") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_EnumValueDescriptorProto_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumValueDescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_EnumValueOptions_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.EnumValueOptions") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FieldDescriptorProto_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.FieldDescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FieldOptions_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.FieldOptions") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FileDescriptorProto_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.FileDescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FileDescriptorSet_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.FileDescriptorSet") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FileOptions_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.FileOptions") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_MessageOptions_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.MessageOptions") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_MethodDescriptorProto_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.MethodDescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_MethodOptions_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.MethodOptions") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_OneofDescriptorProto_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.OneofDescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_ServiceDescriptorProto_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.ServiceDescriptorProto") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_ServiceOptions_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.ServiceOptions") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_SourceCodeInfo_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.SourceCodeInfo") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_SourceCodeInfo_Location_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.SourceCodeInfo.Location") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_UninterpretedOption_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.UninterpretedOption") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_UninterpretedOption_NamePart_is(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), "google.protobuf.UninterpretedOption.NamePart") == 0;
+}
+
+/* Functions to test whether this enum is of a certain type. */
+UPB_INLINE bool upbdefs_google_protobuf_FieldDescriptorProto_Label_is(const upb_enumdef *e) {
+ return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldDescriptorProto.Label") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FieldDescriptorProto_Type_is(const upb_enumdef *e) {
+ return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldDescriptorProto.Type") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FieldOptions_CType_is(const upb_enumdef *e) {
+ return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldOptions.CType") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FieldOptions_JSType_is(const upb_enumdef *e) {
+ return strcmp(upb_enumdef_fullname(e), "google.protobuf.FieldOptions.JSType") == 0;
+}
+UPB_INLINE bool upbdefs_google_protobuf_FileOptions_OptimizeMode_is(const upb_enumdef *e) {
+ return strcmp(upb_enumdef_fullname(e), "google.protobuf.FileOptions.OptimizeMode") == 0;
+}
+
+
+/* Functions to get a fielddef from a msgdef reference. */
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_f_end(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_f_start(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_f_end(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_f_start(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_enum_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_extension(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_extension_range(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_field(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_nested_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_oneof_decl(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 8); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 7); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_reserved_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 10); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_f_reserved_range(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m)); return upb_msgdef_itof(m, 9); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_f_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_f_allow_alias(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumOptions_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumOptions_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumOptions_is(m)); return upb_msgdef_itof(m, 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_f_number(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueOptions_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_EnumValueOptions_is(m)); return upb_msgdef_itof(m, 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_default_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 7); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_extendee(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_json_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 10); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_label(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_number(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_oneof_index(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 9); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 8); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_f_type_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m)); return upb_msgdef_itof(m, 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_ctype(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_jstype(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_lazy(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_packed(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_f_weak(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m)); return upb_msgdef_itof(m, 10); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_dependency(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_enum_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_extension(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 7); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_message_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 8); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_package(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_public_dependency(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 10); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_service(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_source_code_info(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 9); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_syntax(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 12); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_f_weak_dependency(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m)); return upb_msgdef_itof(m, 11); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorSet_f_file(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorSet_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_cc_enable_arenas(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 31); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_cc_generic_services(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 16); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_csharp_namespace(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 37); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 23); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_go_package(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 11); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_generate_equals_and_hash(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 20); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_generic_services(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 17); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_multiple_files(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 10); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_outer_classname(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 8); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_package(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_java_string_check_utf8(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 27); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_javanano_use_deprecated_package(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 38); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_objc_class_prefix(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 36); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_optimize_for(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 9); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_py_generic_services(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 18); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_map_entry(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 7); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_message_set_wire_format(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_no_standard_descriptor_accessor(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_client_streaming(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_input_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_output_type(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_f_server_streaming(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m)); return upb_msgdef_itof(m, 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodOptions_is(m)); return upb_msgdef_itof(m, 33); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MethodOptions_is(m)); return upb_msgdef_itof(m, 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_OneofDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_OneofDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_f_method(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceDescriptorProto_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceDescriptorProto_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_f_options(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceDescriptorProto_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceOptions_is(m)); return upb_msgdef_itof(m, 33); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_ServiceOptions_is(m)); return upb_msgdef_itof(m, 999); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_leading_comments(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_leading_detached_comments(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_path(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_span(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_f_trailing_comments(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m)); return upb_msgdef_itof(m, 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_f_location(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_f_is_extension(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_NamePart_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_f_name_part(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_NamePart_is(m)); return upb_msgdef_itof(m, 1); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_aggregate_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 8); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_double_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 6); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_identifier_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 3); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_name(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 2); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_negative_int_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 5); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_positive_int_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 4); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_f_string_value(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m)); return upb_msgdef_itof(m, 7); }
UPB_END_EXTERN_C
@@ -6752,277 +6978,360 @@ UPB_END_EXTERN_C
namespace upbdefs {
namespace google {
namespace protobuf {
-namespace descriptor {
-inline upb::reffed_ptr<const upb::SymbolTable> SymbolTable() {
- const upb::SymbolTable* s = upbdefs_google_protobuf_descriptor(&s);
- return upb::reffed_ptr<const upb::SymbolTable>(s, &s);
-}
-} /* namespace descriptor */
-} /* namespace protobuf */
-} /* namespace google */
-#define RETURN_REFFED(type, func) \
- const type* obj = func(upbdefs::google::protobuf::descriptor::SymbolTable().get()); \
- return upb::reffed_ptr<const type>(obj);
+class DescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ DescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_is(m));
+ }
-namespace google {
-namespace protobuf {
-namespace DescriptorProto {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_DescriptorProto) }
-inline upb::reffed_ptr<const upb::FieldDef> enum_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_enum_type) }
-inline upb::reffed_ptr<const upb::FieldDef> extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_extension) }
-inline upb::reffed_ptr<const upb::FieldDef> extension_range() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_extension_range) }
-inline upb::reffed_ptr<const upb::FieldDef> field() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_field) }
-inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_name) }
-inline upb::reffed_ptr<const upb::FieldDef> nested_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_nested_type) }
-inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_options) }
-} /* namespace DescriptorProto */
-} /* namespace protobuf */
-} /* namespace google */
+ static DescriptorProto get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_get(&m);
+ return DescriptorProto(m, &m);
+ }
-namespace google {
-namespace protobuf {
-namespace DescriptorProto {
-namespace ExtensionRange {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange) }
-inline upb::reffed_ptr<const upb::FieldDef> end() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange_end) }
-inline upb::reffed_ptr<const upb::FieldDef> start() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange_start) }
-} /* namespace ExtensionRange */
-} /* namespace DescriptorProto */
-} /* namespace protobuf */
-} /* namespace google */
+ class ExtensionRange : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ ExtensionRange(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ExtensionRange_is(m));
+ }
-namespace google {
-namespace protobuf {
-namespace EnumDescriptorProto {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumDescriptorProto) }
-inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_name) }
-inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_options) }
-inline upb::reffed_ptr<const upb::FieldDef> value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_value) }
-} /* namespace EnumDescriptorProto */
-} /* namespace protobuf */
-} /* namespace google */
+ static ExtensionRange get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(&m);
+ return ExtensionRange(m, &m);
+ }
+ };
-namespace google {
-namespace protobuf {
-namespace EnumOptions {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumOptions) }
-inline upb::reffed_ptr<const upb::FieldDef> allow_alias() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumOptions_allow_alias) }
-inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumOptions_uninterpreted_option) }
-} /* namespace EnumOptions */
-} /* namespace protobuf */
-} /* namespace google */
+ class ReservedRange : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ ReservedRange(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_DescriptorProto_ReservedRange_is(m));
+ }
-namespace google {
-namespace protobuf {
-namespace EnumValueDescriptorProto {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumValueDescriptorProto) }
-inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_name) }
-inline upb::reffed_ptr<const upb::FieldDef> number() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_number) }
-inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_options) }
-} /* namespace EnumValueDescriptorProto */
-} /* namespace protobuf */
-} /* namespace google */
+ static ReservedRange get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(&m);
+ return ReservedRange(m, &m);
+ }
+ };
+};
-namespace google {
-namespace protobuf {
-namespace EnumValueOptions {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumValueOptions) }
-inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueOptions_uninterpreted_option) }
-} /* namespace EnumValueOptions */
-} /* namespace protobuf */
-} /* namespace google */
+class EnumDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ EnumDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_EnumDescriptorProto_is(m));
+ }
-namespace google {
-namespace protobuf {
-namespace FieldDescriptorProto {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FieldDescriptorProto) }
-inline upb::reffed_ptr<const upb::FieldDef> default_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_default_value) }
-inline upb::reffed_ptr<const upb::FieldDef> extendee() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_extendee) }
-inline upb::reffed_ptr<const upb::FieldDef> label() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_label) }
-inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_name) }
-inline upb::reffed_ptr<const upb::FieldDef> number() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_number) }
-inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_options) }
-inline upb::reffed_ptr<const upb::FieldDef> type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_type) }
-inline upb::reffed_ptr<const upb::FieldDef> type_name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_type_name) }
-inline upb::reffed_ptr<const upb::EnumDef> Label() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldDescriptorProto_Label) }
-inline upb::reffed_ptr<const upb::EnumDef> Type() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldDescriptorProto_Type) }
-} /* namespace FieldDescriptorProto */
-} /* namespace protobuf */
-} /* namespace google */
+ static EnumDescriptorProto get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumDescriptorProto_get(&m);
+ return EnumDescriptorProto(m, &m);
+ }
+};
-namespace google {
-namespace protobuf {
-namespace FieldOptions {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FieldOptions) }
-inline upb::reffed_ptr<const upb::FieldDef> ctype() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_ctype) }
-inline upb::reffed_ptr<const upb::FieldDef> deprecated() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_deprecated) }
-inline upb::reffed_ptr<const upb::FieldDef> experimental_map_key() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_experimental_map_key) }
-inline upb::reffed_ptr<const upb::FieldDef> lazy() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_lazy) }
-inline upb::reffed_ptr<const upb::FieldDef> packed() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_packed) }
-inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_uninterpreted_option) }
-inline upb::reffed_ptr<const upb::FieldDef> weak() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_weak) }
-inline upb::reffed_ptr<const upb::EnumDef> CType() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldOptions_CType) }
-} /* namespace FieldOptions */
-} /* namespace protobuf */
-} /* namespace google */
+class EnumOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ EnumOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_EnumOptions_is(m));
+ }
-namespace google {
-namespace protobuf {
-namespace FileDescriptorProto {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileDescriptorProto) }
-inline upb::reffed_ptr<const upb::FieldDef> dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_dependency) }
-inline upb::reffed_ptr<const upb::FieldDef> enum_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_enum_type) }
-inline upb::reffed_ptr<const upb::FieldDef> extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_extension) }
-inline upb::reffed_ptr<const upb::FieldDef> message_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_message_type) }
-inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_name) }
-inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_options) }
-inline upb::reffed_ptr<const upb::FieldDef> package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_package) }
-inline upb::reffed_ptr<const upb::FieldDef> public_dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_public_dependency) }
-inline upb::reffed_ptr<const upb::FieldDef> service() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_service) }
-inline upb::reffed_ptr<const upb::FieldDef> source_code_info() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_source_code_info) }
-inline upb::reffed_ptr<const upb::FieldDef> weak_dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_weak_dependency) }
-} /* namespace FileDescriptorProto */
-} /* namespace protobuf */
-} /* namespace google */
+ static EnumOptions get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumOptions_get(&m);
+ return EnumOptions(m, &m);
+ }
+};
-namespace google {
-namespace protobuf {
-namespace FileDescriptorSet {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileDescriptorSet) }
-inline upb::reffed_ptr<const upb::FieldDef> file() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorSet_file) }
-} /* namespace FileDescriptorSet */
-} /* namespace protobuf */
-} /* namespace google */
+class EnumValueDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ EnumValueDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_EnumValueDescriptorProto_is(m));
+ }
-namespace google {
-namespace protobuf {
-namespace FileOptions {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileOptions) }
-inline upb::reffed_ptr<const upb::FieldDef> cc_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_cc_generic_services) }
-inline upb::reffed_ptr<const upb::FieldDef> go_package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_go_package) }
-inline upb::reffed_ptr<const upb::FieldDef> java_generate_equals_and_hash() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_generate_equals_and_hash) }
-inline upb::reffed_ptr<const upb::FieldDef> java_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_generic_services) }
-inline upb::reffed_ptr<const upb::FieldDef> java_multiple_files() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_multiple_files) }
-inline upb::reffed_ptr<const upb::FieldDef> java_outer_classname() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_outer_classname) }
-inline upb::reffed_ptr<const upb::FieldDef> java_package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_package) }
-inline upb::reffed_ptr<const upb::FieldDef> optimize_for() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_optimize_for) }
-inline upb::reffed_ptr<const upb::FieldDef> py_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_py_generic_services) }
-inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_uninterpreted_option) }
-inline upb::reffed_ptr<const upb::EnumDef> OptimizeMode() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FileOptions_OptimizeMode) }
-} /* namespace FileOptions */
-} /* namespace protobuf */
-} /* namespace google */
+ static EnumValueDescriptorProto get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumValueDescriptorProto_get(&m);
+ return EnumValueDescriptorProto(m, &m);
+ }
+};
-namespace google {
-namespace protobuf {
-namespace MessageOptions {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MessageOptions) }
-inline upb::reffed_ptr<const upb::FieldDef> message_set_wire_format() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_message_set_wire_format) }
-inline upb::reffed_ptr<const upb::FieldDef> no_standard_descriptor_accessor() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_no_standard_descriptor_accessor) }
-inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_uninterpreted_option) }
-} /* namespace MessageOptions */
-} /* namespace protobuf */
-} /* namespace google */
+class EnumValueOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ EnumValueOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_EnumValueOptions_is(m));
+ }
-namespace google {
-namespace protobuf {
-namespace MethodDescriptorProto {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MethodDescriptorProto) }
-inline upb::reffed_ptr<const upb::FieldDef> input_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_input_type) }
-inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_name) }
-inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_options) }
-inline upb::reffed_ptr<const upb::FieldDef> output_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_output_type) }
-} /* namespace MethodDescriptorProto */
-} /* namespace protobuf */
-} /* namespace google */
+ static EnumValueOptions get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_EnumValueOptions_get(&m);
+ return EnumValueOptions(m, &m);
+ }
+};
-namespace google {
-namespace protobuf {
-namespace MethodOptions {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MethodOptions) }
-inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodOptions_uninterpreted_option) }
-} /* namespace MethodOptions */
-} /* namespace protobuf */
-} /* namespace google */
+class FieldDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ FieldDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_is(m));
+ }
-namespace google {
-namespace protobuf {
-namespace ServiceDescriptorProto {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_ServiceDescriptorProto) }
-inline upb::reffed_ptr<const upb::FieldDef> method() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_method) }
-inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_name) }
-inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_options) }
-} /* namespace ServiceDescriptorProto */
-} /* namespace protobuf */
-} /* namespace google */
+ static FieldDescriptorProto get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_FieldDescriptorProto_get(&m);
+ return FieldDescriptorProto(m, &m);
+ }
-namespace google {
-namespace protobuf {
-namespace ServiceOptions {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_ServiceOptions) }
-inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceOptions_uninterpreted_option) }
-} /* namespace ServiceOptions */
-} /* namespace protobuf */
-} /* namespace google */
+ class Label : public ::upb::reffed_ptr<const ::upb::EnumDef> {
+ public:
+ Label(const ::upb::EnumDef* e, const void *ref_donor = NULL)
+ : reffed_ptr(e, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_Label_is(e));
+ }
+ static Label get() {
+ const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldDescriptorProto_Label_get(&e);
+ return Label(e, &e);
+ }
+ };
-namespace google {
-namespace protobuf {
-namespace SourceCodeInfo {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_SourceCodeInfo) }
-inline upb::reffed_ptr<const upb::FieldDef> location() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_location) }
-} /* namespace SourceCodeInfo */
-} /* namespace protobuf */
-} /* namespace google */
+ class Type : public ::upb::reffed_ptr<const ::upb::EnumDef> {
+ public:
+ Type(const ::upb::EnumDef* e, const void *ref_donor = NULL)
+ : reffed_ptr(e, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_FieldDescriptorProto_Type_is(e));
+ }
+ static Type get() {
+ const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldDescriptorProto_Type_get(&e);
+ return Type(e, &e);
+ }
+ };
+};
-namespace google {
-namespace protobuf {
-namespace SourceCodeInfo {
-namespace Location {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_SourceCodeInfo_Location) }
-inline upb::reffed_ptr<const upb::FieldDef> leading_comments() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_leading_comments) }
-inline upb::reffed_ptr<const upb::FieldDef> path() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_path) }
-inline upb::reffed_ptr<const upb::FieldDef> span() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_span) }
-inline upb::reffed_ptr<const upb::FieldDef> trailing_comments() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_trailing_comments) }
-} /* namespace Location */
-} /* namespace SourceCodeInfo */
-} /* namespace protobuf */
-} /* namespace google */
+class FieldOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ FieldOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_is(m));
+ }
-namespace google {
-namespace protobuf {
-namespace UninterpretedOption {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_UninterpretedOption) }
-inline upb::reffed_ptr<const upb::FieldDef> aggregate_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_aggregate_value) }
-inline upb::reffed_ptr<const upb::FieldDef> double_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_double_value) }
-inline upb::reffed_ptr<const upb::FieldDef> identifier_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_identifier_value) }
-inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_name) }
-inline upb::reffed_ptr<const upb::FieldDef> negative_int_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_negative_int_value) }
-inline upb::reffed_ptr<const upb::FieldDef> positive_int_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_positive_int_value) }
-inline upb::reffed_ptr<const upb::FieldDef> string_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_string_value) }
-} /* namespace UninterpretedOption */
-} /* namespace protobuf */
-} /* namespace google */
+ static FieldOptions get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_FieldOptions_get(&m);
+ return FieldOptions(m, &m);
+ }
+
+ class CType : public ::upb::reffed_ptr<const ::upb::EnumDef> {
+ public:
+ CType(const ::upb::EnumDef* e, const void *ref_donor = NULL)
+ : reffed_ptr(e, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_CType_is(e));
+ }
+ static CType get() {
+ const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldOptions_CType_get(&e);
+ return CType(e, &e);
+ }
+ };
+
+ class JSType : public ::upb::reffed_ptr<const ::upb::EnumDef> {
+ public:
+ JSType(const ::upb::EnumDef* e, const void *ref_donor = NULL)
+ : reffed_ptr(e, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_FieldOptions_JSType_is(e));
+ }
+ static JSType get() {
+ const ::upb::EnumDef* e = upbdefs_google_protobuf_FieldOptions_JSType_get(&e);
+ return JSType(e, &e);
+ }
+ };
+};
+
+class FileDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ FileDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorProto_is(m));
+ }
+
+ static FileDescriptorProto get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_FileDescriptorProto_get(&m);
+ return FileDescriptorProto(m, &m);
+ }
+};
+
+class FileDescriptorSet : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ FileDescriptorSet(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_FileDescriptorSet_is(m));
+ }
+
+ static FileDescriptorSet get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_FileDescriptorSet_get(&m);
+ return FileDescriptorSet(m, &m);
+ }
+};
+
+class FileOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ FileOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m));
+ }
+
+ static FileOptions get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_FileOptions_get(&m);
+ return FileOptions(m, &m);
+ }
+
+ class OptimizeMode : public ::upb::reffed_ptr<const ::upb::EnumDef> {
+ public:
+ OptimizeMode(const ::upb::EnumDef* e, const void *ref_donor = NULL)
+ : reffed_ptr(e, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_FileOptions_OptimizeMode_is(e));
+ }
+ static OptimizeMode get() {
+ const ::upb::EnumDef* e = upbdefs_google_protobuf_FileOptions_OptimizeMode_get(&e);
+ return OptimizeMode(e, &e);
+ }
+ };
+};
+
+class MessageOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ MessageOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m));
+ }
+
+ static MessageOptions get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_MessageOptions_get(&m);
+ return MessageOptions(m, &m);
+ }
+};
+
+class MethodDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ MethodDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_MethodDescriptorProto_is(m));
+ }
+
+ static MethodDescriptorProto get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_MethodDescriptorProto_get(&m);
+ return MethodDescriptorProto(m, &m);
+ }
+};
+
+class MethodOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ MethodOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_MethodOptions_is(m));
+ }
+
+ static MethodOptions get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_MethodOptions_get(&m);
+ return MethodOptions(m, &m);
+ }
+};
+
+class OneofDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ OneofDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_OneofDescriptorProto_is(m));
+ }
+
+ static OneofDescriptorProto get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_OneofDescriptorProto_get(&m);
+ return OneofDescriptorProto(m, &m);
+ }
+};
+
+class ServiceDescriptorProto : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ ServiceDescriptorProto(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_ServiceDescriptorProto_is(m));
+ }
+
+ static ServiceDescriptorProto get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_ServiceDescriptorProto_get(&m);
+ return ServiceDescriptorProto(m, &m);
+ }
+};
+
+class ServiceOptions : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ ServiceOptions(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_ServiceOptions_is(m));
+ }
+
+ static ServiceOptions get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_ServiceOptions_get(&m);
+ return ServiceOptions(m, &m);
+ }
+};
+
+class SourceCodeInfo : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ SourceCodeInfo(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_is(m));
+ }
+
+ static SourceCodeInfo get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_SourceCodeInfo_get(&m);
+ return SourceCodeInfo(m, &m);
+ }
+
+ class Location : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ Location(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_SourceCodeInfo_Location_is(m));
+ }
+
+ static Location get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_SourceCodeInfo_Location_get(&m);
+ return Location(m, &m);
+ }
+ };
+};
+
+class UninterpretedOption : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ UninterpretedOption(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_is(m));
+ }
+
+ static UninterpretedOption get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_UninterpretedOption_get(&m);
+ return UninterpretedOption(m, &m);
+ }
+
+ class NamePart : public ::upb::reffed_ptr<const ::upb::MessageDef> {
+ public:
+ NamePart(const ::upb::MessageDef* m, const void *ref_donor = NULL)
+ : reffed_ptr(m, ref_donor) {
+ UPB_ASSERT(upbdefs_google_protobuf_UninterpretedOption_NamePart_is(m));
+ }
+
+ static NamePart get() {
+ const ::upb::MessageDef* m = upbdefs_google_protobuf_UninterpretedOption_NamePart_get(&m);
+ return NamePart(m, &m);
+ }
+ };
+};
-namespace google {
-namespace protobuf {
-namespace UninterpretedOption {
-namespace NamePart {
-inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_UninterpretedOption_NamePart) }
-inline upb::reffed_ptr<const upb::FieldDef> is_extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_NamePart_is_extension) }
-inline upb::reffed_ptr<const upb::FieldDef> name_part() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_NamePart_name_part) }
-} /* namespace NamePart */
-} /* namespace UninterpretedOption */
} /* namespace protobuf */
} /* namespace google */
-
} /* namespace upbdefs */
+#endif /* __cplusplus */
-#undef RETURN_REFFED
-#endif /* __cplusplus */
-
-#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ */
+#endif /* UPB_DESCRIPTOR_DESCRIPTOR_PROTO_UPB_H_ */
/*
** Internal-only definitions for the decoder.
*/
@@ -7030,7 +7339,6 @@ inline upb::reffed_ptr<const upb::FieldDef> name_part() { RETURN_REFFED(upb::Fie
#ifndef UPB_DECODER_INT_H_
#define UPB_DECODER_INT_H_
-#include <stdlib.h>
/*
** upb::pb::Decoder
**
@@ -7067,6 +7375,13 @@ UPB_DECLARE_TYPE(upb::pb::DecoderMethodOptions, upb_pbdecodermethodopts)
UPB_DECLARE_DERIVED_TYPE(upb::pb::DecoderMethod, upb::RefCounted,
upb_pbdecodermethod, upb_refcounted)
+/* The maximum number of bytes we are required to buffer internally between
+ * calls to the decoder. The value is 14: a 5 byte unknown tag plus ten-byte
+ * varint, less one because we are buffering an incomplete value.
+ *
+ * Should only be used by unit tests. */
+#define UPB_DECODER_MAX_RESIDUAL_BYTES 14
+
#ifdef __cplusplus
/* The parameters one uses to construct a DecoderMethod.
@@ -7123,7 +7438,7 @@ class upb::pb::DecoderMethod {
* constructed. This hint may be an overestimate for some build configurations.
* But if the decoder library is upgraded without recompiling the application,
* it may be an underestimate. */
-#define UPB_PB_DECODER_SIZE 4408
+#define UPB_PB_DECODER_SIZE 4416
#ifdef __cplusplus
@@ -7541,11 +7856,8 @@ struct upb_pbdecoder {
/* Overall stream offset of "buf." */
uint64_t bufstart_ofs;
- /* Buffer for residual bytes not parsed from the previous buffer.
- * The maximum number of residual bytes we require is 12; a five-byte
- * unknown tag plus an eight-byte value, less one because the value
- * is only a partial value. */
- char residual[12];
+ /* Buffer for residual bytes not parsed from the previous buffer. */
+ char residual[UPB_DECODER_MAX_RESIDUAL_BYTES];
char *residual_end;
/* Bytes of data that should be discarded from the input beore we start
@@ -7812,9 +8124,9 @@ UPB_INLINE uint64_t upb_vencode32(uint32_t val) {
char buf[UPB_PB_VARINT_MAX_LEN];
size_t bytes = upb_vencode64(val, buf);
uint64_t ret = 0;
- assert(bytes <= 5);
+ UPB_ASSERT(bytes <= 5);
memcpy(&ret, buf, bytes);
- assert(ret <= 0xffffffffffU);
+ UPB_ASSERT(ret <= 0xffffffffffU);
return ret;
}
@@ -7939,49 +8251,44 @@ inline reffed_ptr<const Handlers> Encoder::NewHandlers(
#include <stdbool.h>
#ifdef __cplusplus
+#include <vector>
+
extern "C" {
#endif
-/* Loads all defs from the given protobuf binary descriptor, setting default
- * accessors and a default layout on all messages. The caller owns the
- * returned array of defs, which will be of length *n. On error NULL is
- * returned and status is set (if non-NULL). */
-upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n,
- void *owner, upb_status *status);
-
-/* Like the previous but also adds the loaded defs to the given symtab. */
-bool upb_load_descriptor_into_symtab(upb_symtab *symtab, const char *str,
- size_t len, upb_status *status);
-
-/* Like the previous but also reads the descriptor from the given filename. */
-bool upb_load_descriptor_file_into_symtab(upb_symtab *symtab, const char *fname,
- upb_status *status);
-
-/* Reads the given filename into a character string, returning NULL if there
- * was an error. */
-char *upb_readfile(const char *filename, size_t *len);
+/* Loads a binary descriptor and returns a NULL-terminated array of unfrozen
+ * filedefs. The caller owns the returned array, which must be freed with
+ * upb_gfree(). */
+upb_filedef **upb_loaddescriptor(const char *buf, size_t n, const void *owner,
+ upb_status *status);
#ifdef __cplusplus
} /* extern "C" */
namespace upb {
-/* All routines that load descriptors expect the descriptor to be a
- * FileDescriptorSet. */
-inline bool LoadDescriptorFileIntoSymtab(SymbolTable* s, const char *fname,
- Status* status) {
- return upb_load_descriptor_file_into_symtab(s, fname, status);
-}
+inline bool LoadDescriptor(const char* buf, size_t n, Status* status,
+ std::vector<reffed_ptr<FileDef> >* files) {
+ FileDef** parsed_files = upb_loaddescriptor(buf, n, &parsed_files, status);
-inline bool LoadDescriptorIntoSymtab(SymbolTable* s, const char* str,
- size_t len, Status* status) {
- return upb_load_descriptor_into_symtab(s, str, len, status);
+ if (parsed_files) {
+ FileDef** p = parsed_files;
+ while (*p) {
+ files->push_back(reffed_ptr<FileDef>(*p, &parsed_files));
+ ++p;
+ }
+ free(parsed_files);
+ return true;
+ } else {
+ return false;
+ }
}
/* Templated so it can accept both string and std::string. */
template <typename T>
-bool LoadDescriptorIntoSymtab(SymbolTable* s, const T& desc, Status* status) {
- return upb_load_descriptor_into_symtab(s, desc.c_str(), desc.size(), status);
+bool LoadDescriptor(const T& desc, Status* status,
+ std::vector<reffed_ptr<FileDef> >* files) {
+ return LoadDescriptor(desc.c_str(), desc.size(), status, files);
}
} /* namespace upb */
@@ -8083,11 +8390,14 @@ inline reffed_ptr<const Handlers> TextPrinter::NewHandlers(
namespace upb {
namespace json {
class Parser;
+class ParserMethod;
} /* namespace json */
} /* namespace upb */
#endif
UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser)
+UPB_DECLARE_DERIVED_TYPE(upb::json::ParserMethod, upb::RefCounted,
+ upb_json_parsermethod, upb_refcounted)
/* upb::json::Parser **********************************************************/
@@ -8095,7 +8405,7 @@ UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser)
* constructed. This hint may be an overestimate for some build configurations.
* But if the parser library is upgraded without recompiling the application,
* it may be an underestimate. */
-#define UPB_JSON_PARSER_SIZE 3704
+#define UPB_JSON_PARSER_SIZE 4112
#ifdef __cplusplus
@@ -8103,7 +8413,8 @@ UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser)
* sink. */
class upb::json::Parser {
public:
- static Parser* Create(Environment* env, Sink* output);
+ static Parser* Create(Environment* env, const ParserMethod* method,
+ Sink* output);
BytesSink* input();
@@ -8111,25 +8422,72 @@ class upb::json::Parser {
UPB_DISALLOW_POD_OPS(Parser, upb::json::Parser)
};
+class upb::json::ParserMethod {
+ public:
+ /* Include base methods from upb::ReferenceCounted. */
+ UPB_REFCOUNTED_CPPMETHODS
+
+ /* Returns handlers for parsing according to the specified schema. */
+ static reffed_ptr<const ParserMethod> New(const upb::MessageDef* md);
+
+ /* The destination handlers that are statically bound to this method.
+ * This method is only capable of outputting to a sink that uses these
+ * handlers. */
+ const Handlers* dest_handlers() const;
+
+ /* The input handlers for this decoder method. */
+ const BytesHandler* input_handler() const;
+
+ private:
+ UPB_DISALLOW_POD_OPS(ParserMethod, upb::json::ParserMethod)
+};
+
#endif
UPB_BEGIN_EXTERN_C
-upb_json_parser *upb_json_parser_create(upb_env *e, upb_sink *output);
+upb_json_parser* upb_json_parser_create(upb_env* e,
+ const upb_json_parsermethod* m,
+ upb_sink* output);
upb_bytessink *upb_json_parser_input(upb_json_parser *p);
+upb_json_parsermethod* upb_json_parsermethod_new(const upb_msgdef* md,
+ const void* owner);
+const upb_handlers *upb_json_parsermethod_desthandlers(
+ const upb_json_parsermethod *m);
+const upb_byteshandler *upb_json_parsermethod_inputhandler(
+ const upb_json_parsermethod *m);
+
+/* Include refcounted methods like upb_json_parsermethod_ref(). */
+UPB_REFCOUNTED_CMETHODS(upb_json_parsermethod, upb_json_parsermethod_upcast)
+
UPB_END_EXTERN_C
#ifdef __cplusplus
namespace upb {
namespace json {
-inline Parser* Parser::Create(Environment* env, Sink* output) {
- return upb_json_parser_create(env, output);
+inline Parser* Parser::Create(Environment* env, const ParserMethod* method,
+ Sink* output) {
+ return upb_json_parser_create(env, method, output);
}
inline BytesSink* Parser::input() {
return upb_json_parser_input(this);
}
+
+inline const Handlers* ParserMethod::dest_handlers() const {
+ return upb_json_parsermethod_desthandlers(this);
+}
+inline const BytesHandler* ParserMethod::input_handler() const {
+ return upb_json_parsermethod_inputhandler(this);
+}
+/* static */
+inline reffed_ptr<const ParserMethod> ParserMethod::New(
+ const MessageDef* md) {
+ const upb_json_parsermethod *m = upb_json_parsermethod_new(md, &m);
+ return reffed_ptr<const ParserMethod>(m, &m);
+}
+
} /* namespace json */
} /* namespace upb */
@@ -8160,7 +8518,7 @@ UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer)
/* upb::json::Printer *********************************************************/
-#define UPB_JSON_PRINTER_SIZE 168
+#define UPB_JSON_PRINTER_SIZE 176
#ifdef __cplusplus
@@ -8173,8 +8531,12 @@ class upb::json::Printer {
/* The input to the printer. */
Sink* input();
- /* Returns handlers for printing according to the specified schema. */
- static reffed_ptr<const Handlers> NewHandlers(const upb::MessageDef* md);
+ /* Returns handlers for printing according to the specified schema.
+ * If preserve_proto_fieldnames is true, the output JSON will use the
+ * original .proto field names (ie. {"my_field":3}) instead of using
+ * camelCased names, which is the default: (eg. {"myField":3}). */
+ static reffed_ptr<const Handlers> NewHandlers(const upb::MessageDef* md,
+ bool preserve_proto_fieldnames);
static const size_t kSize = UPB_JSON_PRINTER_SIZE;
@@ -8191,6 +8553,7 @@ upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
upb_bytessink *output);
upb_sink *upb_json_printer_input(upb_json_printer *p);
const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
+ bool preserve_fieldnames,
const void *owner);
UPB_END_EXTERN_C
@@ -8205,8 +8568,9 @@ inline Printer* Printer::Create(Environment* env, const upb::Handlers* handlers,
}
inline Sink* Printer::input() { return upb_json_printer_input(this); }
inline reffed_ptr<const Handlers> Printer::NewHandlers(
- const upb::MessageDef *md) {
- const Handlers* h = upb_json_printer_newhandlers(md, &h);
+ const upb::MessageDef *md, bool preserve_proto_fieldnames) {
+ const Handlers* h = upb_json_printer_newhandlers(
+ md, preserve_proto_fieldnames, &h);
return reffed_ptr<const Handlers>(h, &h);
}
} /* namespace json */
diff --git a/php/ext/google/protobuf/utf8.c b/php/ext/google/protobuf/utf8.c
new file mode 100644
index 00000000..a1541636
--- /dev/null
+++ b/php/ext/google/protobuf/utf8.c
@@ -0,0 +1,68 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "utf8.h"
+
+static const uint8_t utf8_offset[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+bool is_structurally_valid_utf8(const char* buf, int len) {
+ int i, j;
+ uint8_t offset;
+
+ i = 0;
+ while (i < len) {
+ offset = utf8_offset[(uint8_t)buf[i]];
+ if (offset == 0 || i + offset > len) {
+ return false;
+ }
+ for (j = i + 1; j < i + offset; j++) {
+ if (buf[j] & 0xc0 != 0x80) {
+ return false;
+ }
+ }
+ i += offset;
+ }
+ return i == len;
+}
diff --git a/php/ext/google/protobuf/utf8.h b/php/ext/google/protobuf/utf8.h
new file mode 100644
index 00000000..28b8d874
--- /dev/null
+++ b/php/ext/google/protobuf/utf8.h
@@ -0,0 +1,36 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTF8_H_
+#define GOOGLE_PROTOBUF_UTF8_H_
+
+bool is_structurally_valid_utf8(const char* buf, int len);
+
+#endif // GOOGLE_PROTOBUF_UTF8_H_
diff --git a/php/src/Google/Protobuf/Internal/DescriptorPool.php b/php/src/Google/Protobuf/Internal/DescriptorPool.php
new file mode 100644
index 00000000..23b304ac
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/DescriptorPool.php
@@ -0,0 +1,162 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+use Google\Protobuf\Internal\Descriptor;
+use Google\Protobuf\Internal\FileDescriptor;
+use Google\Protobuf\Internal\FileDescriptorSet;
+use Google\Protobuf\Internal\MessageBuilderContext;
+use Google\Protobuf\Internal\EnumBuilderContext;
+
+class DescriptorPool
+{
+ private static $pool;
+ // Map from message names to sub-maps, which are maps from field numbers to
+ // field descriptors.
+ private $class_to_desc = [];
+ private $class_to_enum_desc = [];
+ private $proto_to_class = [];
+
+ public static function getGeneratedPool()
+ {
+ if (!isset(self::$pool)) {
+ self::$pool = new DescriptorPool();
+ }
+ return self::$pool;
+ }
+
+ public function internalAddGeneratedFile($data)
+ {
+ $files = new FileDescriptorSet();
+ $files->decode($data);
+ $file = FileDescriptor::buildFromProto($files->getFile()[0]);
+
+ foreach ($file->getMessageType() as &$desc) {
+ $this->addDescriptor($desc);
+ }
+ unset($desc);
+
+ foreach ($file->getEnumType() as &$desc) {
+ $this->addEnumDescriptor($desc);
+ }
+ unset($desc);
+
+ foreach ($file->getMessageType() as &$desc) {
+ $this->crossLink($desc);
+ }
+ unset($desc);
+ }
+
+ public function addMessage($name, $klass)
+ {
+ return new MessageBuilderContext($name, $klass, $this);
+ }
+
+ public function addEnum($name, $klass)
+ {
+ return new EnumBuilderContext($name, $klass, $this);
+ }
+
+ public function addDescriptor($descriptor)
+ {
+ $this->proto_to_class[$descriptor->getFullName()] =
+ $descriptor->getClass();
+ $this->class_to_desc[$descriptor->getClass()] = $descriptor;
+ foreach ($descriptor->getNestedType() as $nested_type) {
+ $this->addDescriptor($nested_type);
+ }
+ }
+
+ public function addEnumDescriptor($descriptor)
+ {
+ $this->proto_to_class[$descriptor->getFullName()] =
+ $descriptor->getClass();
+ $this->class_to_enum_desc[$descriptor->getClass()] = $descriptor;
+ }
+
+ public function getDescriptorByClassName($klass)
+ {
+ return $this->class_to_desc[$klass];
+ }
+
+ public function getEnumDescriptorByClassName($klass)
+ {
+ return $this->class_to_enum_desc[$klass];
+ }
+
+ public function getDescriptorByProtoName($proto)
+ {
+ $klass = $this->proto_to_class[$proto];
+ return $this->class_to_desc[$klass];
+ }
+
+ public function getEnumDescriptorByProtoName($proto)
+ {
+ $klass = $this->proto_to_class[$proto];
+ return $this->class_to_enum_desc[$klass];
+ }
+
+ private function crossLink(&$desc)
+ {
+ foreach ($desc->getField() as &$field) {
+ switch ($field->getType()) {
+ case GPBType::MESSAGE:
+ $proto = $field->getMessageType();
+ $field->setMessageType(
+ $this->getDescriptorByProtoName($proto));
+ break;
+ case GPBType::ENUM:
+ $proto = $field->getEnumType();
+ $field->setEnumType(
+ $this->getEnumDescriptorByProtoName($proto));
+ break;
+ default:
+ break;
+ }
+ }
+ unset($field);
+
+ foreach ($desc->getNestedType() as &$nested_type) {
+ $this->crossLink($nested_type);
+ }
+ unset($nested_type);
+ }
+
+ public function finish()
+ {
+ foreach ($this->class_to_desc as $klass => &$desc) {
+ $this->crossLink($desc);
+ }
+ unset($desc);
+ }
+}
diff --git a/php/src/Google/Protobuf/Internal/EnumBuilderContext.php b/php/src/Google/Protobuf/Internal/EnumBuilderContext.php
new file mode 100644
index 00000000..c1dac24d
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/EnumBuilderContext.php
@@ -0,0 +1,63 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+use Google\Protobuf\Internal\EnumDescriptor;
+use Google\Protobuf\Internal\EnumValueDescriptor;
+
+class EnumBuilderContext
+{
+
+ private $descriptor;
+ private $pool;
+
+ public function __construct($full_name, $klass, $pool)
+ {
+ $this->descriptor = new EnumDescriptor();
+ $this->descriptor->setFullName($full_name);
+ $this->descriptor->setClass($klass);
+ $this->pool = $pool;
+ }
+
+ public function value($name, $number)
+ {
+ $value = new EnumValueDescriptor();
+ $this->descriptor->addValue($number, $value);
+ return $this;
+ }
+
+ public function finalizeToPool()
+ {
+ $this->pool->addEnumDescriptor($this->descriptor);
+ }
+}
diff --git a/php/src/Google/Protobuf/Internal/GPBLabel.php b/php/src/Google/Protobuf/Internal/GPBLabel.php
new file mode 100644
index 00000000..0fb23841
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/GPBLabel.php
@@ -0,0 +1,40 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+class GPBLabel
+{
+ const OPTIONAL = 1;
+ const REQUIRED = 2;
+ const REPEATED = 3;
+}
diff --git a/php/src/Google/Protobuf/Internal/GPBType.php b/php/src/Google/Protobuf/Internal/GPBType.php
new file mode 100644
index 00000000..fa849ceb
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/GPBType.php
@@ -0,0 +1,55 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+class GPBType
+{
+ const DOUBLE = 1;
+ const FLOAT = 2;
+ const INT64 = 3;
+ const UINT64 = 4;
+ const INT32 = 5;
+ const FIXED64 = 6;
+ const FIXED32 = 7;
+ const BOOL = 8;
+ const STRING = 9;
+ const GROUP = 10;
+ const MESSAGE = 11;
+ const BYTES = 12;
+ const UINT32 = 13;
+ const ENUM = 14;
+ const SFIXED32 = 15;
+ const SFIXED64 = 16;
+ const SINT32 = 17;
+ const SINT64 = 18;
+}
diff --git a/php/src/Google/Protobuf/Internal/GPBUtil.php b/php/src/Google/Protobuf/Internal/GPBUtil.php
new file mode 100644
index 00000000..417a9729
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/GPBUtil.php
@@ -0,0 +1,161 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+
+class GPBUtil
+{
+
+ public static function checkString(&$var, $check_utf8)
+ {
+ if (is_array($var) || is_object($var)) {
+ trigger_error("Expect string.", E_USER_ERROR);
+ return;
+ }
+ if (!is_string($var)) {
+ $var = strval($var);
+ }
+ if ($check_utf8 && !preg_match('//u', $var)) {
+ trigger_error("Expect utf-8 encoding.", E_USER_ERROR);
+ return;
+ }
+ }
+
+ public static function checkEnum(&$var)
+ {
+ static::checkInt32($var);
+ }
+
+ public static function checkInt32(&$var)
+ {
+ if (is_numeric($var)) {
+ $var = intval($var);
+ } else {
+ trigger_error("Expect integer.", E_USER_ERROR);
+ }
+ }
+
+ public static function checkUint32(&$var)
+ {
+ if (is_numeric($var)) {
+ $var = intval($var);
+ if (PHP_INT_SIZE === 8) {
+ $var |= ((-(($var >> 31) & 0x1)) & ~0xFFFFFFFF);
+ }
+ } else {
+ trigger_error("Expect integer.", E_USER_ERROR);
+ }
+ }
+
+ public static function checkInt64(&$var)
+ {
+ if (is_numeric($var)) {
+ $var = intval($var);
+ } else {
+ trigger_error("Expect integer.", E_USER_ERROR);
+ }
+ }
+
+ public static function checkUint64(&$var)
+ {
+ if (is_numeric($var)) {
+ $var = intval($var);
+ } else {
+ trigger_error("Expect integer.", E_USER_ERROR);
+ }
+ }
+
+ public static function checkFloat(&$var)
+ {
+ if (is_float($var) || is_numeric($var)) {
+ $var = floatval($var);
+ } else {
+ trigger_error("Expect float.", E_USER_ERROR);
+ }
+ }
+
+ public static function checkDouble(&$var)
+ {
+ if (is_float($var) || is_numeric($var)) {
+ $var = floatval($var);
+ } else {
+ trigger_error("Expect float.", E_USER_ERROR);
+ }
+ }
+
+ public static function checkBool(&$var)
+ {
+ if (is_array($var) || is_object($var)) {
+ trigger_error("Expect boolean.", E_USER_ERROR);
+ return;
+ }
+ $var = boolval($var);
+ }
+
+ public static function checkMessage(&$var, $klass)
+ {
+ if (!$var instanceof $klass && !is_null($var)) {
+ trigger_error("Expect message.", E_USER_ERROR);
+ }
+ }
+
+ public static function checkRepeatedField(&$var, $type, $klass = null)
+ {
+ if (!$var instanceof RepeatedField) {
+ trigger_error("Expect repeated field.", E_USER_ERROR);
+ }
+ if ($var->getType() != $type) {
+ trigger_error(
+ "Expect repeated field of different type.",
+ E_USER_ERROR);
+ }
+ if ($var->getType() === GPBType::MESSAGE &&
+ $var->getClass() !== $klass) {
+ trigger_error(
+ "Expect repeated field of different message.",
+ E_USER_ERROR);
+ }
+ }
+
+ public static function Int64($value)
+ {
+ return new Int64($value);
+ }
+
+ public static function Uint64($value)
+ {
+ return new Uint64($value);
+ }
+}
diff --git a/php/src/Google/Protobuf/Internal/GPBWire.php b/php/src/Google/Protobuf/Internal/GPBWire.php
new file mode 100644
index 00000000..0e741e15
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/GPBWire.php
@@ -0,0 +1,583 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+use Google\Protobuf\Internal\GPBUtil;
+use Google\Protobuf\Internal\Int64;
+use Google\Protobuf\Internal\Uint64;
+
+class GPBWire
+{
+
+ const TAG_TYPE_BITS = 3;
+
+ const WIRETYPE_VARINT = 0;
+ const WIRETYPE_FIXED64 = 1;
+ const WIRETYPE_LENGTH_DELIMITED = 2;
+ const WIRETYPE_START_GROUP = 3;
+ const WIRETYPE_END_GROUP = 4;
+ const WIRETYPE_FIXED32 = 5;
+
+ const UNKNOWN = 0;
+ const NORMAL_FORMAT = 1;
+ const PACKED_FORMAT = 2;
+
+ public static function getTagFieldNumber($tag)
+ {
+ return ($tag >> self::TAG_TYPE_BITS) &
+ (1 << ((PHP_INT_SIZE * 8) - self::TAG_TYPE_BITS)) - 1;
+ }
+
+ public static function getTagWireType($tag)
+ {
+ return $tag & 0x7;
+ }
+
+ public static function getWireType($type)
+ {
+ switch ($type) {
+ case GPBType::FLOAT:
+ case GPBType::FIXED32:
+ case GPBType::SFIXED32:
+ return self::WIRETYPE_FIXED32;
+ case GPBType::DOUBLE:
+ case GPBType::FIXED64:
+ case GPBType::SFIXED64:
+ return self::WIRETYPE_FIXED64;
+ case GPBType::UINT32:
+ case GPBType::UINT64:
+ case GPBType::INT32:
+ case GPBType::INT64:
+ case GPBType::SINT32:
+ case GPBType::SINT64:
+ case GPBType::ENUM:
+ case GPBType::BOOL:
+ return self::WIRETYPE_VARINT;
+ case GPBType::STRING:
+ case GPBType::BYTES:
+ case GPBType::MESSAGE:
+ return self::WIRETYPE_LENGTH_DELIMITED;
+ case GPBType::GROUP:
+ user_error("Unsupported type.");
+ return 0;
+ default:
+ user_error("Unsupported type.");
+ return 0;
+ }
+ }
+
+ // ZigZag Transform: Encodes signed integers so that they can be effectively
+ // used with varint encoding.
+ //
+ // varint operates on unsigned integers, encoding smaller numbers into fewer
+ // bytes. If you try to use it on a signed integer, it will treat this
+ // number as a very large unsigned integer, which means that even small
+ // signed numbers like -1 will take the maximum number of bytes (10) to
+ // encode. zigZagEncode() maps signed integers to unsigned in such a way
+ // that those with a small absolute value will have smaller encoded values,
+ // making them appropriate for encoding using varint.
+ //
+ // int32 -> uint32
+ // -------------------------
+ // 0 -> 0
+ // -1 -> 1
+ // 1 -> 2
+ // -2 -> 3
+ // ... -> ...
+ // 2147483647 -> 4294967294
+ // -2147483648 -> 4294967295
+ //
+ // >> encode >>
+ // << decode <<
+ public static function zigZagEncode32($int32)
+ {
+ // Fill high 32 bits.
+ if (PHP_INT_SIZE === 8) {
+ $int32 |= ((($int32 << 32) >> 31) & (0xFFFFFFFF << 32));
+ }
+
+ $uint32 = ($int32 << 1) ^ ($int32 >> 31);
+
+ // Fill high 32 bits.
+ if (PHP_INT_SIZE === 8) {
+ $uint32 |= ((($uint32 << 32) >> 31) & (0xFFFFFFFF << 32));
+ }
+
+ return $uint32;
+ }
+
+ public static function zigZagDecode32($uint32)
+ {
+ // Fill high 32 bits.
+ if (PHP_INT_SIZE === 8) {
+ $uint32 |= ($uint32 & 0xFFFFFFFF);
+ }
+
+ $int32 = (($uint32 >> 1) & 0x7FFFFFFF) ^ (-($uint32 & 1));
+
+ return $int32;
+ }
+
+ public static function zigZagEncode64($int64)
+ {
+ $a = $int64->copy()->leftShift(1);
+ $b = $int64->copy()->rightShift(63);
+ $result = $a->bitXor($b);
+ $uint64 = Uint64::newValue($result->high, $result->low);
+ return $uint64;
+ }
+
+ public static function zigZagDecode64($uint64)
+ {
+ $a = $uint64->copy()->rightShift(1);
+ $b = $uint64->oddMask();
+ $result = $a->bitXor($b);
+ $int64 = Int64::newValue($result->high, $result->low);
+ return $int64;
+ }
+
+ public static function readInt32(&$input, &$value)
+ {
+ return $input->readVarint32($value);
+ }
+
+ public static function readInt64(&$input, &$value)
+ {
+ return $input->readVarint64($value);
+ }
+
+ public static function readUint32(&$input, &$value)
+ {
+ return self::readInt32($input, $value);
+ }
+
+ public static function readUint64(&$input, &$value)
+ {
+ return self::readInt64($input, $value);
+ }
+
+ public static function readSint32(&$input, &$value)
+ {
+ if (!$input->readVarint32($value)) {
+ return false;
+ }
+ $value = GPBWire::zigZagDecode32($value);
+ return true;
+ }
+
+ public static function readSint64(&$input, &$value)
+ {
+ if (!$input->readVarint64($value)) {
+ return false;
+ }
+ $value = GPBWire::zigZagDecode64($value);
+ return true;
+ }
+
+ public static function readFixed32(&$input, &$value)
+ {
+ return $input->readLittleEndian32($value);
+ }
+
+ public static function readFixed64(&$input, &$value)
+ {
+ return $input->readLittleEndian64($value);
+ }
+
+ public static function readSfixed32(&$input, &$value)
+ {
+ if (!self::readFixed32($input, $value)) {
+ return false;
+ }
+ if (PHP_INT_SIZE === 8) {
+ $value |= (-($value >> 31) << 32);
+ }
+ return true;
+ }
+
+ public static function readSfixed64(&$input, &$value)
+ {
+ if (!self::readFixed64($input, $value)) {
+ return false;
+ }
+ $value = Int64::newValue($value->high, $value->low);
+ return true;
+ }
+
+ public static function readFloat(&$input, &$value)
+ {
+ $data = null;
+ if (!$input->readRaw(4, $data)) {
+ return false;
+ }
+ $value = unpack('f', $data)[1];
+ return true;
+ }
+
+ public static function readDouble(&$input, &$value)
+ {
+ $data = null;
+ if (!$input->readRaw(8, $data)) {
+ return false;
+ }
+ $value = unpack('d', $data)[1];
+ return true;
+ }
+
+ public static function readBool(&$input, &$value)
+ {
+ if (!$input->readVarint64($value)) {
+ return false;
+ }
+ if ($value->high === 0 && $value->low === 0) {
+ $value = false;
+ } else {
+ $value = true;
+ }
+ return true;
+ }
+
+ public static function readString(&$input, &$value)
+ {
+ $length = 0;
+ return $input->readVarintSizeAsInt($length) && $input->readRaw($length, $value);
+ }
+
+ public static function readMessage(&$input, &$message)
+ {
+ $length = 0;
+ if (!$input->readVarintSizeAsInt($length)) {
+ return false;
+ }
+ $old_limit = 0;
+ $recursion_limit = 0;
+ $input->incrementRecursionDepthAndPushLimit(
+ $length,
+ $old_limit,
+ $recursion_limit);
+ if ($recursion_limit < 0 || !$message->parseFromStream($input)) {
+ return false;
+ }
+ return $input->decrementRecursionDepthAndPopLimit($old_limit);
+ }
+
+ public static function writeTag(&$output, $tag)
+ {
+ return $output->writeTag($tag);
+ }
+
+ public static function writeInt32(&$output, $value)
+ {
+ return $output->writeVarint32($value);
+ }
+
+ public static function writeInt64(&$output, $value)
+ {
+ return $output->writeVarint64($value);
+ }
+
+ public static function writeUint32(&$output, $value)
+ {
+ return $output->writeVarint32($value);
+ }
+
+ public static function writeUint64(&$output, $value)
+ {
+ return $output->writeVarint64($value);
+ }
+
+ public static function writeSint32(&$output, $value)
+ {
+ $value = GPBWire::zigZagEncode32($value);
+ return $output->writeVarint64($value);
+ }
+
+ public static function writeSint64(&$output, $value)
+ {
+ $value = GPBWire::zigZagEncode64(GPBUtil::Int64($value));
+ return $output->writeVarint64($value->toInteger());
+ }
+
+ public static function writeFixed32(&$output, $value)
+ {
+ return $output->writeLittleEndian32($value);
+ }
+
+ public static function writeFixed64(&$output, $value)
+ {
+ return $output->writeLittleEndian64($value);
+ }
+
+ public static function writeSfixed32(&$output, $value)
+ {
+ return $output->writeLittleEndian32($value);
+ }
+
+ public static function writeSfixed64(&$output, $value)
+ {
+ return $output->writeLittleEndian64($value);
+ }
+
+ public static function writeBool(&$output, $value)
+ {
+ if ($value) {
+ return $output->writeVarint32(1);
+ } else {
+ return $output->writeVarint32(0);
+ }
+ }
+
+ public static function writeFloat(&$output, $value)
+ {
+ $data = pack("f", $value);
+ return $output->writeRaw($data, 4);
+ }
+
+ public static function writeDouble(&$output, $value)
+ {
+ $data = pack("d", $value);
+ return $output->writeRaw($data, 8);
+ }
+
+ public static function writeString(&$output, $value)
+ {
+ return self::writeBytes($output, $value);
+ }
+
+ public static function writeBytes(&$output, $value)
+ {
+ $size = strlen($value);
+ if (!$output->writeVarint32($size)) {
+ return false;
+ }
+ return $output->writeRaw($value, $size);
+ }
+
+ public static function writeMessage(&$output, $value)
+ {
+ $size = $value->byteSize();
+ if (!$output->writeVarint32($size)) {
+ return false;
+ }
+ return $value->serializeToStream($output);
+ }
+
+ public static function makeTag($number, $type)
+ {
+ return ($number << 3) | self::getWireType($type);
+ }
+
+ public static function tagSize($field)
+ {
+ $tag = self::makeTag($field->getNumber(), $field->getType());
+ return self::varint32Size($tag);
+ }
+
+ public static function varint32Size($value)
+ {
+ if ($value < 0) {
+ return 5;
+ }
+ if ($value < (1 << 7)) {
+ return 1;
+ }
+ if ($value < (1 << 14)) {
+ return 2;
+ }
+ if ($value < (1 << 21)) {
+ return 3;
+ }
+ if ($value < (1 << 28)) {
+ return 4;
+ }
+ return 5;
+ }
+
+ public static function sint32Size($value)
+ {
+ $value = self::zigZagEncode32($value);
+ return self::varint32Size($value);
+ }
+
+ public static function sint64Size($value)
+ {
+ $value = GPBUtil::Int64($value);
+ $value = self::zigZagEncode64($value);
+ return self::varint64Size($value->toInteger());
+ }
+
+ public static function varint64Size($value)
+ {
+ if ($value < 0) {
+ return 10;
+ }
+ if ($value < (1 << 7)) {
+ return 1;
+ }
+ if ($value < (1 << 14)) {
+ return 2;
+ }
+ if ($value < (1 << 21)) {
+ return 3;
+ }
+ if ($value < (1 << 28)) {
+ return 4;
+ }
+ if ($value < (1 << 35)) {
+ return 5;
+ }
+ if ($value < (1 << 42)) {
+ return 6;
+ }
+ if ($value < (1 << 49)) {
+ return 7;
+ }
+ if ($value < (1 << 56)) {
+ return 8;
+ }
+ return 9;
+ }
+
+ public static function serializeFieldToStream(
+ $value,
+ $field,
+ $need_tag,
+ &$output)
+ {
+ if ($need_tag) {
+ if (!GPBWire::writeTag(
+ $output,
+ self::makeTag(
+ $field->getNumber(),
+ $field->getType()))) {
+ return false;
+ }
+ }
+ switch ($field->getType()) {
+ case GPBType::DOUBLE:
+ if (!GPBWire::writeDouble($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::FLOAT:
+ if (!GPBWire::writeFloat($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::INT64:
+ if (!GPBWire::writeInt64($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::UINT64:
+ if (!GPBWire::writeUint64($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::INT32:
+ if (!GPBWire::writeInt32($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::FIXED32:
+ if (!GPBWire::writeFixed32($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::FIXED64:
+ if (!GPBWire::writeFixed64($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::BOOL:
+ if (!GPBWire::writeBool($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::STRING:
+ if (!GPBWire::writeString($output, $value)) {
+ return false;
+ }
+ break;
+ // case GPBType::GROUP:
+ // echo "GROUP\xA";
+ // trigger_error("Not implemented.", E_ERROR);
+ // break;
+ case GPBType::MESSAGE:
+ if (!GPBWire::writeMessage($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::BYTES:
+ if (!GPBWire::writeBytes($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::UINT32:
+ if (!GPBWire::writeUint32($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::ENUM:
+ if (!GPBWire::writeInt32($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::SFIXED32:
+ if (!GPBWire::writeSfixed32($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::SFIXED64:
+ if (!GPBWire::writeSfixed64($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::SINT32:
+ if (!GPBWire::writeSint32($output, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::SINT64:
+ if (!GPBWire::writeSint64($output, $value)) {
+ return false;
+ }
+ break;
+ default:
+ user_error("Unsupported type.");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/php/src/Google/Protobuf/Internal/InputStream.php b/php/src/Google/Protobuf/Internal/InputStream.php
new file mode 100644
index 00000000..18d07075
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/InputStream.php
@@ -0,0 +1,323 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+use Google\Protobuf\Internal\Uint64;
+
+class InputStream
+{
+
+ private $buffer;
+ private $buffer_size_after_limit;
+ private $buffer_end;
+ private $current;
+ private $current_limit;
+ private $legitimate_message_end;
+ private $recursion_budget;
+ private $recursion_limit;
+ private $total_bytes_limit;
+ private $total_bytes_read;
+
+ const MAX_VARINT_BYTES = 10;
+ const MAX_VARINT32_BYTES = 5;
+ const DEFAULT_RECURSION_LIMIT = 100;
+ const DEFAULT_TOTAL_BYTES_LIMIT = 33554432; // 32 << 20, 32MB
+
+ public function __construct($buffer)
+ {
+ $start = 0;
+ $end = strlen($buffer);
+ $this->buffer = $buffer;
+ $this->buffer_size_after_limit = 0;
+ $this->buffer_end = $end;
+ $this->current = $start;
+ $this->current_limit = $end;
+ $this->legitimate_message_end = false;
+ $this->recursion_budget = self::DEFAULT_RECURSION_LIMIT;
+ $this->recursion_limit = self::DEFAULT_RECURSION_LIMIT;
+ $this->total_bytes_limit = self::DEFAULT_TOTAL_BYTES_LIMIT;
+ $this->total_bytes_read = $end - $start;
+ }
+
+ private function advance($amount)
+ {
+ $this->current += $amount;
+ }
+
+ private function bufferSize()
+ {
+ return $this->buffer_end - $this->current;
+ }
+
+ private function current()
+ {
+ return $this->total_bytes_read -
+ ($this->buffer_end - $this->current +
+ $this->buffer_size_after_limit);
+ }
+
+ private function recomputeBufferLimits()
+ {
+ $this->buffer_end += $this->buffer_size_after_limit;
+ $closest_limit = min($this->current_limit, $this->total_bytes_limit);
+ if ($closest_limit < $this->total_bytes_read) {
+ // The limit position is in the current buffer. We must adjust the
+ // buffer size accordingly.
+ $this->buffer_size_after_limit = $this->total_bytes_read -
+ $closest_limit;
+ $this->buffer_end -= $this->buffer_size_after_limit;
+ } else {
+ $this->buffer_size_after_limit = 0;
+ }
+ }
+
+ private function consumedEntireMessage()
+ {
+ return $this->legitimate_message_end;
+ }
+
+ /**
+ * Read uint32 into $var. Advance buffer with consumed bytes. If the
+ * contained varint is larger than 32 bits, discard the high order bits.
+ * @param $var.
+ */
+ public function readVarint32(&$var)
+ {
+ if (!$this->readVarint64($var)) {
+ return false;
+ }
+ $var = $var->toInteger() & 0xFFFFFFFF;
+ // Convert large uint32 to int32.
+ if (PHP_INT_SIZE === 8 && ($var > 0x7FFFFFFF)) {
+ $var = $var | (0xFFFFFFFF << 32);
+ }
+ return true;
+ }
+
+ /**
+ * Read Uint64 into $var. Advance buffer with consumed bytes.
+ * @param $var.
+ */
+ public function readVarint64(&$var)
+ {
+ $result = new Uint64(0);
+ $count = 0;
+ $b = 0;
+
+ do {
+ if ($this->current === $this->buffer_end) {
+ return false;
+ }
+ if ($count === self::MAX_VARINT_BYTES) {
+ return false;
+ }
+ $b = ord($this->buffer[$this->current]);
+ $result->bitOr((new Uint64($b & 0x7F))->leftShift(7 * $count));
+ $this->advance(1);
+ $count += 1;
+ } while ($b & 0x80);
+
+ $var = $result;
+ return true;
+ }
+
+ /**
+ * Read int into $var. If the result is larger than the largest integer, $var
+ * will be -1. Advance buffer with consumed bytes.
+ * @param $var.
+ */
+ public function readVarintSizeAsInt(&$var)
+ {
+ if (!$this->readVarint64($var)) {
+ return false;
+ }
+ $var = $var->toInteger();
+ return true;
+ }
+
+ /**
+ * Read 32-bit unsiged integer to $var. If the buffer has less than 4 bytes,
+ * return false. Advance buffer with consumed bytes.
+ * @param $var.
+ */
+ public function readLittleEndian32(&$var)
+ {
+ $data = null;
+ if (!$this->readRaw(4, $data)) {
+ return false;
+ }
+ $var = unpack('V', $data);
+ $var = $var[1];
+ return true;
+ }
+
+ /**
+ * Read 64-bit unsiged integer to $var. If the buffer has less than 8 bytes,
+ * return false. Advance buffer with consumed bytes.
+ * @param $var.
+ */
+ public function readLittleEndian64(&$var)
+ {
+ $data = null;
+ if (!$this->readRaw(4, $data)) {
+ return false;
+ }
+ $low = unpack('V', $data)[1];
+ if (!$this->readRaw(4, $data)) {
+ return false;
+ }
+ $high = unpack('V', $data)[1];
+ $var = Uint64::newValue($high, $low);
+ return true;
+ }
+
+ /**
+ * Read tag into $var. Advance buffer with consumed bytes.
+ * @param $var.
+ */
+ public function readTag()
+ {
+ if ($this->current === $this->buffer_end) {
+ // Make sure that it failed due to EOF, not because we hit
+ // total_bytes_limit, which, unlike normal limits, is not a valid
+ // place to end a message.
+ $current_position = $this->total_bytes_read -
+ $this->buffer_size_after_limit;
+ if ($current_position >= $this->total_bytes_limit) {
+ // Hit total_bytes_limit_. But if we also hit the normal limit,
+ // we're still OK.
+ $this->legitimate_message_end =
+ ($this->current_limit === $this->total_bytes_limit);
+ } else {
+ $this->legitimate_message_end = true;
+ }
+ return 0;
+ }
+
+ $result = 0;
+ // The larget tag is 2^29 - 1, which can be represented by int32.
+ $success = $this->readVarint32($result);
+ if ($success) {
+ return $result;
+ } else {
+ return 0;
+ }
+ }
+
+ public function readRaw($size, &$buffer)
+ {
+ $current_buffer_size = 0;
+ if ($this->bufferSize() < $size) {
+ return false;
+ }
+
+ $buffer = substr($this->buffer, $this->current, $size);
+ $this->advance($size);
+
+ return true;
+ }
+
+ /* Places a limit on the number of bytes that the stream may read, starting
+ * from the current position. Once the stream hits this limit, it will act
+ * like the end of the input has been reached until popLimit() is called.
+ *
+ * As the names imply, the stream conceptually has a stack of limits. The
+ * shortest limit on the stack is always enforced, even if it is not the top
+ * limit.
+ *
+ * The value returned by pushLimit() is opaque to the caller, and must be
+ * passed unchanged to the corresponding call to popLimit().
+ *
+ * @param integer $byte_limit
+ */
+ public function pushLimit($byte_limit)
+ {
+ // Current position relative to the beginning of the stream.
+ $current_position = $this->current();
+ $old_limit = $this->current_limit;
+
+ // security: byte_limit is possibly evil, so check for negative values
+ // and overflow.
+ if ($byte_limit >= 0 && $byte_limit <= PHP_INT_MAX - $current_position) {
+ $this->current_limit = $current_position + $byte_limit;
+ } else {
+ // Negative or overflow.
+ $this->current_limit = PHP_INT_MAX;
+ }
+
+ // We need to enforce all limits, not just the new one, so if the previous
+ // limit was before the new requested limit, we continue to enforce the
+ // previous limit.
+ $this->current_limit = min($this->current_limit, $old_limit);
+
+ $this->recomputeBufferLimits();
+ return $old_limit;
+ }
+
+ /* The limit passed in is actually the *old* limit, which we returned from
+ * PushLimit().
+ *
+ * @param integer $byte_limit
+ */
+ public function popLimit($byte_limit)
+ {
+ $this->current_limit = $byte_limit;
+ $this->recomputeBufferLimits();
+ // We may no longer be at a legitimate message end. ReadTag() needs to
+ // be called again to find out.
+ $this->legitimate_message_end = false;
+ }
+
+ public function incrementRecursionDepthAndPushLimit(
+ $byte_limit, &$old_limit, &$recursion_budget)
+ {
+ $old_limit = $this->pushLimit($byte_limit);
+ $recursion_limit = --$this->recursion_limit;
+ }
+
+ public function decrementRecursionDepthAndPopLimit($byte_limit)
+ {
+ $result = $this->consumedEntireMessage();
+ $this->popLimit($byte_limit);
+ ++$this->recursion_budget;
+ return $result;
+ }
+
+ public function bytesUntilLimit()
+ {
+ if ($this->current_limit === PHP_INT_MAX) {
+ return -1;
+ }
+ return $this->current_limit - $this->current;
+ }
+}
diff --git a/php/src/Google/Protobuf/Internal/MapEntry.php b/php/src/Google/Protobuf/Internal/MapEntry.php
new file mode 100644
index 00000000..926645e1
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/MapEntry.php
@@ -0,0 +1,57 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+use Google\Protobuf\Internal\Message;
+
+class MapEntry extends Message
+{
+ public $key;
+ public $value;
+
+ public function setKey(&$key) {
+ $this->key = $key;
+ }
+
+ public function getKey() {
+ return $this->key;
+ }
+
+ public function setValue(&$value) {
+ $this->value = $value;
+ }
+
+ public function getValue() {
+ return $this->value;
+ }
+}
diff --git a/php/src/Google/Protobuf/Internal/MapField.php b/php/src/Google/Protobuf/Internal/MapField.php
new file mode 100644
index 00000000..14ee7ebe
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/MapField.php
@@ -0,0 +1,321 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/**
+ * MapField and MapFieldIter are used by generated protocol message classes to
+ * manipulate map fields.
+ */
+
+namespace Google\Protobuf\Internal;
+
+/**
+ * MapFieldIter is used to iterate MapField. It is also need for the foreach
+ * syntax.
+ */
+class MapFieldIter implements \Iterator
+{
+
+ /**
+ * @ignore
+ */
+ private $container;
+
+ /**
+ * Create iterator instance for MapField.
+ *
+ * @param MapField The MapField instance for which this iterator is
+ * created.
+ * @ignore
+ */
+ public function __construct($container)
+ {
+ $this->container = $container;
+ }
+
+ /**
+ * Reset the status of the iterator
+ *
+ * @return void
+ */
+ public function rewind()
+ {
+ return reset($this->container);
+ }
+
+ /**
+ * Return the element at the current position.
+ *
+ * @return object The element at the current position.
+ */
+ public function current()
+ {
+ return current($this->container);
+ }
+
+ /**
+ * Return the current key.
+ *
+ * @return object The current key.
+ */
+ public function key()
+ {
+ return key($this->container);
+ }
+
+ /**
+ * Move to the next position.
+ *
+ * @return void
+ */
+ public function next()
+ {
+ return next($this->container);
+ }
+
+ /**
+ * Check whether there are more elements to iterate.
+ *
+ * @return bool True if there are more elements to iterate.
+ */
+ public function valid()
+ {
+ return key($this->container) !== null;
+ }
+}
+
+/**
+ * @ignore
+ */
+function checkKey($key_type, &$key)
+{
+ switch ($key_type) {
+ case GPBType::INT32:
+ GPBUtil::checkInt32($key);
+ break;
+ case GPBType::UINT32:
+ GPBUtil::checkUint32($key);
+ break;
+ case GPBType::INT64:
+ GPBUtil::checkInt64($key);
+ break;
+ case GPBType::UINT64:
+ GPBUtil::checkUint64($key);
+ break;
+ case GPBType::FIXED64:
+ GPBUtil::checkUint64($key);
+ break;
+ case GPBType::FIXED32:
+ GPBUtil::checkUint32($key);
+ break;
+ case GPBType::SFIXED64:
+ GPBUtil::checkInt64($key);
+ break;
+ case GPBType::SFIXED32:
+ GPBUtil::checkInt32($key);
+ break;
+ case GPBType::SINT64:
+ GPBUtil::checkInt64($key);
+ break;
+ case GPBType::SINT32:
+ GPBUtil::checkInt32($key);
+ break;
+ case GPBType::BOOL:
+ GPBUtil::checkBool($key);
+ break;
+ case GPBType::STRING:
+ GPBUtil::checkString($key, true);
+ break;
+ default:
+ var_dump($key_type);
+ trigger_error(
+ "Given type cannot be map key.",
+ E_USER_ERROR);
+ break;
+ }
+}
+
+/**
+ * MapField is used by generated protocol message classes to manipulate map
+ * fields. It can be used like native PHP array.
+ */
+class MapField implements \ArrayAccess, \IteratorAggregate, \Countable
+{
+ /**
+ * @ignore
+ */
+ private $container;
+ /**
+ * @ignore
+ */
+ private $key_type;
+ /**
+ * @ignore
+ */
+ private $value_type;
+ /**
+ * @ignore
+ */
+ private $value_klass;
+
+ /**
+ * Constructs an instance of MapField.
+ *
+ * @param long $key_type Type of the stored key element.
+ * @param long $value_type Type of the stored value element.
+ * @param string $klass Message/Enum class name of value instance
+ * (message/enum fields only).
+ * @ignore
+ */
+ public function __construct($key_type, $value_type, $klass = null)
+ {
+ $this->container = [];
+ $this->key_type = $key_type;
+ $this->value_type = $value_type;
+ $this->klass = $klass;
+ }
+
+ /**
+ * Return the element at the given key.
+ *
+ * This will also be called for: $ele = $arr[$key]
+ *
+ * @param object $key The key of the element to be fetched.
+ * @return object The stored element at given key.
+ * @throws ErrorException Invalid type for index.
+ * @throws ErrorException Non-existing index.
+ */
+ public function offsetGet($key)
+ {
+ return $this->container[$key];
+ }
+
+ /**
+ * Assign the element at the given key.
+ *
+ * This will also be called for: $arr[$key] = $value
+ *
+ * @param object $key The key of the element to be fetched.
+ * @param object $value The element to be assigned.
+ * @return void
+ * @throws ErrorException Invalid type for key.
+ * @throws ErrorException Invalid type for value.
+ * @throws ErrorException Non-existing key.
+ */
+ public function offsetSet($key, $value)
+ {
+ checkKey($this->key_type, $key);
+
+ switch ($this->value_type) {
+ case GPBType::INT32:
+ GPBUtil::checkInt32($value);
+ break;
+ case GPBType::UINT32:
+ GPBUtil::checkUint32($value);
+ break;
+ case GPBType::INT64:
+ GPBUtil::checkInt64($value);
+ break;
+ case GPBType::UINT64:
+ GPBUtil::checkUint64($value);
+ break;
+ case GPBType::FLOAT:
+ GPBUtil::checkFloat($value);
+ break;
+ case GPBType::DOUBLE:
+ GPBUtil::checkDouble($value);
+ break;
+ case GPBType::BOOL:
+ GPBUtil::checkBool($value);
+ break;
+ case GPBType::STRING:
+ GPBUtil::checkString($value, true);
+ break;
+ case GPBType::MESSAGE:
+ GPBUtil::checkMessage($value, $this->klass);
+ break;
+ default:
+ break;
+ }
+
+ $this->container[$key] = $value;
+ }
+
+ /**
+ * Remove the element at the given key.
+ *
+ * This will also be called for: unset($arr)
+ *
+ * @param object $key The key of the element to be removed.
+ * @return void
+ * @throws ErrorException Invalid type for key.
+ */
+ public function offsetUnset($key)
+ {
+ checkKey($this->key_type, $key);
+ unset($this->container[$key]);
+ }
+
+ /**
+ * Check the existence of the element at the given key.
+ *
+ * This will also be called for: isset($arr)
+ *
+ * @param object $key The key of the element to be removed.
+ * @return bool True if the element at the given key exists.
+ * @throws ErrorException Invalid type for key.
+ */
+ public function offsetExists($key)
+ {
+ checkKey($this->key_type, $key);
+ return isset($this->container[$key]);
+ }
+
+ /**
+ * @ignore
+ */
+ public function getIterator()
+ {
+ return new MapFieldIter($this->container);
+ }
+
+ /**
+ * Return the number of stored elements.
+ *
+ * This will also be called for: count($arr)
+ *
+ * @return integer The number of stored elements.
+ */
+ public function count()
+ {
+ return count($this->container);
+ }
+}
diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php
new file mode 100644
index 00000000..a8de6a11
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/Message.php
@@ -0,0 +1,671 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/**
+ * Defines Message, the parent class extended by all protocol message classes.
+ */
+
+namespace Google\Protobuf\Internal;
+
+use Google\Protobuf\Internal\InputStream;
+use Google\Protobuf\Internal\OutputStream;
+use Google\Protobuf\Internal\DescriptorPool;
+use Google\Protobuf\Internal\GPBLabel;
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\GPBWire;
+use Google\Protobuf\Internal\MapEntry;
+use Google\Protobuf\Internal\RepeatedField;
+
+/**
+ * Parent class of all proto messages. Users should not instantiate this class
+ * or extend this class or its child classes by their own. See the comment of
+ * specific functions for more details.
+ */
+class Message
+{
+
+ /**
+ * @ignore
+ */
+ private $desc;
+
+ /**
+ * @ignore
+ */
+ public function __construct($desc = NULL)
+ {
+ // MapEntry message is shared by all types of map fields, whose
+ // descriptors are different from each other. Thus, we cannot find a
+ // specific descriptor from the descriptor pool.
+ if (get_class($this) === 'Google\Protobuf\Internal\MapEntry') {
+ $this->desc = $desc;
+ return;
+ }
+ $pool = DescriptorPool::getGeneratedPool();
+ $this->desc = $pool->getDescriptorByClassName(get_class($this));
+ foreach ($this->desc->getField() as $field) {
+ $setter = $field->getSetter();
+ if ($field->isMap()) {
+ $message_type = $field->getMessageType();
+ $key_field = $message_type->getFieldByNumber(1);
+ $value_field = $message_type->getFieldByNumber(2);
+ switch ($value_field->getType()) {
+ case GPBType::MESSAGE:
+ case GPBType::GROUP:
+ $this->$setter(
+ new MapField(
+ $key_field->getType(),
+ $value_field->getType(),
+ $value_field->getMessageType()->getClass()));
+ break;
+ case GPBType::ENUM:
+ $this->$setter(
+ new MapField(
+ $key_field->getType(),
+ $value_field->getType(),
+ $value_field->getEnumType()->getClass()));
+ break;
+ default:
+ $this->$setter(new MapField($key_field->getType(),
+ $value_field->getType()));
+ break;
+ }
+ } else if ($field->getLabel() === GPBLabel::REPEATED) {
+ switch ($field->getType()) {
+ case GPBType::MESSAGE:
+ case GPBType::GROUP:
+ $this->$setter(
+ new RepeatedField(
+ $field->getType(),
+ $field->getMessageType()->getClass()));
+ break;
+ case GPBType::ENUM:
+ $this->$setter(
+ new RepeatedField(
+ $field->getType(),
+ $field->getEnumType()->getClass()));
+ break;
+ default:
+ $this->$setter(new RepeatedField($field->getType()));
+ break;
+ }
+ } else if ($field->getOneofIndex() !== -1) {
+ $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
+ $oneof_name = $oneof->getName();
+ $this->$oneof_name = new OneofField($oneof);
+ }
+ }
+ }
+
+ protected function readOneof($number)
+ {
+ $field = $this->desc->getFieldByNumber($number);
+ $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
+ $oneof_name = $oneof->getName();
+ $oneof_field = $this->$oneof_name;
+ if ($number === $oneof_field->getNumber()) {
+ return $oneof_field->getValue();
+ } else {
+ return $this->defaultValue($field);
+ }
+ }
+
+ protected function writeOneof($number, $value)
+ {
+ $field = $this->desc->getFieldByNumber($number);
+ $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
+ $oneof_name = $oneof->getName();
+ $oneof_field = $this->$oneof_name;
+ $oneof_field->setValue($value);
+ $oneof_field->setFieldName($field->getName());
+ $oneof_field->setNumber($number);
+ }
+
+ /**
+ * @ignore
+ */
+ private function defaultValue($field)
+ {
+ $value = null;
+
+ switch ($field->getType()) {
+ case GPBType::DOUBLE:
+ case GPBType::FLOAT:
+ return 0.0;
+ case GPBType::UINT32:
+ case GPBType::UINT64:
+ case GPBType::INT32:
+ case GPBType::INT64:
+ case GPBType::FIXED32:
+ case GPBType::FIXED64:
+ case GPBType::SFIXED32:
+ case GPBType::SFIXED64:
+ case GPBType::SINT32:
+ case GPBType::SINT64:
+ case GPBType::ENUM:
+ return 0;
+ case GPBType::BOOL:
+ return false;
+ case GPBType::STRING:
+ case GPBType::BYTES:
+ return "";
+ case GPBType::GROUP:
+ case GPBType::MESSAGE:
+ return null;
+ default:
+ user_error("Unsupported type.");
+ return false;
+ }
+ }
+
+ /**
+ * @ignore
+ */
+ private static function parseFieldFromStreamNoTag($input, $field, &$value)
+ {
+ switch ($field->getType()) {
+ case GPBType::DOUBLE:
+ if (!GPBWire::readDouble($input, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::FLOAT:
+ if (!GPBWire::readFloat($input, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::INT64:
+ if (!GPBWire::readInt64($input, $value)) {
+ return false;
+ }
+ $value = $value->toInteger();
+ break;
+ case GPBType::UINT64:
+ if (!GPBWire::readUint64($input, $value)) {
+ return false;
+ }
+ $value = $value->toInteger();
+ break;
+ case GPBType::INT32:
+ if (!GPBWire::readInt32($input, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::FIXED64:
+ if (!GPBWire::readFixed64($input, $value)) {
+ return false;
+ }
+ $value = $value->toInteger();
+ break;
+ case GPBType::FIXED32:
+ if (!GPBWire::readFixed32($input, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::BOOL:
+ if (!GPBWire::readBool($input, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::STRING:
+ // TODO(teboring): Add utf-8 check.
+ if (!GPBWire::readString($input, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::GROUP:
+ echo "GROUP\xA";
+ trigger_error("Not implemented.", E_ERROR);
+ break;
+ case GPBType::MESSAGE:
+ if ($field->isMap()) {
+ $value = new MapEntry($field->getMessageType());
+ } else {
+ $klass = $field->getMessageType()->getClass();
+ $value = new $klass;
+ }
+ if (!GPBWire::readMessage($input, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::BYTES:
+ if (!GPBWire::readString($input, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::UINT32:
+ if (!GPBWire::readUint32($input, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::ENUM:
+ // TODO(teboring): Check unknown enum value.
+ if (!GPBWire::readInt32($input, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::SFIXED32:
+ if (!GPBWire::readSfixed32($input, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::SFIXED64:
+ if (!GPBWire::readSfixed64($input, $value)) {
+ return false;
+ }
+ $value = $value->toInteger();
+ break;
+ case GPBType::SINT32:
+ if (!GPBWire::readSint32($input, $value)) {
+ return false;
+ }
+ break;
+ case GPBType::SINT64:
+ if (!GPBWire::readSint64($input, $value)) {
+ return false;
+ }
+ $value = $value->toInteger();
+ break;
+ default:
+ user_error("Unsupported type.");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @ignore
+ */
+ private function parseFieldFromStream($tag, $input, $field)
+ {
+ $value = null;
+ $field_type = $field->getType();
+
+ $value_format = GPBWire::UNKNOWN;
+ if (GPBWire::getTagWireType($tag) ===
+ GPBWire::getWireType($field_type)) {
+ $value_format = GPBWire::NORMAL_FORMAT;
+ } elseif ($field->isPackable() &&
+ GPBWire::getTagWireType($tag) ===
+ GPBWire::WIRETYPE_LENGTH_DELIMITED) {
+ $value_format = GPBWire::PACKED_FORMAT;
+ }
+
+ if ($value_format === GPBWire::NORMAL_FORMAT) {
+ if (!self::parseFieldFromStreamNoTag($input, $field, $value)) {
+ return false;
+ }
+ } elseif ($value_format === GPBWire::PACKED_FORMAT) {
+ $length = 0;
+ if (!GPBWire::readInt32($input, $length)) {
+ return false;
+ }
+ $limit = $input->pushLimit($length);
+ $getter = $field->getGetter();
+ while ($input->bytesUntilLimit() > 0) {
+ if (!self::parseFieldFromStreamNoTag($input, $field, $value)) {
+ return false;
+ }
+ $this->$getter()[] = $value;
+ }
+ $input->popLimit($limit);
+ return true;
+ } else {
+ return false;
+ }
+
+ if ($field->isMap()) {
+ $getter = $field->getGetter();
+ $this->$getter()[$value->getKey()] = $value->getValue();
+ } else if ($field->isRepeated()) {
+ $getter = $field->getGetter();
+ $this->$getter()[] = $value;
+ } else {
+ $setter = $field->getSetter();
+ $this->$setter($value);
+ }
+
+ return true;
+ }
+
+ /**
+ * Parses a protocol buffer contained in a string.
+ *
+ * This function takes a string in the (non-human-readable) binary wire
+ * format, matching the encoding output by encode().
+ *
+ * @param string $data Binary protobuf data.
+ * @return bool Return true on success.
+ */
+ public function decode($data)
+ {
+ $input = new InputStream($data);
+ $this->parseFromStream($input);
+ }
+
+ /**
+ * @ignore
+ */
+ public function parseFromStream($input)
+ {
+ while (true) {
+ $tag = $input->readTag();
+ // End of input. This is a valid place to end, so return true.
+ if ($tag === 0) {
+ return true;
+ }
+
+ $number = GPBWire::getTagFieldNumber($tag);
+ $field = $this->desc->getFieldByNumber($number);
+
+ if (!$this->parseFieldFromStream($tag, $input, $field)) {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * @ignore
+ */
+ private function serializeSingularFieldToStream($field, &$output)
+ {
+ if (!$this->existField($field)) {
+ return true;
+ }
+ $getter = $field->getGetter();
+ $value = $this->$getter();
+ if (!GPBWire::serializeFieldToStream($value, $field, true, $output)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @ignore
+ */
+ private function serializeRepeatedFieldToStream($field, &$output)
+ {
+ $getter = $field->getGetter();
+ $values = $this->$getter();
+ $count = count($values);
+ if ($count === 0) {
+ return true;
+ }
+
+ $packed = $field->getPacked();
+ if ($packed) {
+ if (!GPBWire::writeTag(
+ $output,
+ GPBWire::makeTag($field->getNumber(), GPBType::STRING))) {
+ return false;
+ }
+ $size = 0;
+ foreach ($values as $value) {
+ $size += $this->fieldDataOnlyByteSize($field, $value);
+ }
+ if (!$output->writeVarint32($size)) {
+ return false;
+ }
+ }
+
+ foreach ($values as $value) {
+ if (!GPBWire::serializeFieldToStream(
+ $value,
+ $field,
+ !$packed,
+ $output)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @ignore
+ */
+ private function serializeMapFieldToStream($field, $output)
+ {
+ $getter = $field->getGetter();
+ $values = $this->$getter();
+ $count = count($values);
+ if ($count === 0) {
+ return true;
+ }
+
+ foreach ($values as $key => $value) {
+ $map_entry = new MapEntry($field->getMessageType());
+ $map_entry->setKey($key);
+ $map_entry->setValue($value);
+ if (!GPBWire::serializeFieldToStream(
+ $map_entry,
+ $field,
+ true,
+ $output)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @ignore
+ */
+ private function serializeFieldToStream(&$output, $field)
+ {
+ if ($field->isMap()) {
+ return $this->serializeMapFieldToStream($field, $output);
+ } elseif ($field->isRepeated()) {
+ return $this->serializeRepeatedFieldToStream($field, $output);
+ } else {
+ return $this->serializeSingularFieldToStream($field, $output);
+ }
+ }
+
+ /**
+ * @ignore
+ */
+ public function serializeToStream(&$output)
+ {
+ $fields = $this->desc->getField();
+ foreach ($fields as $field) {
+ if (!$this->serializeFieldToStream($output, $field)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Serialize the message to string.
+ * @return string Serialized binary protobuf data.
+ */
+ public function encode()
+ {
+ $output = new OutputStream($this->byteSize());
+ $this->serializeToStream($output);
+ return $output->getData();
+ }
+
+ /**
+ * @ignore
+ */
+ private function existField($field)
+ {
+ $getter = $field->getGetter();
+ $value = $this->$getter();
+ return $value !== $this->defaultValue($field);
+ }
+
+ /**
+ * @ignore
+ */
+ private function repeatedFieldDataOnlyByteSize($field)
+ {
+ $size = 0;
+
+ $getter = $field->getGetter();
+ $values = $this->$getter();
+ $count = count($values);
+ if ($count !== 0) {
+ $size += $count * GPBWire::tagSize($field);
+ foreach ($values as $value) {
+ $size += $this->singularFieldDataOnlyByteSize($field);
+ }
+ }
+ }
+
+ /**
+ * @ignore
+ */
+ private function fieldDataOnlyByteSize($field, $value)
+ {
+ $size = 0;
+
+ switch ($field->getType()) {
+ case GPBType::BOOL:
+ $size += 1;
+ break;
+ case GPBType::FLOAT:
+ case GPBType::FIXED32:
+ case GPBType::SFIXED32:
+ $size += 4;
+ break;
+ case GPBType::DOUBLE:
+ case GPBType::FIXED64:
+ case GPBType::SFIXED64:
+ $size += 8;
+ break;
+ case GPBType::UINT32:
+ case GPBType::INT32:
+ case GPBType::ENUM:
+ $size += GPBWire::varint32Size($value);
+ break;
+ case GPBType::UINT64:
+ case GPBType::INT64:
+ $size += GPBWire::varint64Size($value);
+ break;
+ case GPBType::SINT32:
+ $size += GPBWire::sint32Size($value);
+ break;
+ case GPBType::SINT64:
+ $size += GPBWire::sint64Size($value);
+ break;
+ case GPBType::STRING:
+ case GPBType::BYTES:
+ $size += strlen($value);
+ $size += GPBWire::varint32Size($size);
+ break;
+ case GPBType::MESSAGE:
+ $size += $value->byteSize();
+ $size += GPBWire::varint32Size($size);
+ break;
+ case GPBType::GROUP:
+ // TODO(teboring): Add support.
+ user_error("Unsupported type.");
+ break;
+ default:
+ user_error("Unsupported type.");
+ return 0;
+ }
+
+ return $size;
+ }
+
+ /**
+ * @ignore
+ */
+ private function fieldByteSize($field)
+ {
+ $size = 0;
+ if ($field->isMap()) {
+ $getter = $field->getGetter();
+ $values = $this->$getter();
+ $count = count($values);
+ if ($count !== 0) {
+ $size += $count * GPBWire::tagSize($field);
+ $message_type = $field->getMessageType();
+ $key_field = $message_type->getFieldByNumber(1);
+ $value_field = $message_type->getFieldByNumber(2);
+ foreach ($values as $key => $value) {
+ $data_size = 0;
+ $data_size += $this->fieldDataOnlyByteSize($key_field, $key);
+ $data_size += $this->fieldDataOnlyByteSize(
+ $value_field,
+ $value);
+ $data_size += GPBWire::tagSize($key_field);
+ $data_size += GPBWire::tagSize($value_field);
+ $size += GPBWire::varint32Size($data_size) + $data_size;
+ }
+ }
+ } elseif ($field->isRepeated()) {
+ $getter = $field->getGetter();
+ $values = $this->$getter();
+ $count = count($values);
+ if ($count !== 0) {
+ if ($field->getPacked()) {
+ $data_size = 0;
+ foreach ($values as $value) {
+ $data_size += $this->fieldDataOnlyByteSize($field, $value);
+ }
+ $size += GPBWire::tagSize($field);
+ $size += GPBWire::varint32Size($data_size);
+ $size += $data_size;
+ } else {
+ $size += $count * GPBWire::tagSize($field);
+ foreach ($values as $value) {
+ $size += $this->fieldDataOnlyByteSize($field, $value);
+ }
+ }
+ }
+ } elseif ($this->existField($field)) {
+ $size += GPBWire::tagSize($field);
+ $getter = $field->getGetter();
+ $value = $this->$getter();
+ $size += $this->fieldDataOnlyByteSize($field, $value);
+ }
+ return $size;
+ }
+
+ /**
+ * @ignore
+ */
+ public function byteSize()
+ {
+ $size = 0;
+
+ $fields = $this->desc->getField();
+ foreach ($fields as $field) {
+ $size += $this->fieldByteSize($field);
+ }
+ return $size;
+ }
+}
diff --git a/php/src/Google/Protobuf/Internal/MessageBuilderContext.php b/php/src/Google/Protobuf/Internal/MessageBuilderContext.php
new file mode 100644
index 00000000..2724d267
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/MessageBuilderContext.php
@@ -0,0 +1,120 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+use Google\Protobuf\Internal\GPBLabel;
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\Descriptor;
+use Google\Protobuf\Internal\FieldDescriptor;
+
+class MessageBuilderContext
+{
+
+ private $descriptor;
+ private $pool;
+
+ public function __construct($full_name, $klass, $pool)
+ {
+ $this->descriptor = new Descriptor();
+ $this->descriptor->setFullName($full_name);
+ $this->descriptor->setClass($klass);
+ $this->pool = $pool;
+ }
+
+ private function getFieldDescriptor($name, $label, $type,
+ $number, $type_name = null)
+ {
+ $field = new FieldDescriptor();
+ $field->setName($name);
+ $camel_name = implode('', array_map('ucwords', explode('_', $name)));
+ $field->setGetter('get' . $camel_name);
+ $field->setSetter('set' . $camel_name);
+ $field->setType($type);
+ $field->setNumber($number);
+ $field->setLabel($label);
+
+ // At this time, the message/enum type may have not been added to pool.
+ // So we use the type name as place holder and will replace it with the
+ // actual descriptor in cross building.
+ switch ($type) {
+ case GPBType::MESSAGE:
+ $field->setMessageType($type_name);
+ break;
+ case GPBType::ENUM:
+ $field->setEnumType($type_name);
+ break;
+ default:
+ break;
+ }
+
+ return $field;
+ }
+
+ public function optional($name, $type, $number, $type_name = null)
+ {
+ $this->descriptor->addField($this->getFieldDescriptor(
+ $name,
+ GPBLabel::OPTIONAL,
+ $type,
+ $number,
+ $type_name));
+ return $this;
+ }
+
+ public function repeated($name, $type, $number, $type_name = null)
+ {
+ $this->descriptor->addField($this->getFieldDescriptor(
+ $name,
+ GPBLabel::REPEATED,
+ $type,
+ $number,
+ $type_name));
+ return $this;
+ }
+
+ public function required($name, $type, $number, $type_name = null)
+ {
+ $this->descriptor->addField($this->getFieldDescriptor(
+ $name,
+ GPBLabel::REQUIRED,
+ $type,
+ $number,
+ $type_name));
+ return $this;
+ }
+
+ public function finalizeToPool()
+ {
+ $this->pool->addDescriptor($this->descriptor);
+ }
+}
diff --git a/php/src/Google/Protobuf/Internal/OneofField.php b/php/src/Google/Protobuf/Internal/OneofField.php
new file mode 100644
index 00000000..2c689e83
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/OneofField.php
@@ -0,0 +1,77 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+class OneofField
+{
+
+ private $desc;
+ private $field_name;
+ private $number = 0;
+ private $value;
+
+ public function __construct($desc)
+ {
+ $this->desc = $desc;
+ }
+
+ public function setValue($value)
+ {
+ $this->value = $value;
+ }
+
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ public function setFieldName($field_name)
+ {
+ $this->field_name = $field_name;
+ }
+
+ public function getFieldName()
+ {
+ return $this->field_name;
+ }
+
+ public function setNumber($number)
+ {
+ $this->number = $number;
+ }
+
+ public function getNumber()
+ {
+ return $this->number;
+ }
+}
diff --git a/php/src/Google/Protobuf/Internal/OutputStream.php b/php/src/Google/Protobuf/Internal/OutputStream.php
new file mode 100644
index 00000000..fcc5ce6d
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/OutputStream.php
@@ -0,0 +1,143 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+class OutputStream
+{
+
+ private $buffer;
+ private $buffer_size;
+ private $current;
+
+ const MAX_VARINT32_BYTES = 5;
+ const MAX_VARINT64_BYTES = 10;
+
+ public function __construct($size)
+ {
+ $this->current = 0;
+ $this->buffer_size = $size;
+ $this->buffer = str_repeat(chr(0), $this->buffer_size);
+ }
+
+ public function getData()
+ {
+ return $this->buffer;
+ }
+
+ public function writeVarint32($value)
+ {
+ $bytes = str_repeat(chr(0), self::MAX_VARINT32_BYTES);
+ $size = self::writeVarintToArray($value, $bytes, true);
+ return $this->writeRaw($bytes, $size);
+ }
+
+ public function writeVarint64($value)
+ {
+ $bytes = str_repeat(chr(0), self::MAX_VARINT64_BYTES);
+ $size = self::writeVarintToArray($value, $bytes);
+ return $this->writeRaw($bytes, $size);
+ }
+
+ public function writeLittleEndian32($value)
+ {
+ $bytes = str_repeat(chr(0), 4);
+ $size = self::writeLittleEndian32ToArray($value, $bytes);
+ return $this->writeRaw($bytes, $size);
+ }
+
+ public function writeLittleEndian64($value)
+ {
+ $bytes = str_repeat(chr(0), 8);
+ $size = self::writeLittleEndian64ToArray($value, $bytes);
+ return $this->writeRaw($bytes, $size);
+ }
+
+ public function writeTag($tag)
+ {
+ return $this->writeVarint32($tag);
+ }
+
+ public function writeRaw($data, $size)
+ {
+ if ($this->buffer_size < $size) {
+ var_dump($this->buffer_size);
+ var_dump($size);
+ trigger_error("Output stream doesn't have enough buffer.");
+ return false;
+ }
+
+ for ($i = 0; $i < $size; $i++) {
+ $this->buffer[$this->current] = $data[$i];
+ $this->current++;
+ $this->buffer_size--;
+ }
+ return true;
+ }
+
+ private static function writeVarintToArray($value, &$buffer, $trim = false)
+ {
+ $current = 0;
+ if ($trim) {
+ $value &= 0xFFFFFFFF;
+ }
+ while ($value >= 0x80 || $value < 0) {
+ $buffer[$current] = chr($value | 0x80);
+ $value = ($value >> 7) & ~(0x7F << ((PHP_INT_SIZE << 3) - 7));
+ $current++;
+ }
+ $buffer[$current] = chr($value);
+ return $current + 1;
+ }
+
+ private static function writeLittleEndian32ToArray($value, &$buffer)
+ {
+ $buffer[0] = chr($value & 0x000000FF);
+ $buffer[1] = chr(($value >> 8) & 0x000000FF);
+ $buffer[2] = chr(($value >> 16) & 0x000000FF);
+ $buffer[3] = chr(($value >> 24) & 0x000000FF);
+ return 4;
+ }
+
+ private static function writeLittleEndian64ToArray($value, &$buffer)
+ {
+ $buffer[0] = chr($value & 0x000000FF);
+ $buffer[1] = chr(($value >> 8) & 0x000000FF);
+ $buffer[2] = chr(($value >> 16) & 0x000000FF);
+ $buffer[3] = chr(($value >> 24) & 0x000000FF);
+ $buffer[4] = chr(($value >> 32) & 0x000000FF);
+ $buffer[5] = chr(($value >> 40) & 0x000000FF);
+ $buffer[6] = chr(($value >> 48) & 0x000000FF);
+ $buffer[7] = chr(($value >> 56) & 0x000000FF);
+ return 8;
+ }
+}
diff --git a/php/src/Google/Protobuf/Internal/RepeatedField.php b/php/src/Google/Protobuf/Internal/RepeatedField.php
new file mode 100644
index 00000000..0dc5d9d2
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/RepeatedField.php
@@ -0,0 +1,303 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/**
+ * RepeatedField and RepeatedFieldIter are used by generated protocol message
+ * classes to manipulate repeated fields.
+ */
+
+namespace Google\Protobuf\Internal;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * RepeatedFieldIter is used to iterate RepeatedField. It is also need for the
+ * foreach syntax.
+ */
+class RepeatedFieldIter implements \Iterator
+{
+
+ /**
+ * @ignore
+ */
+ private $position;
+ /**
+ * @ignore
+ */
+ private $container;
+
+ /**
+ * Create iterator instance for RepeatedField.
+ *
+ * @param RepeatedField The RepeatedField instance for which this iterator
+ * is created.
+ * @ignore
+ */
+ public function __construct($container)
+ {
+ $this->position = 0;
+ $this->container = $container;
+ }
+
+ /**
+ * Reset the status of the iterator
+ *
+ * @return void
+ */
+ public function rewind()
+ {
+ $this->position = 0;
+ }
+
+ /**
+ * Return the element at the current position.
+ *
+ * @return object The element at the current position.
+ */
+ public function current()
+ {
+ return $this->container[$this->position];
+ }
+
+ /**
+ * Return the current position.
+ *
+ * @return integer The current position.
+ */
+ public function key()
+ {
+ return $this->position;
+ }
+
+ /**
+ * Move to the next position.
+ *
+ * @return void
+ */
+ public function next()
+ {
+ ++$this->position;
+ }
+
+ /**
+ * Check whether there are more elements to iterate.
+ *
+ * @return bool True if there are more elements to iterate.
+ */
+ public function valid()
+ {
+ return isset($this->container[$this->position]);
+ }
+}
+
+/**
+ * RepeatedField is used by generated protocol message classes to manipulate
+ * repeated fields. It can be used like native PHP array.
+ */
+class RepeatedField implements \ArrayAccess, \IteratorAggregate, \Countable
+{
+
+ /**
+ * @ignore
+ */
+ private $container;
+ /**
+ * @ignore
+ */
+ private $type;
+ /**
+ * @ignore
+ */
+ private $klass;
+
+ /**
+ * Constructs an instance of RepeatedField.
+ *
+ * @param long $type Type of the stored element.
+ * @param string $klass Message/Enum class name (message/enum fields only).
+ * @ignore
+ */
+ public function __construct($type, $klass = null)
+ {
+ $this->container = [];
+ $this->type = $type;
+ $this->klass = $klass;
+ }
+
+ /**
+ * @ignore
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * @ignore
+ */
+ public function getClass()
+ {
+ return $this->klass;
+ }
+
+ /**
+ * Return the element at the given index.
+ *
+ * This will also be called for: $ele = $arr[0]
+ *
+ * @param long $offset The index of the element to be fetched.
+ * @return object The stored element at given index.
+ * @throws ErrorException Invalid type for index.
+ * @throws ErrorException Non-existing index.
+ */
+ public function offsetGet($offset)
+ {
+ return $this->container[$offset];
+ }
+
+ /**
+ * Assign the element at the given index.
+ *
+ * This will also be called for: $arr []= $ele and $arr[0] = ele
+ *
+ * @param long $offset The index of the element to be assigned.
+ * @param object $value The element to be assigned.
+ * @return void
+ * @throws ErrorException Invalid type for index.
+ * @throws ErrorException Non-existing index.
+ * @throws ErrorException Incorrect type of the element.
+ */
+ public function offsetSet($offset, $value)
+ {
+ switch ($this->type) {
+ case GPBType::INT32:
+ GPBUtil::checkInt32($value);
+ break;
+ case GPBType::UINT32:
+ GPBUtil::checkUint32($value);
+ break;
+ case GPBType::INT64:
+ GPBUtil::checkInt64($value);
+ break;
+ case GPBType::UINT64:
+ GPBUtil::checkUint64($value);
+ break;
+ case GPBType::FLOAT:
+ GPBUtil::checkFloat($value);
+ break;
+ case GPBType::DOUBLE:
+ GPBUtil::checkDouble($value);
+ break;
+ case GPBType::BOOL:
+ GPBUtil::checkBool($value);
+ break;
+ case GPBType::STRING:
+ GPBUtil::checkString($value, true);
+ break;
+ case GPBType::MESSAGE:
+ GPBUtil::checkMessage($value, $this->klass);
+ break;
+ default:
+ break;
+ }
+ if (is_null($offset)) {
+ $this->container[] = $value;
+ } else {
+ $count = count($this->container);
+ if (!is_numeric($offset) || $offset < 0 || $offset >= $count) {
+ trigger_error(
+ "Cannot modify element at the given index",
+ E_USER_ERROR);
+ return;
+ }
+ $this->container[$offset] = $value;
+ }
+ }
+
+ /**
+ * Remove the element at the given index.
+ *
+ * This will also be called for: unset($arr)
+ *
+ * @param long $offset The index of the element to be removed.
+ * @return void
+ * @throws ErrorException Invalid type for index.
+ * @throws ErrorException The element to be removed is not at the end of the
+ * RepeatedField.
+ */
+ public function offsetUnset($offset)
+ {
+ $count = count($this->container);
+ if (!is_numeric($offset) || $count === 0 || $offset !== $count - 1) {
+ trigger_error(
+ "Cannot remove element at the given index",
+ E_USER_ERROR);
+ return;
+ }
+ array_pop($this->container);
+ }
+
+ /**
+ * Check the existence of the element at the given index.
+ *
+ * This will also be called for: isset($arr)
+ *
+ * @param long $offset The index of the element to be removed.
+ * @return bool True if the element at the given offset exists.
+ * @throws ErrorException Invalid type for index.
+ */
+ public function offsetExists($offset)
+ {
+ return isset($this->container[$offset]);
+ }
+
+ /**
+ * @ignore
+ */
+ public function getIterator()
+ {
+ return new RepeatedFieldIter($this->container);
+ }
+
+ /**
+ * Return the number of stored elements.
+ *
+ * This will also be called for: count($arr)
+ *
+ * @return integer The number of stored elements.
+ */
+ public function count()
+ {
+ return count($this->container);
+ }
+}
diff --git a/php/src/Google/Protobuf/Internal/Type.php b/php/src/Google/Protobuf/Internal/Type.php
new file mode 100644
index 00000000..088f0e0c
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/Type.php
@@ -0,0 +1,175 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+class GPBInteger
+{
+ public $high = 0;
+ public $low = 0;
+
+ public function __construct($value = 0)
+ {
+ $this->low = $value & 0xFFFFFFFF;
+ if (PHP_INT_SIZE === 8) {
+ $this->high = ($value >> 32) & 0xFFFFFFFF;
+ }
+ }
+
+ // Return 0 for unsigned integers and 1 for signed integers.
+ protected function sign()
+ {
+ trigger_error("Not implemented", E_ERROR);
+ }
+
+ public function leftShift($count)
+ {
+ if ($count > 63) {
+ $this->low = 0;
+ $this->high = 0;
+ return;
+ }
+ if ($count > 32) {
+ $this->high = $this->low;
+ $this->low = 0;
+ $count -= 32;
+ }
+ $mask = (1 << $count) - 1;
+ $this->high = (($this->high << $count) & 0xFFFFFFFF) |
+ (($this->low >> (32 - $count)) & $mask);
+ $this->low = ($this->low << $count) & 0xFFFFFFFF;
+
+ $this->high &= 0xFFFFFFFF;
+ $this->low &= 0xFFFFFFFF;
+ return $this;
+ }
+
+ public function rightShift($count)
+ {
+ $sign = (($this->high & 0x80000000) >> 31) & $this->sign();
+ if ($count > 63) {
+ $this->low = -$sign;
+ $this->high = -$sign;
+ return;
+ }
+ if ($count > 32) {
+ $this->low = $this->high;
+ $this->high = -$sign;
+ $count -= 32;
+ }
+ $this->low = (($this->low >> $count) & 0xFFFFFFFF) |
+ (($this->high << (32 - $count)) & 0xFFFFFFFF);
+ $this->high = (($this->high >> $count) | (-$sign << $count));
+
+ $this->high &= 0xFFFFFFFF;
+ $this->low &= 0xFFFFFFFF;
+
+ return $this;
+ }
+
+ public function bitOr($var)
+ {
+ $this->high |= $var->high;
+ $this->low |= $var->low;
+ return $this;
+ }
+
+ public function bitXor($var)
+ {
+ $this->high ^= $var->high;
+ $this->low ^= $var->low;
+ return $this;
+ }
+
+ public function bitAnd($var)
+ {
+ $this->high &= $var->high;
+ $this->low &= $var->low;
+ return $this;
+ }
+
+ // Even: all zero; Odd: all one.
+ public function oddMask()
+ {
+ $low = (-($this->low & 1)) & 0xFFFFFFFF;
+ $high = $low;
+ return UInt64::newValue($high, $low);
+ }
+
+ public function toInteger()
+ {
+ if (PHP_INT_SIZE === 8) {
+ return ($this->high << 32) | $this->low;
+ } else {
+ return $this->low;
+ }
+ }
+
+ public function copy()
+ {
+ return static::newValue($this->high, $this->low);
+ }
+}
+
+class Uint64 extends GPBInteger
+{
+
+ public static function newValue($high, $low)
+ {
+ $uint64 = new Uint64(0);
+ $uint64->high = $high;
+ $uint64->low = $low;
+ return $uint64;
+ }
+
+ protected function sign()
+ {
+ return 0;
+ }
+}
+
+class Int64 extends GPBInteger
+{
+
+ public static function newValue($high, $low)
+ {
+ $int64 = new Int64(0);
+ $int64->high = $high;
+ $int64->low = $low;
+ return $int64;
+ }
+
+ protected function sign()
+ {
+ return 1;
+ }
+}
diff --git a/php/src/Google/Protobuf/descriptor.php b/php/src/Google/Protobuf/descriptor.php
new file mode 100644
index 00000000..afe08227
--- /dev/null
+++ b/php/src/Google/Protobuf/descriptor.php
@@ -0,0 +1,541 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\MessageOptions;
+
+class FileDescriptor
+{
+
+ private $package;
+ private $message_type = [];
+ private $enum_type = [];
+
+ public function setPackage($package)
+ {
+ $this->package = $package;
+ }
+
+ public function getPackage()
+ {
+ return $this->package;
+ }
+
+ public function getMessageType()
+ {
+ return $this->message_type;
+ }
+
+ public function addMessageType($desc)
+ {
+ $this->message_type[] = $desc;
+ }
+
+ public function getEnumType()
+ {
+ return $this->enum_type;
+ }
+
+ public function addEnumType($desc)
+ {
+ $this->enum_type[]= $desc;
+ }
+
+ public static function buildFromProto($proto)
+ {
+ $file = new FileDescriptor();
+ $file->setPackage($proto->getPackage());
+ foreach ($proto->getMessageType() as $message_proto) {
+ $file->addMessageType(Descriptor::buildFromProto(
+ $message_proto, $file->getPackage(), ""));
+ }
+ foreach ($proto->getEnumType() as $enum_proto) {
+ $file->getEnumType()[] =
+ $file->addEnumType(
+ EnumDescriptor::buildFromProto(
+ $enum_proto,
+ $file->getPackage(),
+ ""));
+ }
+ return $file;
+ }
+}
+
+class Descriptor
+{
+
+ private $full_name;
+ private $field = [];
+ private $nested_type = [];
+ private $enum_type = [];
+ private $klass;
+ private $options;
+ private $oneof_decl = [];
+
+ public function addOneofDecl($oneof)
+ {
+ $this->oneof_decl[] = $oneof;
+ }
+
+ public function getOneofDecl()
+ {
+ return $this->oneof_decl;
+ }
+
+ public function setFullName($full_name)
+ {
+ $this->full_name = $full_name;
+ }
+
+ public function getFullName()
+ {
+ return $this->full_name;
+ }
+
+ public function addField($field)
+ {
+ $this->field[$field->getNumber()] = $field;
+ }
+
+ public function getField()
+ {
+ return $this->field;
+ }
+
+ public function addNestedType($desc)
+ {
+ $this->nested_type[] = $desc;
+ }
+
+ public function getNestedType()
+ {
+ return $this->nested_type;
+ }
+
+ public function addEnumType($desc)
+ {
+ $this->enum_type[] = $desc;
+ }
+
+ public function getEnumType()
+ {
+ return $this->enum_type;
+ }
+
+ public function getFieldByNumber($number)
+ {
+ return $this->field[$number];
+ }
+
+ public function setClass($klass)
+ {
+ $this->klass = $klass;
+ }
+
+ public function getClass()
+ {
+ return $this->klass;
+ }
+
+ public function setOptions($options)
+ {
+ $this->options = $options;
+ }
+
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ public static function buildFromProto($proto, $package, $containing)
+ {
+ $desc = new Descriptor();
+
+ $message_name_without_package = "";
+ $classname = "";
+ $fullname = "";
+ getFullClassName(
+ $proto,
+ $containing,
+ $package,
+ $message_name_without_package,
+ $classname,
+ $fullname);
+ $desc->setFullName($fullname);
+ $desc->setClass($classname);
+ $desc->setOptions($proto->getOptions());
+
+ foreach ($proto->getField() as $field_proto) {
+ $desc->addField(FieldDescriptor::buildFromProto($field_proto));
+ }
+
+ // Handle nested types.
+ foreach ($proto->getNestedType() as $nested_proto) {
+ $desc->addNestedType(Descriptor::buildFromProto(
+ $nested_proto, $package, $message_name_without_package));
+ }
+
+ // Handle oneof fields.
+ foreach ($proto->getOneofDecl() as $oneof_proto) {
+ $desc->addOneofDecl(
+ OneofDescriptor::buildFromProto($oneof_proto, $desc));
+ }
+
+ return $desc;
+ }
+}
+function getFullClassName(
+ $proto,
+ $containing,
+ $package,
+ &$message_name_without_package,
+ &$classname,
+ &$fullname)
+{
+ // Full name needs to start with '.'.
+ $message_name_without_package = $proto->getName();
+ if ($containing !== "") {
+ $message_name_without_package =
+ $containing . "." . $message_name_without_package;
+ }
+ if ($package === "") {
+ $fullname = "." . $message_name_without_package;
+ } else {
+ $fullname = "." . $package . "." . $message_name_without_package;
+ }
+
+ // Nested message class names are seperated by '_', and package names are
+ // seperated by '\'.
+ $class_name_without_package =
+ implode('_', array_map('ucwords',
+ explode('.', $message_name_without_package)));
+ $classname =
+ implode('\\', array_map('ucwords', explode('.', $package))).
+ "\\".$class_name_without_package;
+}
+
+class OneofDescriptor
+{
+
+ private $name;
+ private $fields;
+
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function addField(&$field)
+ {
+ $this->fields[] = $field;
+ }
+
+ public function getFields()
+ {
+ return $this->fields;
+ }
+
+ public static function buildFromProto($oneof_proto)
+ {
+ $oneof = new OneofDescriptor();
+ $oneof->setName($oneof_proto->getName());
+ return $oneof;
+ }
+}
+
+
+class EnumDescriptor
+{
+
+ private $klass;
+ private $full_name;
+ private $value;
+
+ public function setFullName($full_name)
+ {
+ $this->full_name = $full_name;
+ }
+
+ public function getFullName()
+ {
+ return $this->full_name;
+ }
+
+ public function addValue($number, $value)
+ {
+ $this->value[$number] = $value;
+ }
+
+ public function setClass($klass)
+ {
+ $this->klass = $klass;
+ }
+
+ public function getClass()
+ {
+ return $this->klass;
+ }
+
+ public static function buildFromProto($proto, $package, $containing)
+ {
+ $desc = new EnumDescriptor();
+
+ $enum_name_without_package = "";
+ $classname = "";
+ $fullname = "";
+ getFullClassName(
+ $proto,
+ $containing,
+ $package,
+ $enum_name_without_package,
+ $classname,
+ $fullname);
+ $desc->setFullName($fullname);
+ $desc->setClass($classname);
+
+ return $desc;
+ }
+}
+
+class EnumValueDescriptor
+{
+}
+
+class FieldDescriptor
+{
+
+ private $name;
+ private $setter;
+ private $getter;
+ private $number;
+ private $label;
+ private $type;
+ private $message_type;
+ private $enum_type;
+ private $packed;
+ private $is_map;
+ private $oneof_index = -1;
+
+ public function setOneofIndex($index)
+ {
+ $this->oneof_index = $index;
+ }
+
+ public function getOneofIndex()
+ {
+ return $this->oneof_index;
+ }
+
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function setSetter($setter)
+ {
+ $this->setter = $setter;
+ }
+
+ public function getSetter()
+ {
+ return $this->setter;
+ }
+
+ public function setGetter($getter)
+ {
+ $this->getter = $getter;
+ }
+
+ public function getGetter()
+ {
+ return $this->getter;
+ }
+
+ public function setNumber($number)
+ {
+ $this->number = $number;
+ }
+
+ public function getNumber()
+ {
+ return $this->number;
+ }
+
+ public function setLabel($label)
+ {
+ $this->label = $label;
+ }
+
+ public function getLabel()
+ {
+ return $this->label;
+ }
+
+ public function isRepeated()
+ {
+ return $this->label === GPBLabel::REPEATED;
+ }
+
+ public function setType($type)
+ {
+ $this->type = $type;
+ }
+
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ public function setMessageType($message_type)
+ {
+ $this->message_type = $message_type;
+ }
+
+ public function getMessageType()
+ {
+ return $this->message_type;
+ }
+
+ public function setEnumType($enum_type)
+ {
+ $this->enum_type = $enum_type;
+ }
+
+ public function getEnumType()
+ {
+ return $this->enum_type;
+ }
+
+ public function setPacked($packed)
+ {
+ $this->packed = $packed;
+ }
+
+ public function getPacked()
+ {
+ return $this->packed;
+ }
+
+ public function isPackable()
+ {
+ return $this->isRepeated() && self::isTypePackable($this->type);
+ }
+
+ public function isMap()
+ {
+ return $this->getType() == GPBType::MESSAGE &&
+ !is_null($this->getMessageType()->getOptions()) &&
+ $this->getMessageType()->getOptions()->getMapEntry();
+ }
+
+ private static function isTypePackable($field_type)
+ {
+ return ($field_type !== GPBType::STRING &&
+ $field_type !== GPBType::GROUP &&
+ $field_type !== GPBType::MESSAGE &&
+ $field_type !== GPBType::BYTES);
+ }
+
+ public static function getFieldDescriptor(
+ $name,
+ $label,
+ $type,
+ $number,
+ $oneof_index,
+ $packed,
+ $type_name = null)
+ {
+ $field = new FieldDescriptor();
+ $field->setName($name);
+ $camel_name = implode('', array_map('ucwords', explode('_', $name)));
+ $field->setGetter('get' . $camel_name);
+ $field->setSetter('set' . $camel_name);
+ $field->setType($type);
+ $field->setNumber($number);
+ $field->setLabel($label);
+ $field->setPacked($packed);
+ $field->setOneofIndex($oneof_index);
+
+ // At this time, the message/enum type may have not been added to pool.
+ // So we use the type name as place holder and will replace it with the
+ // actual descriptor in cross building.
+ switch ($type) {
+ case GPBType::MESSAGE:
+ $field->setMessageType($type_name);
+ break;
+ case GPBType::ENUM:
+ $field->setEnumType($type_name);
+ break;
+ default:
+ break;
+ }
+
+ return $field;
+ }
+
+ public static function buildFromProto($proto)
+ {
+ $type_name = null;
+ switch ($proto->getType()) {
+ case GPBType::MESSAGE:
+ case GPBType::GROUP:
+ case GPBType::ENUM:
+ $type_name = $proto->getTypeName();
+ break;
+ default:
+ break;
+ }
+
+ $oneof_index = $proto->hasOneofIndex() ? $proto->getOneofIndex() : -1;
+ $packed = false;
+ $options = $proto->getOptions();
+ if ($options !== null) {
+ $packed = $options->getPacked();
+ }
+
+ return FieldDescriptor::getFieldDescriptor(
+ $proto->getName(), $proto->getLabel(), $proto->getType(),
+ $proto->getNumber(), $oneof_index, $packed, $type_name);
+ }
+}
diff --git a/php/src/Google/Protobuf/descriptor_internal.pb.php b/php/src/Google/Protobuf/descriptor_internal.pb.php
new file mode 100644
index 00000000..161a9f52
--- /dev/null
+++ b/php/src/Google/Protobuf/descriptor_internal.pb.php
@@ -0,0 +1,2532 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: google/protobuf/descriptor.proto
+
+namespace Google\Protobuf\Internal;
+
+use Google\Protobuf\Internal\DescriptorPool;
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\GPBWire;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\InputStream;
+
+use Google\Protobuf\Internal\GPBUtil;
+
+class FileDescriptorSet extends \Google\Protobuf\Internal\Message
+{
+ private $file;
+ private $has_file = false;
+
+ public function getFile()
+ {
+ return $this->file;
+ }
+
+ public function setFile(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\FileDescriptorProto::class);
+ $this->file = $var;
+ $this->has_file = true;
+ }
+
+ public function hasFile()
+ {
+ return $this->has_file;
+ }
+
+}
+
+class FileDescriptorProto extends \Google\Protobuf\Internal\Message
+{
+ private $name = '';
+ private $has_name = false;
+ private $package = '';
+ private $has_package = false;
+ private $dependency;
+ private $has_dependency = false;
+ private $public_dependency;
+ private $has_public_dependency = false;
+ private $weak_dependency;
+ private $has_weak_dependency = false;
+ private $message_type;
+ private $has_message_type = false;
+ private $enum_type;
+ private $has_enum_type = false;
+ private $service;
+ private $has_service = false;
+ private $extension;
+ private $has_extension = false;
+ private $options = null;
+ private $has_options = false;
+ private $source_code_info = null;
+ private $has_source_code_info = false;
+ private $syntax = '';
+ private $has_syntax = false;
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function setName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->name = $var;
+ $this->has_name = true;
+ }
+
+ public function hasName()
+ {
+ return $this->has_name;
+ }
+
+ public function getPackage()
+ {
+ return $this->package;
+ }
+
+ public function setPackage($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->package = $var;
+ $this->has_package = true;
+ }
+
+ public function hasPackage()
+ {
+ return $this->has_package;
+ }
+
+ public function getDependency()
+ {
+ return $this->dependency;
+ }
+
+ public function setDependency(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::STRING);
+ $this->dependency = $var;
+ $this->has_dependency = true;
+ }
+
+ public function hasDependency()
+ {
+ return $this->has_dependency;
+ }
+
+ public function getPublicDependency()
+ {
+ return $this->public_dependency;
+ }
+
+ public function setPublicDependency(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::INT32);
+ $this->public_dependency = $var;
+ $this->has_public_dependency = true;
+ }
+
+ public function hasPublicDependency()
+ {
+ return $this->has_public_dependency;
+ }
+
+ public function getWeakDependency()
+ {
+ return $this->weak_dependency;
+ }
+
+ public function setWeakDependency(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::INT32);
+ $this->weak_dependency = $var;
+ $this->has_weak_dependency = true;
+ }
+
+ public function hasWeakDependency()
+ {
+ return $this->has_weak_dependency;
+ }
+
+ public function getMessageType()
+ {
+ return $this->message_type;
+ }
+
+ public function setMessageType(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto::class);
+ $this->message_type = $var;
+ $this->has_message_type = true;
+ }
+
+ public function hasMessageType()
+ {
+ return $this->has_message_type;
+ }
+
+ public function getEnumType()
+ {
+ return $this->enum_type;
+ }
+
+ public function setEnumType(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto::class);
+ $this->enum_type = $var;
+ $this->has_enum_type = true;
+ }
+
+ public function hasEnumType()
+ {
+ return $this->has_enum_type;
+ }
+
+ public function getService()
+ {
+ return $this->service;
+ }
+
+ public function setService(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\ServiceDescriptorProto::class);
+ $this->service = $var;
+ $this->has_service = true;
+ }
+
+ public function hasService()
+ {
+ return $this->has_service;
+ }
+
+ public function getExtension()
+ {
+ return $this->extension;
+ }
+
+ public function setExtension(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class);
+ $this->extension = $var;
+ $this->has_extension = true;
+ }
+
+ public function hasExtension()
+ {
+ return $this->has_extension;
+ }
+
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ public function setOptions(&$var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FileOptions::class);
+ $this->options = $var;
+ $this->has_options = true;
+ }
+
+ public function hasOptions()
+ {
+ return $this->has_options;
+ }
+
+ public function getSourceCodeInfo()
+ {
+ return $this->source_code_info;
+ }
+
+ public function setSourceCodeInfo(&$var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Internal\SourceCodeInfo::class);
+ $this->source_code_info = $var;
+ $this->has_source_code_info = true;
+ }
+
+ public function hasSourceCodeInfo()
+ {
+ return $this->has_source_code_info;
+ }
+
+ public function getSyntax()
+ {
+ return $this->syntax;
+ }
+
+ public function setSyntax($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->syntax = $var;
+ $this->has_syntax = true;
+ }
+
+ public function hasSyntax()
+ {
+ return $this->has_syntax;
+ }
+
+}
+
+class DescriptorProto extends \Google\Protobuf\Internal\Message
+{
+ private $name = '';
+ private $has_name = false;
+ private $field;
+ private $has_field = false;
+ private $extension;
+ private $has_extension = false;
+ private $nested_type;
+ private $has_nested_type = false;
+ private $enum_type;
+ private $has_enum_type = false;
+ private $extension_range;
+ private $has_extension_range = false;
+ private $oneof_decl;
+ private $has_oneof_decl = false;
+ private $options = null;
+ private $has_options = false;
+ private $reserved_range;
+ private $has_reserved_range = false;
+ private $reserved_name;
+ private $has_reserved_name = false;
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function setName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->name = $var;
+ $this->has_name = true;
+ }
+
+ public function hasName()
+ {
+ return $this->has_name;
+ }
+
+ public function getField()
+ {
+ return $this->field;
+ }
+
+ public function setField(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class);
+ $this->field = $var;
+ $this->has_field = true;
+ }
+
+ public function hasField()
+ {
+ return $this->has_field;
+ }
+
+ public function getExtension()
+ {
+ return $this->extension;
+ }
+
+ public function setExtension(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class);
+ $this->extension = $var;
+ $this->has_extension = true;
+ }
+
+ public function hasExtension()
+ {
+ return $this->has_extension;
+ }
+
+ public function getNestedType()
+ {
+ return $this->nested_type;
+ }
+
+ public function setNestedType(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto::class);
+ $this->nested_type = $var;
+ $this->has_nested_type = true;
+ }
+
+ public function hasNestedType()
+ {
+ return $this->has_nested_type;
+ }
+
+ public function getEnumType()
+ {
+ return $this->enum_type;
+ }
+
+ public function setEnumType(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto::class);
+ $this->enum_type = $var;
+ $this->has_enum_type = true;
+ }
+
+ public function hasEnumType()
+ {
+ return $this->has_enum_type;
+ }
+
+ public function getExtensionRange()
+ {
+ return $this->extension_range;
+ }
+
+ public function setExtensionRange(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto_ExtensionRange::class);
+ $this->extension_range = $var;
+ $this->has_extension_range = true;
+ }
+
+ public function hasExtensionRange()
+ {
+ return $this->has_extension_range;
+ }
+
+ public function getOneofDecl()
+ {
+ return $this->oneof_decl;
+ }
+
+ public function setOneofDecl(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\OneofDescriptorProto::class);
+ $this->oneof_decl = $var;
+ $this->has_oneof_decl = true;
+ }
+
+ public function hasOneofDecl()
+ {
+ return $this->has_oneof_decl;
+ }
+
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ public function setOptions(&$var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Internal\MessageOptions::class);
+ $this->options = $var;
+ $this->has_options = true;
+ }
+
+ public function hasOptions()
+ {
+ return $this->has_options;
+ }
+
+ public function getReservedRange()
+ {
+ return $this->reserved_range;
+ }
+
+ public function setReservedRange(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto_ReservedRange::class);
+ $this->reserved_range = $var;
+ $this->has_reserved_range = true;
+ }
+
+ public function hasReservedRange()
+ {
+ return $this->has_reserved_range;
+ }
+
+ public function getReservedName()
+ {
+ return $this->reserved_name;
+ }
+
+ public function setReservedName(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::STRING);
+ $this->reserved_name = $var;
+ $this->has_reserved_name = true;
+ }
+
+ public function hasReservedName()
+ {
+ return $this->has_reserved_name;
+ }
+
+}
+
+class DescriptorProto_ExtensionRange extends \Google\Protobuf\Internal\Message
+{
+ private $start = 0;
+ private $has_start = false;
+ private $end = 0;
+ private $has_end = false;
+
+ public function getStart()
+ {
+ return $this->start;
+ }
+
+ public function setStart($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->start = $var;
+ $this->has_start = true;
+ }
+
+ public function hasStart()
+ {
+ return $this->has_start;
+ }
+
+ public function getEnd()
+ {
+ return $this->end;
+ }
+
+ public function setEnd($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->end = $var;
+ $this->has_end = true;
+ }
+
+ public function hasEnd()
+ {
+ return $this->has_end;
+ }
+
+}
+
+class DescriptorProto_ReservedRange extends \Google\Protobuf\Internal\Message
+{
+ private $start = 0;
+ private $has_start = false;
+ private $end = 0;
+ private $has_end = false;
+
+ public function getStart()
+ {
+ return $this->start;
+ }
+
+ public function setStart($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->start = $var;
+ $this->has_start = true;
+ }
+
+ public function hasStart()
+ {
+ return $this->has_start;
+ }
+
+ public function getEnd()
+ {
+ return $this->end;
+ }
+
+ public function setEnd($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->end = $var;
+ $this->has_end = true;
+ }
+
+ public function hasEnd()
+ {
+ return $this->has_end;
+ }
+
+}
+
+class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
+{
+ private $name = '';
+ private $has_name = false;
+ private $number = 0;
+ private $has_number = false;
+ private $label = 0;
+ private $has_label = false;
+ private $type = 0;
+ private $has_type = false;
+ private $type_name = '';
+ private $has_type_name = false;
+ private $extendee = '';
+ private $has_extendee = false;
+ private $default_value = '';
+ private $has_default_value = false;
+ private $oneof_index = 0;
+ private $has_oneof_index = false;
+ private $json_name = '';
+ private $has_json_name = false;
+ private $options = null;
+ private $has_options = false;
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function setName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->name = $var;
+ $this->has_name = true;
+ }
+
+ public function hasName()
+ {
+ return $this->has_name;
+ }
+
+ public function getNumber()
+ {
+ return $this->number;
+ }
+
+ public function setNumber($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->number = $var;
+ $this->has_number = true;
+ }
+
+ public function hasNumber()
+ {
+ return $this->has_number;
+ }
+
+ public function getLabel()
+ {
+ return $this->label;
+ }
+
+ public function setLabel($var)
+ {
+ GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto_Label::class);
+ $this->label = $var;
+ $this->has_label = true;
+ }
+
+ public function hasLabel()
+ {
+ return $this->has_label;
+ }
+
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ public function setType($var)
+ {
+ GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto_Type::class);
+ $this->type = $var;
+ $this->has_type = true;
+ }
+
+ public function hasType()
+ {
+ return $this->has_type;
+ }
+
+ public function getTypeName()
+ {
+ return $this->type_name;
+ }
+
+ public function setTypeName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->type_name = $var;
+ $this->has_type_name = true;
+ }
+
+ public function hasTypeName()
+ {
+ return $this->has_type_name;
+ }
+
+ public function getExtendee()
+ {
+ return $this->extendee;
+ }
+
+ public function setExtendee($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->extendee = $var;
+ $this->has_extendee = true;
+ }
+
+ public function hasExtendee()
+ {
+ return $this->has_extendee;
+ }
+
+ public function getDefaultValue()
+ {
+ return $this->default_value;
+ }
+
+ public function setDefaultValue($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->default_value = $var;
+ $this->has_default_value = true;
+ }
+
+ public function hasDefaultValue()
+ {
+ return $this->has_default_value;
+ }
+
+ public function getOneofIndex()
+ {
+ return $this->oneof_index;
+ }
+
+ public function setOneofIndex($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->oneof_index = $var;
+ $this->has_oneof_index = true;
+ }
+
+ public function hasOneofIndex()
+ {
+ return $this->has_oneof_index;
+ }
+
+ public function getJsonName()
+ {
+ return $this->json_name;
+ }
+
+ public function setJsonName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->json_name = $var;
+ $this->has_json_name = true;
+ }
+
+ public function hasJsonName()
+ {
+ return $this->has_json_name;
+ }
+
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ public function setOptions(&$var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FieldOptions::class);
+ $this->options = $var;
+ $this->has_options = true;
+ }
+
+ public function hasOptions()
+ {
+ return $this->has_options;
+ }
+
+}
+
+class FieldDescriptorProto_Type
+{
+ const TYPE_DOUBLE = 1;
+ const TYPE_FLOAT = 2;
+ const TYPE_INT64 = 3;
+ const TYPE_UINT64 = 4;
+ const TYPE_INT32 = 5;
+ const TYPE_FIXED64 = 6;
+ const TYPE_FIXED32 = 7;
+ const TYPE_BOOL = 8;
+ const TYPE_STRING = 9;
+ const TYPE_GROUP = 10;
+ const TYPE_MESSAGE = 11;
+ const TYPE_BYTES = 12;
+ const TYPE_UINT32 = 13;
+ const TYPE_ENUM = 14;
+ const TYPE_SFIXED32 = 15;
+ const TYPE_SFIXED64 = 16;
+ const TYPE_SINT32 = 17;
+ const TYPE_SINT64 = 18;
+}
+
+class FieldDescriptorProto_Label
+{
+ const LABEL_OPTIONAL = 1;
+ const LABEL_REQUIRED = 2;
+ const LABEL_REPEATED = 3;
+}
+
+class OneofDescriptorProto extends \Google\Protobuf\Internal\Message
+{
+ private $name = '';
+ private $has_name = false;
+ private $options = null;
+ private $has_options = false;
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function setName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->name = $var;
+ $this->has_name = true;
+ }
+
+ public function hasName()
+ {
+ return $this->has_name;
+ }
+
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ public function setOptions(&$var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Internal\OneofOptions::class);
+ $this->options = $var;
+ $this->has_options = true;
+ }
+
+ public function hasOptions()
+ {
+ return $this->has_options;
+ }
+
+}
+
+class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
+{
+ private $name = '';
+ private $has_name = false;
+ private $value;
+ private $has_value = false;
+ private $options = null;
+ private $has_options = false;
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function setName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->name = $var;
+ $this->has_name = true;
+ }
+
+ public function hasName()
+ {
+ return $this->has_name;
+ }
+
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ public function setValue(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\EnumValueDescriptorProto::class);
+ $this->value = $var;
+ $this->has_value = true;
+ }
+
+ public function hasValue()
+ {
+ return $this->has_value;
+ }
+
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ public function setOptions(&$var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Internal\EnumOptions::class);
+ $this->options = $var;
+ $this->has_options = true;
+ }
+
+ public function hasOptions()
+ {
+ return $this->has_options;
+ }
+
+}
+
+class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message
+{
+ private $name = '';
+ private $has_name = false;
+ private $number = 0;
+ private $has_number = false;
+ private $options = null;
+ private $has_options = false;
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function setName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->name = $var;
+ $this->has_name = true;
+ }
+
+ public function hasName()
+ {
+ return $this->has_name;
+ }
+
+ public function getNumber()
+ {
+ return $this->number;
+ }
+
+ public function setNumber($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->number = $var;
+ $this->has_number = true;
+ }
+
+ public function hasNumber()
+ {
+ return $this->has_number;
+ }
+
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ public function setOptions(&$var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Internal\EnumValueOptions::class);
+ $this->options = $var;
+ $this->has_options = true;
+ }
+
+ public function hasOptions()
+ {
+ return $this->has_options;
+ }
+
+}
+
+class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message
+{
+ private $name = '';
+ private $has_name = false;
+ private $method;
+ private $has_method = false;
+ private $options = null;
+ private $has_options = false;
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function setName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->name = $var;
+ $this->has_name = true;
+ }
+
+ public function hasName()
+ {
+ return $this->has_name;
+ }
+
+ public function getMethod()
+ {
+ return $this->method;
+ }
+
+ public function setMethod(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\MethodDescriptorProto::class);
+ $this->method = $var;
+ $this->has_method = true;
+ }
+
+ public function hasMethod()
+ {
+ return $this->has_method;
+ }
+
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ public function setOptions(&$var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Internal\ServiceOptions::class);
+ $this->options = $var;
+ $this->has_options = true;
+ }
+
+ public function hasOptions()
+ {
+ return $this->has_options;
+ }
+
+}
+
+class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
+{
+ private $name = '';
+ private $has_name = false;
+ private $input_type = '';
+ private $has_input_type = false;
+ private $output_type = '';
+ private $has_output_type = false;
+ private $options = null;
+ private $has_options = false;
+ private $client_streaming = false;
+ private $has_client_streaming = false;
+ private $server_streaming = false;
+ private $has_server_streaming = false;
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function setName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->name = $var;
+ $this->has_name = true;
+ }
+
+ public function hasName()
+ {
+ return $this->has_name;
+ }
+
+ public function getInputType()
+ {
+ return $this->input_type;
+ }
+
+ public function setInputType($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->input_type = $var;
+ $this->has_input_type = true;
+ }
+
+ public function hasInputType()
+ {
+ return $this->has_input_type;
+ }
+
+ public function getOutputType()
+ {
+ return $this->output_type;
+ }
+
+ public function setOutputType($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->output_type = $var;
+ $this->has_output_type = true;
+ }
+
+ public function hasOutputType()
+ {
+ return $this->has_output_type;
+ }
+
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ public function setOptions(&$var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Internal\MethodOptions::class);
+ $this->options = $var;
+ $this->has_options = true;
+ }
+
+ public function hasOptions()
+ {
+ return $this->has_options;
+ }
+
+ public function getClientStreaming()
+ {
+ return $this->client_streaming;
+ }
+
+ public function setClientStreaming($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->client_streaming = $var;
+ $this->has_client_streaming = true;
+ }
+
+ public function hasClientStreaming()
+ {
+ return $this->has_client_streaming;
+ }
+
+ public function getServerStreaming()
+ {
+ return $this->server_streaming;
+ }
+
+ public function setServerStreaming($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->server_streaming = $var;
+ $this->has_server_streaming = true;
+ }
+
+ public function hasServerStreaming()
+ {
+ return $this->has_server_streaming;
+ }
+
+}
+
+class FileOptions extends \Google\Protobuf\Internal\Message
+{
+ private $java_package = '';
+ private $has_java_package = false;
+ private $java_outer_classname = '';
+ private $has_java_outer_classname = false;
+ private $java_multiple_files = false;
+ private $has_java_multiple_files = false;
+ private $java_generate_equals_and_hash = false;
+ private $has_java_generate_equals_and_hash = false;
+ private $java_string_check_utf8 = false;
+ private $has_java_string_check_utf8 = false;
+ private $optimize_for = 0;
+ private $has_optimize_for = false;
+ private $go_package = '';
+ private $has_go_package = false;
+ private $cc_generic_services = false;
+ private $has_cc_generic_services = false;
+ private $java_generic_services = false;
+ private $has_java_generic_services = false;
+ private $py_generic_services = false;
+ private $has_py_generic_services = false;
+ private $deprecated = false;
+ private $has_deprecated = false;
+ private $cc_enable_arenas = false;
+ private $has_cc_enable_arenas = false;
+ private $objc_class_prefix = '';
+ private $has_objc_class_prefix = false;
+ private $csharp_namespace = '';
+ private $has_csharp_namespace = false;
+ private $uninterpreted_option;
+ private $has_uninterpreted_option = false;
+
+ public function getJavaPackage()
+ {
+ return $this->java_package;
+ }
+
+ public function setJavaPackage($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->java_package = $var;
+ $this->has_java_package = true;
+ }
+
+ public function hasJavaPackage()
+ {
+ return $this->has_java_package;
+ }
+
+ public function getJavaOuterClassname()
+ {
+ return $this->java_outer_classname;
+ }
+
+ public function setJavaOuterClassname($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->java_outer_classname = $var;
+ $this->has_java_outer_classname = true;
+ }
+
+ public function hasJavaOuterClassname()
+ {
+ return $this->has_java_outer_classname;
+ }
+
+ public function getJavaMultipleFiles()
+ {
+ return $this->java_multiple_files;
+ }
+
+ public function setJavaMultipleFiles($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->java_multiple_files = $var;
+ $this->has_java_multiple_files = true;
+ }
+
+ public function hasJavaMultipleFiles()
+ {
+ return $this->has_java_multiple_files;
+ }
+
+ public function getJavaGenerateEqualsAndHash()
+ {
+ return $this->java_generate_equals_and_hash;
+ }
+
+ public function setJavaGenerateEqualsAndHash($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->java_generate_equals_and_hash = $var;
+ $this->has_java_generate_equals_and_hash = true;
+ }
+
+ public function hasJavaGenerateEqualsAndHash()
+ {
+ return $this->has_java_generate_equals_and_hash;
+ }
+
+ public function getJavaStringCheckUtf8()
+ {
+ return $this->java_string_check_utf8;
+ }
+
+ public function setJavaStringCheckUtf8($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->java_string_check_utf8 = $var;
+ $this->has_java_string_check_utf8 = true;
+ }
+
+ public function hasJavaStringCheckUtf8()
+ {
+ return $this->has_java_string_check_utf8;
+ }
+
+ public function getOptimizeFor()
+ {
+ return $this->optimize_for;
+ }
+
+ public function setOptimizeFor($var)
+ {
+ GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FileOptions_OptimizeMode::class);
+ $this->optimize_for = $var;
+ $this->has_optimize_for = true;
+ }
+
+ public function hasOptimizeFor()
+ {
+ return $this->has_optimize_for;
+ }
+
+ public function getGoPackage()
+ {
+ return $this->go_package;
+ }
+
+ public function setGoPackage($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->go_package = $var;
+ $this->has_go_package = true;
+ }
+
+ public function hasGoPackage()
+ {
+ return $this->has_go_package;
+ }
+
+ public function getCcGenericServices()
+ {
+ return $this->cc_generic_services;
+ }
+
+ public function setCcGenericServices($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->cc_generic_services = $var;
+ $this->has_cc_generic_services = true;
+ }
+
+ public function hasCcGenericServices()
+ {
+ return $this->has_cc_generic_services;
+ }
+
+ public function getJavaGenericServices()
+ {
+ return $this->java_generic_services;
+ }
+
+ public function setJavaGenericServices($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->java_generic_services = $var;
+ $this->has_java_generic_services = true;
+ }
+
+ public function hasJavaGenericServices()
+ {
+ return $this->has_java_generic_services;
+ }
+
+ public function getPyGenericServices()
+ {
+ return $this->py_generic_services;
+ }
+
+ public function setPyGenericServices($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->py_generic_services = $var;
+ $this->has_py_generic_services = true;
+ }
+
+ public function hasPyGenericServices()
+ {
+ return $this->has_py_generic_services;
+ }
+
+ public function getDeprecated()
+ {
+ return $this->deprecated;
+ }
+
+ public function setDeprecated($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->deprecated = $var;
+ $this->has_deprecated = true;
+ }
+
+ public function hasDeprecated()
+ {
+ return $this->has_deprecated;
+ }
+
+ public function getCcEnableArenas()
+ {
+ return $this->cc_enable_arenas;
+ }
+
+ public function setCcEnableArenas($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->cc_enable_arenas = $var;
+ $this->has_cc_enable_arenas = true;
+ }
+
+ public function hasCcEnableArenas()
+ {
+ return $this->has_cc_enable_arenas;
+ }
+
+ public function getObjcClassPrefix()
+ {
+ return $this->objc_class_prefix;
+ }
+
+ public function setObjcClassPrefix($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->objc_class_prefix = $var;
+ $this->has_objc_class_prefix = true;
+ }
+
+ public function hasObjcClassPrefix()
+ {
+ return $this->has_objc_class_prefix;
+ }
+
+ public function getCsharpNamespace()
+ {
+ return $this->csharp_namespace;
+ }
+
+ public function setCsharpNamespace($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->csharp_namespace = $var;
+ $this->has_csharp_namespace = true;
+ }
+
+ public function hasCsharpNamespace()
+ {
+ return $this->has_csharp_namespace;
+ }
+
+ public function getUninterpretedOption()
+ {
+ return $this->uninterpreted_option;
+ }
+
+ public function setUninterpretedOption(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
+ $this->uninterpreted_option = $var;
+ $this->has_uninterpreted_option = true;
+ }
+
+ public function hasUninterpretedOption()
+ {
+ return $this->has_uninterpreted_option;
+ }
+
+}
+
+class FileOptions_OptimizeMode
+{
+ const SPEED = 1;
+ const CODE_SIZE = 2;
+ const LITE_RUNTIME = 3;
+}
+
+class MessageOptions extends \Google\Protobuf\Internal\Message
+{
+ private $message_set_wire_format = false;
+ private $has_message_set_wire_format = false;
+ private $no_standard_descriptor_accessor = false;
+ private $has_no_standard_descriptor_accessor = false;
+ private $deprecated = false;
+ private $has_deprecated = false;
+ private $map_entry = false;
+ private $has_map_entry = false;
+ private $uninterpreted_option;
+ private $has_uninterpreted_option = false;
+
+ public function getMessageSetWireFormat()
+ {
+ return $this->message_set_wire_format;
+ }
+
+ public function setMessageSetWireFormat($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->message_set_wire_format = $var;
+ $this->has_message_set_wire_format = true;
+ }
+
+ public function hasMessageSetWireFormat()
+ {
+ return $this->has_message_set_wire_format;
+ }
+
+ public function getNoStandardDescriptorAccessor()
+ {
+ return $this->no_standard_descriptor_accessor;
+ }
+
+ public function setNoStandardDescriptorAccessor($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->no_standard_descriptor_accessor = $var;
+ $this->has_no_standard_descriptor_accessor = true;
+ }
+
+ public function hasNoStandardDescriptorAccessor()
+ {
+ return $this->has_no_standard_descriptor_accessor;
+ }
+
+ public function getDeprecated()
+ {
+ return $this->deprecated;
+ }
+
+ public function setDeprecated($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->deprecated = $var;
+ $this->has_deprecated = true;
+ }
+
+ public function hasDeprecated()
+ {
+ return $this->has_deprecated;
+ }
+
+ public function getMapEntry()
+ {
+ return $this->map_entry;
+ }
+
+ public function setMapEntry($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->map_entry = $var;
+ $this->has_map_entry = true;
+ }
+
+ public function hasMapEntry()
+ {
+ return $this->has_map_entry;
+ }
+
+ public function getUninterpretedOption()
+ {
+ return $this->uninterpreted_option;
+ }
+
+ public function setUninterpretedOption(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
+ $this->uninterpreted_option = $var;
+ $this->has_uninterpreted_option = true;
+ }
+
+ public function hasUninterpretedOption()
+ {
+ return $this->has_uninterpreted_option;
+ }
+
+}
+
+class FieldOptions extends \Google\Protobuf\Internal\Message
+{
+ private $ctype = 0;
+ private $has_ctype = false;
+ private $packed = false;
+ private $has_packed = false;
+ private $jstype = 0;
+ private $has_jstype = false;
+ private $lazy = false;
+ private $has_lazy = false;
+ private $deprecated = false;
+ private $has_deprecated = false;
+ private $weak = false;
+ private $has_weak = false;
+ private $uninterpreted_option;
+ private $has_uninterpreted_option = false;
+
+ public function getCtype()
+ {
+ return $this->ctype;
+ }
+
+ public function setCtype($var)
+ {
+ GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions_CType::class);
+ $this->ctype = $var;
+ $this->has_ctype = true;
+ }
+
+ public function hasCtype()
+ {
+ return $this->has_ctype;
+ }
+
+ public function getPacked()
+ {
+ return $this->packed;
+ }
+
+ public function setPacked($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->packed = $var;
+ $this->has_packed = true;
+ }
+
+ public function hasPacked()
+ {
+ return $this->has_packed;
+ }
+
+ public function getJstype()
+ {
+ return $this->jstype;
+ }
+
+ public function setJstype($var)
+ {
+ GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions_JSType::class);
+ $this->jstype = $var;
+ $this->has_jstype = true;
+ }
+
+ public function hasJstype()
+ {
+ return $this->has_jstype;
+ }
+
+ public function getLazy()
+ {
+ return $this->lazy;
+ }
+
+ public function setLazy($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->lazy = $var;
+ $this->has_lazy = true;
+ }
+
+ public function hasLazy()
+ {
+ return $this->has_lazy;
+ }
+
+ public function getDeprecated()
+ {
+ return $this->deprecated;
+ }
+
+ public function setDeprecated($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->deprecated = $var;
+ $this->has_deprecated = true;
+ }
+
+ public function hasDeprecated()
+ {
+ return $this->has_deprecated;
+ }
+
+ public function getWeak()
+ {
+ return $this->weak;
+ }
+
+ public function setWeak($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->weak = $var;
+ $this->has_weak = true;
+ }
+
+ public function hasWeak()
+ {
+ return $this->has_weak;
+ }
+
+ public function getUninterpretedOption()
+ {
+ return $this->uninterpreted_option;
+ }
+
+ public function setUninterpretedOption(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
+ $this->uninterpreted_option = $var;
+ $this->has_uninterpreted_option = true;
+ }
+
+ public function hasUninterpretedOption()
+ {
+ return $this->has_uninterpreted_option;
+ }
+
+}
+
+class FieldOptions_CType
+{
+ const STRING = 0;
+ const CORD = 1;
+ const STRING_PIECE = 2;
+}
+
+class FieldOptions_JSType
+{
+ const JS_NORMAL = 0;
+ const JS_STRING = 1;
+ const JS_NUMBER = 2;
+}
+
+class OneofOptions extends \Google\Protobuf\Internal\Message
+{
+ private $uninterpreted_option;
+ private $has_uninterpreted_option = false;
+
+ public function getUninterpretedOption()
+ {
+ return $this->uninterpreted_option;
+ }
+
+ public function setUninterpretedOption(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
+ $this->uninterpreted_option = $var;
+ $this->has_uninterpreted_option = true;
+ }
+
+ public function hasUninterpretedOption()
+ {
+ return $this->has_uninterpreted_option;
+ }
+
+}
+
+class EnumOptions extends \Google\Protobuf\Internal\Message
+{
+ private $allow_alias = false;
+ private $has_allow_alias = false;
+ private $deprecated = false;
+ private $has_deprecated = false;
+ private $uninterpreted_option;
+ private $has_uninterpreted_option = false;
+
+ public function getAllowAlias()
+ {
+ return $this->allow_alias;
+ }
+
+ public function setAllowAlias($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->allow_alias = $var;
+ $this->has_allow_alias = true;
+ }
+
+ public function hasAllowAlias()
+ {
+ return $this->has_allow_alias;
+ }
+
+ public function getDeprecated()
+ {
+ return $this->deprecated;
+ }
+
+ public function setDeprecated($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->deprecated = $var;
+ $this->has_deprecated = true;
+ }
+
+ public function hasDeprecated()
+ {
+ return $this->has_deprecated;
+ }
+
+ public function getUninterpretedOption()
+ {
+ return $this->uninterpreted_option;
+ }
+
+ public function setUninterpretedOption(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
+ $this->uninterpreted_option = $var;
+ $this->has_uninterpreted_option = true;
+ }
+
+ public function hasUninterpretedOption()
+ {
+ return $this->has_uninterpreted_option;
+ }
+
+}
+
+class EnumValueOptions extends \Google\Protobuf\Internal\Message
+{
+ private $deprecated = false;
+ private $has_deprecated = false;
+ private $uninterpreted_option;
+ private $has_uninterpreted_option = false;
+
+ public function getDeprecated()
+ {
+ return $this->deprecated;
+ }
+
+ public function setDeprecated($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->deprecated = $var;
+ $this->has_deprecated = true;
+ }
+
+ public function hasDeprecated()
+ {
+ return $this->has_deprecated;
+ }
+
+ public function getUninterpretedOption()
+ {
+ return $this->uninterpreted_option;
+ }
+
+ public function setUninterpretedOption(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
+ $this->uninterpreted_option = $var;
+ $this->has_uninterpreted_option = true;
+ }
+
+ public function hasUninterpretedOption()
+ {
+ return $this->has_uninterpreted_option;
+ }
+
+}
+
+class ServiceOptions extends \Google\Protobuf\Internal\Message
+{
+ private $deprecated = false;
+ private $has_deprecated = false;
+ private $uninterpreted_option;
+ private $has_uninterpreted_option = false;
+
+ public function getDeprecated()
+ {
+ return $this->deprecated;
+ }
+
+ public function setDeprecated($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->deprecated = $var;
+ $this->has_deprecated = true;
+ }
+
+ public function hasDeprecated()
+ {
+ return $this->has_deprecated;
+ }
+
+ public function getUninterpretedOption()
+ {
+ return $this->uninterpreted_option;
+ }
+
+ public function setUninterpretedOption(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
+ $this->uninterpreted_option = $var;
+ $this->has_uninterpreted_option = true;
+ }
+
+ public function hasUninterpretedOption()
+ {
+ return $this->has_uninterpreted_option;
+ }
+
+}
+
+class MethodOptions extends \Google\Protobuf\Internal\Message
+{
+ private $deprecated = false;
+ private $has_deprecated = false;
+ private $uninterpreted_option;
+ private $has_uninterpreted_option = false;
+
+ public function getDeprecated()
+ {
+ return $this->deprecated;
+ }
+
+ public function setDeprecated($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->deprecated = $var;
+ $this->has_deprecated = true;
+ }
+
+ public function hasDeprecated()
+ {
+ return $this->has_deprecated;
+ }
+
+ public function getUninterpretedOption()
+ {
+ return $this->uninterpreted_option;
+ }
+
+ public function setUninterpretedOption(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
+ $this->uninterpreted_option = $var;
+ $this->has_uninterpreted_option = true;
+ }
+
+ public function hasUninterpretedOption()
+ {
+ return $this->has_uninterpreted_option;
+ }
+
+}
+
+class UninterpretedOption extends \Google\Protobuf\Internal\Message
+{
+ private $name;
+ private $has_name = false;
+ private $identifier_value = '';
+ private $has_identifier_value = false;
+ private $positive_int_value = 0;
+ private $has_positive_int_value = false;
+ private $negative_int_value = 0;
+ private $has_negative_int_value = false;
+ private $double_value = 0.0;
+ private $has_double_value = false;
+ private $string_value = '';
+ private $has_string_value = false;
+ private $aggregate_value = '';
+ private $has_aggregate_value = false;
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function setName(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption_NamePart::class);
+ $this->name = $var;
+ $this->has_name = true;
+ }
+
+ public function hasName()
+ {
+ return $this->has_name;
+ }
+
+ public function getIdentifierValue()
+ {
+ return $this->identifier_value;
+ }
+
+ public function setIdentifierValue($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->identifier_value = $var;
+ $this->has_identifier_value = true;
+ }
+
+ public function hasIdentifierValue()
+ {
+ return $this->has_identifier_value;
+ }
+
+ public function getPositiveIntValue()
+ {
+ return $this->positive_int_value;
+ }
+
+ public function setPositiveIntValue($var)
+ {
+ GPBUtil::checkUint64($var);
+ $this->positive_int_value = $var;
+ $this->has_positive_int_value = true;
+ }
+
+ public function hasPositiveIntValue()
+ {
+ return $this->has_positive_int_value;
+ }
+
+ public function getNegativeIntValue()
+ {
+ return $this->negative_int_value;
+ }
+
+ public function setNegativeIntValue($var)
+ {
+ GPBUtil::checkInt64($var);
+ $this->negative_int_value = $var;
+ $this->has_negative_int_value = true;
+ }
+
+ public function hasNegativeIntValue()
+ {
+ return $this->has_negative_int_value;
+ }
+
+ public function getDoubleValue()
+ {
+ return $this->double_value;
+ }
+
+ public function setDoubleValue($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->double_value = $var;
+ $this->has_double_value = true;
+ }
+
+ public function hasDoubleValue()
+ {
+ return $this->has_double_value;
+ }
+
+ public function getStringValue()
+ {
+ return $this->string_value;
+ }
+
+ public function setStringValue($var)
+ {
+ GPBUtil::checkString($var, False);
+ $this->string_value = $var;
+ $this->has_string_value = true;
+ }
+
+ public function hasStringValue()
+ {
+ return $this->has_string_value;
+ }
+
+ public function getAggregateValue()
+ {
+ return $this->aggregate_value;
+ }
+
+ public function setAggregateValue($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->aggregate_value = $var;
+ $this->has_aggregate_value = true;
+ }
+
+ public function hasAggregateValue()
+ {
+ return $this->has_aggregate_value;
+ }
+
+}
+
+class UninterpretedOption_NamePart extends \Google\Protobuf\Internal\Message
+{
+ private $name_part = '';
+ private $has_name_part = false;
+ private $is_extension = false;
+ private $has_is_extension = false;
+
+ public function getNamePart()
+ {
+ return $this->name_part;
+ }
+
+ public function setNamePart($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->name_part = $var;
+ $this->has_name_part = true;
+ }
+
+ public function hasNamePart()
+ {
+ return $this->has_name_part;
+ }
+
+ public function getIsExtension()
+ {
+ return $this->is_extension;
+ }
+
+ public function setIsExtension($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->is_extension = $var;
+ $this->has_is_extension = true;
+ }
+
+ public function hasIsExtension()
+ {
+ return $this->has_is_extension;
+ }
+
+}
+
+class SourceCodeInfo extends \Google\Protobuf\Internal\Message
+{
+ private $location;
+ private $has_location = false;
+
+ public function getLocation()
+ {
+ return $this->location;
+ }
+
+ public function setLocation(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\SourceCodeInfo_Location::class);
+ $this->location = $var;
+ $this->has_location = true;
+ }
+
+ public function hasLocation()
+ {
+ return $this->has_location;
+ }
+
+}
+
+class SourceCodeInfo_Location extends \Google\Protobuf\Internal\Message
+{
+ private $path;
+ private $has_path = false;
+ private $span;
+ private $has_span = false;
+ private $leading_comments = '';
+ private $has_leading_comments = false;
+ private $trailing_comments = '';
+ private $has_trailing_comments = false;
+ private $leading_detached_comments;
+ private $has_leading_detached_comments = false;
+
+ public function getPath()
+ {
+ return $this->path;
+ }
+
+ public function setPath(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::INT32);
+ $this->path = $var;
+ $this->has_path = true;
+ }
+
+ public function hasPath()
+ {
+ return $this->has_path;
+ }
+
+ public function getSpan()
+ {
+ return $this->span;
+ }
+
+ public function setSpan(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::INT32);
+ $this->span = $var;
+ $this->has_span = true;
+ }
+
+ public function hasSpan()
+ {
+ return $this->has_span;
+ }
+
+ public function getLeadingComments()
+ {
+ return $this->leading_comments;
+ }
+
+ public function setLeadingComments($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->leading_comments = $var;
+ $this->has_leading_comments = true;
+ }
+
+ public function hasLeadingComments()
+ {
+ return $this->has_leading_comments;
+ }
+
+ public function getTrailingComments()
+ {
+ return $this->trailing_comments;
+ }
+
+ public function setTrailingComments($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->trailing_comments = $var;
+ $this->has_trailing_comments = true;
+ }
+
+ public function hasTrailingComments()
+ {
+ return $this->has_trailing_comments;
+ }
+
+ public function getLeadingDetachedComments()
+ {
+ return $this->leading_detached_comments;
+ }
+
+ public function setLeadingDetachedComments(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::STRING);
+ $this->leading_detached_comments = $var;
+ $this->has_leading_detached_comments = true;
+ }
+
+ public function hasLeadingDetachedComments()
+ {
+ return $this->has_leading_detached_comments;
+ }
+
+}
+
+class GeneratedCodeInfo extends \Google\Protobuf\Internal\Message
+{
+ private $annotation;
+ private $has_annotation = false;
+
+ public function getAnnotation()
+ {
+ return $this->annotation;
+ }
+
+ public function setAnnotation(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation::class);
+ $this->annotation = $var;
+ $this->has_annotation = true;
+ }
+
+ public function hasAnnotation()
+ {
+ return $this->has_annotation;
+ }
+
+}
+
+class GeneratedCodeInfo_Annotation extends \Google\Protobuf\Internal\Message
+{
+ private $path;
+ private $has_path = false;
+ private $source_file = '';
+ private $has_source_file = false;
+ private $begin = 0;
+ private $has_begin = false;
+ private $end = 0;
+ private $has_end = false;
+
+ public function getPath()
+ {
+ return $this->path;
+ }
+
+ public function setPath(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::INT32);
+ $this->path = $var;
+ $this->has_path = true;
+ }
+
+ public function hasPath()
+ {
+ return $this->has_path;
+ }
+
+ public function getSourceFile()
+ {
+ return $this->source_file;
+ }
+
+ public function setSourceFile($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->source_file = $var;
+ $this->has_source_file = true;
+ }
+
+ public function hasSourceFile()
+ {
+ return $this->has_source_file;
+ }
+
+ public function getBegin()
+ {
+ return $this->begin;
+ }
+
+ public function setBegin($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->begin = $var;
+ $this->has_begin = true;
+ }
+
+ public function hasBegin()
+ {
+ return $this->has_begin;
+ }
+
+ public function getEnd()
+ {
+ return $this->end;
+ }
+
+ public function setEnd($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->end = $var;
+ $this->has_end = true;
+ }
+
+ public function hasEnd()
+ {
+ return $this->has_end;
+ }
+
+}
+
+$pool = DescriptorPool::getGeneratedPool();
+
+$pool->addMessage('google.protobuf.internal.FileDescriptorSet', FileDescriptorSet::class)
+ ->repeated('file', GPBType::MESSAGE, 1, 'google.protobuf.internal.FileDescriptorProto')
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.FileDescriptorProto', FileDescriptorProto::class)
+ ->optional('name', GPBType::STRING, 1)
+ ->optional('package', GPBType::STRING, 2)
+ ->repeated('dependency', GPBType::STRING, 3)
+ ->repeated('public_dependency', GPBType::INT32, 10)
+ ->repeated('weak_dependency', GPBType::INT32, 11)
+ ->repeated('message_type', GPBType::MESSAGE, 4, 'google.protobuf.internal.DescriptorProto')
+ ->repeated('enum_type', GPBType::MESSAGE, 5, 'google.protobuf.internal.EnumDescriptorProto')
+ ->repeated('service', GPBType::MESSAGE, 6, 'google.protobuf.internal.ServiceDescriptorProto')
+ ->repeated('extension', GPBType::MESSAGE, 7, 'google.protobuf.internal.FieldDescriptorProto')
+ ->optional('options', GPBType::MESSAGE, 8, 'google.protobuf.internal.FileOptions')
+ ->optional('source_code_info', GPBType::MESSAGE, 9, 'google.protobuf.internal.SourceCodeInfo')
+ ->optional('syntax', GPBType::STRING, 12)
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.DescriptorProto', DescriptorProto::class)
+ ->optional('name', GPBType::STRING, 1)
+ ->repeated('field', GPBType::MESSAGE, 2, 'google.protobuf.internal.FieldDescriptorProto')
+ ->repeated('extension', GPBType::MESSAGE, 6, 'google.protobuf.internal.FieldDescriptorProto')
+ ->repeated('nested_type', GPBType::MESSAGE, 3, 'google.protobuf.internal.DescriptorProto')
+ ->repeated('enum_type', GPBType::MESSAGE, 4, 'google.protobuf.internal.EnumDescriptorProto')
+ ->repeated('extension_range', GPBType::MESSAGE, 5, 'google.protobuf.internal.DescriptorProto.ExtensionRange')
+ ->repeated('oneof_decl', GPBType::MESSAGE, 8, 'google.protobuf.internal.OneofDescriptorProto')
+ ->optional('options', GPBType::MESSAGE, 7, 'google.protobuf.internal.MessageOptions')
+ ->repeated('reserved_range', GPBType::MESSAGE, 9, 'google.protobuf.internal.DescriptorProto.ReservedRange')
+ ->repeated('reserved_name', GPBType::STRING, 10)
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.DescriptorProto.ExtensionRange', DescriptorProto_ExtensionRange::class)
+ ->optional('start', GPBType::INT32, 1)
+ ->optional('end', GPBType::INT32, 2)
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.DescriptorProto.ReservedRange', DescriptorProto_ReservedRange::class)
+ ->optional('start', GPBType::INT32, 1)
+ ->optional('end', GPBType::INT32, 2)
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.FieldDescriptorProto', FieldDescriptorProto::class)
+ ->optional('name', GPBType::STRING, 1)
+ ->optional('number', GPBType::INT32, 3)
+ ->optional('label', GPBType::ENUM, 4, 'google.protobuf.internal.FieldDescriptorProto.Label')
+ ->optional('type', GPBType::ENUM, 5, 'google.protobuf.internal.FieldDescriptorProto.Type')
+ ->optional('type_name', GPBType::STRING, 6)
+ ->optional('extendee', GPBType::STRING, 2)
+ ->optional('default_value', GPBType::STRING, 7)
+ ->optional('oneof_index', GPBType::INT32, 9)
+ ->optional('json_name', GPBType::STRING, 10)
+ ->optional('options', GPBType::MESSAGE, 8, 'google.protobuf.internal.FieldOptions')
+ ->finalizeToPool();
+
+$pool->addEnum('google.protobuf.internal.FieldDescriptorProto.Type', Type::class)
+ ->value("TYPE_DOUBLE", 1)
+ ->value("TYPE_FLOAT", 2)
+ ->value("TYPE_INT64", 3)
+ ->value("TYPE_UINT64", 4)
+ ->value("TYPE_INT32", 5)
+ ->value("TYPE_FIXED64", 6)
+ ->value("TYPE_FIXED32", 7)
+ ->value("TYPE_BOOL", 8)
+ ->value("TYPE_STRING", 9)
+ ->value("TYPE_GROUP", 10)
+ ->value("TYPE_MESSAGE", 11)
+ ->value("TYPE_BYTES", 12)
+ ->value("TYPE_UINT32", 13)
+ ->value("TYPE_ENUM", 14)
+ ->value("TYPE_SFIXED32", 15)
+ ->value("TYPE_SFIXED64", 16)
+ ->value("TYPE_SINT32", 17)
+ ->value("TYPE_SINT64", 18)
+ ->finalizeToPool();
+
+$pool->addEnum('google.protobuf.internal.FieldDescriptorProto.Label', Label::class)
+ ->value("LABEL_OPTIONAL", 1)
+ ->value("LABEL_REQUIRED", 2)
+ ->value("LABEL_REPEATED", 3)
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.OneofDescriptorProto', OneofDescriptorProto::class)
+ ->optional('name', GPBType::STRING, 1)
+ ->optional('options', GPBType::MESSAGE, 2, 'google.protobuf.internal.OneofOptions')
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.EnumDescriptorProto', EnumDescriptorProto::class)
+ ->optional('name', GPBType::STRING, 1)
+ ->repeated('value', GPBType::MESSAGE, 2, 'google.protobuf.internal.EnumValueDescriptorProto')
+ ->optional('options', GPBType::MESSAGE, 3, 'google.protobuf.internal.EnumOptions')
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.EnumValueDescriptorProto', EnumValueDescriptorProto::class)
+ ->optional('name', GPBType::STRING, 1)
+ ->optional('number', GPBType::INT32, 2)
+ ->optional('options', GPBType::MESSAGE, 3, 'google.protobuf.internal.EnumValueOptions')
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.ServiceDescriptorProto', ServiceDescriptorProto::class)
+ ->optional('name', GPBType::STRING, 1)
+ ->repeated('method', GPBType::MESSAGE, 2, 'google.protobuf.internal.MethodDescriptorProto')
+ ->optional('options', GPBType::MESSAGE, 3, 'google.protobuf.internal.ServiceOptions')
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.MethodDescriptorProto', MethodDescriptorProto::class)
+ ->optional('name', GPBType::STRING, 1)
+ ->optional('input_type', GPBType::STRING, 2)
+ ->optional('output_type', GPBType::STRING, 3)
+ ->optional('options', GPBType::MESSAGE, 4, 'google.protobuf.internal.MethodOptions')
+ ->optional('client_streaming', GPBType::BOOL, 5)
+ ->optional('server_streaming', GPBType::BOOL, 6)
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.FileOptions', FileOptions::class)
+ ->optional('java_package', GPBType::STRING, 1)
+ ->optional('java_outer_classname', GPBType::STRING, 8)
+ ->optional('java_multiple_files', GPBType::BOOL, 10)
+ ->optional('java_generate_equals_and_hash', GPBType::BOOL, 20)
+ ->optional('java_string_check_utf8', GPBType::BOOL, 27)
+ ->optional('optimize_for', GPBType::ENUM, 9, 'google.protobuf.internal.FileOptions.OptimizeMode')
+ ->optional('go_package', GPBType::STRING, 11)
+ ->optional('cc_generic_services', GPBType::BOOL, 16)
+ ->optional('java_generic_services', GPBType::BOOL, 17)
+ ->optional('py_generic_services', GPBType::BOOL, 18)
+ ->optional('deprecated', GPBType::BOOL, 23)
+ ->optional('cc_enable_arenas', GPBType::BOOL, 31)
+ ->optional('objc_class_prefix', GPBType::STRING, 36)
+ ->optional('csharp_namespace', GPBType::STRING, 37)
+ ->repeated('uninterpreted_option', GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption')
+ ->finalizeToPool();
+
+$pool->addEnum('google.protobuf.internal.FileOptions.OptimizeMode', OptimizeMode::class)
+ ->value("SPEED", 1)
+ ->value("CODE_SIZE", 2)
+ ->value("LITE_RUNTIME", 3)
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.MessageOptions', MessageOptions::class)
+ ->optional('message_set_wire_format', GPBType::BOOL, 1)
+ ->optional('no_standard_descriptor_accessor', GPBType::BOOL, 2)
+ ->optional('deprecated', GPBType::BOOL, 3)
+ ->optional('map_entry', GPBType::BOOL, 7)
+ ->repeated('uninterpreted_option', GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption')
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.FieldOptions', FieldOptions::class)
+ ->optional('ctype', GPBType::ENUM, 1, 'google.protobuf.internal.FieldOptions.CType')
+ ->optional('packed', GPBType::BOOL, 2)
+ ->optional('jstype', GPBType::ENUM, 6, 'google.protobuf.internal.FieldOptions.JSType')
+ ->optional('lazy', GPBType::BOOL, 5)
+ ->optional('deprecated', GPBType::BOOL, 3)
+ ->optional('weak', GPBType::BOOL, 10)
+ ->repeated('uninterpreted_option', GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption')
+ ->finalizeToPool();
+
+$pool->addEnum('google.protobuf.internal.FieldOptions.CType', CType::class)
+ ->value("STRING", 0)
+ ->value("CORD", 1)
+ ->value("STRING_PIECE", 2)
+ ->finalizeToPool();
+
+$pool->addEnum('google.protobuf.internal.FieldOptions.JSType', JSType::class)
+ ->value("JS_NORMAL", 0)
+ ->value("JS_STRING", 1)
+ ->value("JS_NUMBER", 2)
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.OneofOptions', OneofOptions::class)
+ ->repeated('uninterpreted_option', GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption')
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.EnumOptions', EnumOptions::class)
+ ->optional('allow_alias', GPBType::BOOL, 2)
+ ->optional('deprecated', GPBType::BOOL, 3)
+ ->repeated('uninterpreted_option', GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption')
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.EnumValueOptions', EnumValueOptions::class)
+ ->optional('deprecated', GPBType::BOOL, 1)
+ ->repeated('uninterpreted_option', GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption')
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.ServiceOptions', ServiceOptions::class)
+ ->optional('deprecated', GPBType::BOOL, 33)
+ ->repeated('uninterpreted_option', GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption')
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.MethodOptions', MethodOptions::class)
+ ->optional('deprecated', GPBType::BOOL, 33)
+ ->repeated('uninterpreted_option', GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption')
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.UninterpretedOption', UninterpretedOption::class)
+ ->repeated('name', GPBType::MESSAGE, 2, 'google.protobuf.internal.UninterpretedOption.NamePart')
+ ->optional('identifier_value', GPBType::STRING, 3)
+ ->optional('positive_int_value', GPBType::UINT64, 4)
+ ->optional('negative_int_value', GPBType::INT64, 5)
+ ->optional('double_value', GPBType::DOUBLE, 6)
+ ->optional('string_value', GPBType::BYTES, 7)
+ ->optional('aggregate_value', GPBType::STRING, 8)
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.UninterpretedOption.NamePart', UninterpretedOption_NamePart::class)
+ ->required('name_part', GPBType::STRING, 1)
+ ->required('is_extension', GPBType::BOOL, 2)
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.SourceCodeInfo', SourceCodeInfo::class)
+ ->repeated('location', GPBType::MESSAGE, 1, 'google.protobuf.internal.SourceCodeInfo.Location')
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.SourceCodeInfo.Location', SourceCodeInfo_Location::class)
+ ->repeated('path', GPBType::INT32, 1)
+ ->repeated('span', GPBType::INT32, 2)
+ ->optional('leading_comments', GPBType::STRING, 3)
+ ->optional('trailing_comments', GPBType::STRING, 4)
+ ->repeated('leading_detached_comments', GPBType::STRING, 6)
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.GeneratedCodeInfo', GeneratedCodeInfo::class)
+ ->repeated('annotation', GPBType::MESSAGE, 1, 'google.protobuf.internal.GeneratedCodeInfo.Annotation')
+ ->finalizeToPool();
+
+$pool->addMessage('google.protobuf.internal.GeneratedCodeInfo.Annotation', GeneratedCodeInfo_Annotation::class)
+ ->repeated('path', GPBType::INT32, 1)
+ ->optional('source_file', GPBType::STRING, 2)
+ ->optional('begin', GPBType::INT32, 3)
+ ->optional('end', GPBType::INT32, 4)
+ ->finalizeToPool();
+
+$pool->finish();
diff --git a/php/src/phpdoc.dist.xml b/php/src/phpdoc.dist.xml
new file mode 100644
index 00000000..dd313025
--- /dev/null
+++ b/php/src/phpdoc.dist.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- Install phpDocumentor to generate docs. -->
+<phpdoc>
+ <parser>
+ <target>doc</target>
+ </parser>
+ <transformer>
+ <target>doc</target>
+ </transformer>
+ <files>
+ <file>Google/Protobuf/Internal/MapField.php</file>
+ <file>Google/Protobuf/Internal/Message.php</file>
+ <file>Google/Protobuf/Internal/RepeatedField.php</file>
+ </files>
+</phpdoc>
diff --git a/php/tests/array_test.php b/php/tests/array_test.php
new file mode 100644
index 00000000..d683add5
--- /dev/null
+++ b/php/tests/array_test.php
@@ -0,0 +1,888 @@
+<?php
+
+require_once('test.pb.php');
+require_once('test_util.php');
+
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBType;
+use Foo\TestMessage;
+use Foo\TestMessage_Sub;
+
+class RepeatedFieldTest extends PHPUnit_Framework_TestCase
+{
+
+ #########################################################
+ # Test int32 field.
+ #########################################################
+
+ public function testInt32()
+ {
+ $arr = new RepeatedField(GPBType::INT32);
+
+ // Test append.
+ $arr []= MAX_INT32;
+ $this->assertSame(MAX_INT32, $arr[0]);
+ $arr []= MIN_INT32;
+ $this->assertSame(MIN_INT32, $arr[1]);
+
+ $arr []= 1.1;
+ $this->assertSame(1, $arr[2]);
+ $arr []= MAX_INT32_FLOAT;
+ $this->assertSame(MAX_INT32, $arr[3]);
+ $arr []= MAX_INT32_FLOAT;
+ $this->assertSame(MAX_INT32, $arr[4]);
+
+ $arr []= '2';
+ $this->assertSame(2, $arr[5]);
+ $arr []= '3.1';
+ $this->assertSame(3, $arr[6]);
+ $arr []= MAX_INT32_STRING;
+ $this->assertSame(MAX_INT32, $arr[7]);
+
+ $this->assertEquals(8, count($arr));
+
+ for ($i = 0; $i < count($arr); $i++) {
+ $arr[$i] = 0;
+ $this->assertSame(0, $arr[$i]);
+ }
+
+ // Test set.
+ $arr [0]= MAX_INT32;
+ $this->assertSame(MAX_INT32, $arr[0]);
+ $arr [1]= MIN_INT32;
+ $this->assertSame(MIN_INT32, $arr[1]);
+
+ $arr [2]= 1.1;
+ $this->assertSame(1, $arr[2]);
+ $arr [3]= MAX_INT32_FLOAT;
+ $this->assertSame(MAX_INT32, $arr[3]);
+ $arr [4]= MAX_INT32_FLOAT;
+ $this->assertSame(MAX_INT32, $arr[4]);
+
+ $arr [5]= '2';
+ $this->assertSame(2, $arr[5]);
+ $arr [6]= '3.1';
+ $this->assertSame(3, $arr[6]);
+ $arr [7]= MAX_INT32_STRING;
+ $this->assertSame(MAX_INT32, $arr[7]);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt32AppendStringFail()
+ {
+ $arr = new RepeatedField(GPBType::INT32);
+ $arr []= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt32SetStringFail()
+ {
+ $arr = new RepeatedField(GPBType::INT32);
+ $arr []= 0;
+ $arr [0]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt32AppendMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::INT32);
+ $arr []= new TestMessage_Sub();
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt32SetMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::INT32);
+ $arr []= 0;
+ $arr [0]= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test uint32 field.
+ #########################################################
+
+ public function testUint32()
+ {
+ $arr = new RepeatedField(GPBType::UINT32);
+
+ // Test append.
+ $arr []= MAX_UINT32;
+ $this->assertSame(-1, $arr[0]);
+ $arr []= -1;
+ $this->assertSame(-1, $arr[1]);
+ $arr []= MIN_UINT32;
+ $this->assertSame(MIN_UINT32, $arr[2]);
+
+ $arr []= 1.1;
+ $this->assertSame(1, $arr[3]);
+ $arr []= MAX_UINT32_FLOAT;
+ $this->assertSame(-1, $arr[4]);
+ $arr []= -1.0;
+ $this->assertSame(-1, $arr[5]);
+ $arr []= MIN_UINT32_FLOAT;
+ $this->assertSame(MIN_UINT32, $arr[6]);
+
+ $arr []= '2';
+ $this->assertSame(2, $arr[7]);
+ $arr []= '3.1';
+ $this->assertSame(3, $arr[8]);
+ $arr []= MAX_UINT32_STRING;
+ $this->assertSame(-1, $arr[9]);
+ $arr []= '-1.0';
+ $this->assertSame(-1, $arr[10]);
+ $arr []= MIN_UINT32_STRING;
+ $this->assertSame(MIN_UINT32, $arr[11]);
+
+ $this->assertEquals(12, count($arr));
+
+ for ($i = 0; $i < count($arr); $i++) {
+ $arr[$i] = 0;
+ $this->assertSame(0, $arr[$i]);
+ }
+
+ // Test set.
+ $arr [0]= MAX_UINT32;
+ $this->assertSame(-1, $arr[0]);
+ $arr [1]= -1;
+ $this->assertSame(-1, $arr[1]);
+ $arr [2]= MIN_UINT32;
+ $this->assertSame(MIN_UINT32, $arr[2]);
+
+ $arr [3]= 1.1;
+ $this->assertSame(1, $arr[3]);
+ $arr [4]= MAX_UINT32_FLOAT;
+ $this->assertSame(-1, $arr[4]);
+ $arr [5]= -1.0;
+ $this->assertSame(-1, $arr[5]);
+ $arr [6]= MIN_UINT32_FLOAT;
+ $this->assertSame(MIN_UINT32, $arr[6]);
+
+ $arr [7]= '2';
+ $this->assertSame(2, $arr[7]);
+ $arr [8]= '3.1';
+ $this->assertSame(3, $arr[8]);
+ $arr [9]= MAX_UINT32_STRING;
+ $this->assertSame(-1, $arr[9]);
+ $arr [10]= '-1.0';
+ $this->assertSame(-1, $arr[10]);
+ $arr [11]= MIN_UINT32_STRING;
+ $this->assertSame(MIN_UINT32, $arr[11]);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint32AppendStringFail()
+ {
+ $arr = new RepeatedField(GPBType::UINT32);
+ $arr []= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint32SetStringFail()
+ {
+ $arr = new RepeatedField(GPBType::UINT32);
+ $arr []= 0;
+ $arr [0]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint32AppendMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::UINT32);
+ $arr []= new TestMessage_Sub();
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint32SetMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::UINT32);
+ $arr []= 0;
+ $arr [0]= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test int64 field.
+ #########################################################
+
+ public function testInt64()
+ {
+ $arr = new RepeatedField(GPBType::INT64);
+
+ // Test append.
+ $arr []= MAX_INT64;
+ $this->assertSame(MAX_INT64, $arr[0]);
+ $arr []= MIN_INT64;
+ $this->assertEquals(MIN_INT64, $arr[1]);
+
+ $arr []= 1.1;
+ $this->assertSame(1, $arr[2]);
+
+ $arr []= '2';
+ $this->assertSame(2, $arr[3]);
+ $arr []= '3.1';
+ $this->assertSame(3, $arr[4]);
+ $arr []= MAX_INT64_STRING;
+ $this->assertSame(MAX_INT64, $arr[5]);
+ $arr []= MIN_INT64_STRING;
+ $this->assertEquals(MIN_INT64, $arr[6]);
+
+ $this->assertEquals(7, count($arr));
+
+ for ($i = 0; $i < count($arr); $i++) {
+ $arr[$i] = 0;
+ $this->assertSame(0, $arr[$i]);
+ }
+
+ // Test set.
+ $arr [0]= MAX_INT64;
+ $this->assertSame(MAX_INT64, $arr[0]);
+ $arr [1]= MIN_INT64;
+ $this->assertEquals(MIN_INT64, $arr[1]);
+
+ $arr [2]= 1.1;
+ $this->assertSame(1, $arr[2]);
+
+ $arr [3]= '2';
+ $this->assertSame(2, $arr[3]);
+ $arr [4]= '3.1';
+ $this->assertSame(3, $arr[4]);
+ $arr [5]= MAX_INT64_STRING;
+ $this->assertSame(MAX_INT64, $arr[5]);
+ $arr [6]= MIN_INT64_STRING;
+ $this->assertEquals(MIN_INT64, $arr[6]);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt64AppendStringFail()
+ {
+ $arr = new RepeatedField(GPBType::INT64);
+ $arr []= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt64SetStringFail()
+ {
+ $arr = new RepeatedField(GPBType::INT64);
+ $arr []= 0;
+ $arr [0]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt64AppendMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::INT64);
+ $arr []= new TestMessage_Sub();
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt64SetMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::INT64);
+ $arr []= 0;
+ $arr [0]= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test uint64 field.
+ #########################################################
+
+ public function testUint64()
+ {
+ $arr = new RepeatedField(GPBType::UINT64);
+
+ // Test append.
+ $arr []= MAX_UINT64;
+ $this->assertEquals(MAX_UINT64, $arr[0]);
+
+ $arr []= 1.1;
+ $this->assertSame(1, $arr[1]);
+
+ $arr []= '2';
+ $this->assertSame(2, $arr[2]);
+ $arr []= '3.1';
+ $this->assertSame(3, $arr[3]);
+ $arr []= MAX_UINT64_STRING;
+ $this->assertEquals(MAX_UINT64, $arr[4]);
+
+ $this->assertEquals(5, count($arr));
+
+ for ($i = 0; $i < count($arr); $i++) {
+ $arr[$i] = 0;
+ $this->assertSame(0, $arr[$i]);
+ }
+
+ // Test set.
+ $arr [0]= MAX_UINT64;
+ $this->assertEquals(MAX_UINT64, $arr[0]);
+
+ $arr [1]= 1.1;
+ $this->assertSame(1, $arr[1]);
+
+ $arr [2]= '2';
+ $this->assertSame(2, $arr[2]);
+ $arr [3]= '3.1';
+ $this->assertSame(3, $arr[3]);
+ $arr [4]= MAX_UINT64_STRING;
+ $this->assertEquals(MAX_UINT64, $arr[4]);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint64AppendStringFail()
+ {
+ $arr = new RepeatedField(GPBType::UINT64);
+ $arr []= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint64SetStringFail()
+ {
+ $arr = new RepeatedField(GPBType::UINT64);
+ $arr []= 0;
+ $arr [0]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint64AppendMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::UINT64);
+ $arr []= new TestMessage_Sub();
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint64SetMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::UINT64);
+ $arr []= 0;
+ $arr [0]= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test float field.
+ #########################################################
+
+ public function testFloat()
+ {
+ $arr = new RepeatedField(GPBType::FLOAT);
+
+ // Test append.
+ $arr []= 1;
+ $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
+
+ $arr []= 1.1;
+ $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
+
+ $arr []= '2';
+ $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
+ $arr []= '3.1';
+ $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
+
+ $this->assertEquals(4, count($arr));
+
+ for ($i = 0; $i < count($arr); $i++) {
+ $arr[$i] = 0;
+ $this->assertSame(0.0, $arr[$i]);
+ }
+
+ // Test set.
+ $arr [0]= 1;
+ $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
+
+ $arr [1]= 1.1;
+ $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
+
+ $arr [2]= '2';
+ $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
+ $arr [3]= '3.1';
+ $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testFloatAppendStringFail()
+ {
+ $arr = new RepeatedField(GPBType::FLOAT);
+ $arr []= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testFloatSetStringFail()
+ {
+ $arr = new RepeatedField(GPBType::FLOAT);
+ $arr []= 0.0;
+ $arr [0]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testFloatAppendMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::FLOAT);
+ $arr []= new TestMessage_Sub();
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testFloatSetMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::FLOAT);
+ $arr []= 0.0;
+ $arr [0]= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test double field.
+ #########################################################
+
+ public function testDouble()
+ {
+ $arr = new RepeatedField(GPBType::DOUBLE);
+
+ // Test append.
+ $arr []= 1;
+ $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
+
+ $arr []= 1.1;
+ $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
+
+ $arr []= '2';
+ $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
+ $arr []= '3.1';
+ $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
+
+ $this->assertEquals(4, count($arr));
+
+ for ($i = 0; $i < count($arr); $i++) {
+ $arr[$i] = 0;
+ $this->assertSame(0.0, $arr[$i]);
+ }
+
+ // Test set.
+ $arr [0]= 1;
+ $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
+
+ $arr [1]= 1.1;
+ $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
+
+ $arr [2]= '2';
+ $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
+ $arr [3]= '3.1';
+ $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testDoubleAppendStringFail()
+ {
+ $arr = new RepeatedField(GPBType::DOUBLE);
+ $arr []= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testDoubleSetStringFail()
+ {
+ $arr = new RepeatedField(GPBType::DOUBLE);
+ $arr []= 0.0;
+ $arr [0]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testDoubleAppendMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::DOUBLE);
+ $arr []= new TestMessage_Sub();
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testDoubleSetMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::DOUBLE);
+ $arr []= 0.0;
+ $arr [0]= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test bool field.
+ #########################################################
+
+ public function testBool()
+ {
+ $arr = new RepeatedField(GPBType::BOOL);
+
+ // Test append.
+ $arr []= true;
+ $this->assertSame(true, $arr[0]);
+
+ $arr []= -1;
+ $this->assertSame(true, $arr[1]);
+
+ $arr []= 1.1;
+ $this->assertSame(true, $arr[2]);
+
+ $arr []= '';
+ $this->assertSame(false, $arr[3]);
+
+ $this->assertEquals(4, count($arr));
+
+ for ($i = 0; $i < count($arr); $i++) {
+ $arr[$i] = 0;
+ $this->assertSame(false, $arr[$i]);
+ }
+
+ // Test set.
+ $arr [0]= true;
+ $this->assertSame(true, $arr[0]);
+
+ $arr [1]= -1;
+ $this->assertSame(true, $arr[1]);
+
+ $arr [2]= 1.1;
+ $this->assertSame(true, $arr[2]);
+
+ $arr [3]= '';
+ $this->assertSame(false, $arr[3]);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testBoolAppendMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::BOOL);
+ $arr []= new TestMessage_Sub();
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testBoolSetMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::BOOL);
+ $arr []= true;
+ $arr [0]= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test string field.
+ #########################################################
+
+ public function testString()
+ {
+ $arr = new RepeatedField(GPBType::STRING);
+
+ // Test append.
+ $arr []= 'abc';
+ $this->assertSame('abc', $arr[0]);
+
+ $arr []= 1;
+ $this->assertSame('1', $arr[1]);
+
+ $arr []= 1.1;
+ $this->assertSame('1.1', $arr[2]);
+
+ $arr []= true;
+ $this->assertSame('1', $arr[3]);
+
+ $this->assertEquals(4, count($arr));
+
+ for ($i = 0; $i < count($arr); $i++) {
+ $arr[$i] = '';
+ $this->assertSame('', $arr[$i]);
+ }
+
+ // Test set.
+ $arr [0]= 'abc';
+ $this->assertSame('abc', $arr[0]);
+
+ $arr [1]= 1;
+ $this->assertSame('1', $arr[1]);
+
+ $arr [2]= 1.1;
+ $this->assertSame('1.1', $arr[2]);
+
+ $arr [3]= true;
+ $this->assertSame('1', $arr[3]);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testStringAppendMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::STRING);
+ $arr []= new TestMessage_Sub();
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testStringSetMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::STRING);
+ $arr []= 'abc';
+ $arr [0]= new TestMessage_Sub();
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testStringAppendInvalidUTF8Fail()
+ {
+ $arr = new RepeatedField(GPBType::STRING);
+ $hex = hex2bin("ff");
+ $arr []= $hex;
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testStringSetInvalidUTF8Fail()
+ {
+ $arr = new RepeatedField(GPBType::STRING);
+ $arr []= 'abc';
+ $hex = hex2bin("ff");
+ $arr [0]= $hex;
+ }
+
+ #########################################################
+ # Test message field.
+ #########################################################
+
+ public function testMessage()
+ {
+ $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+
+ // Test append.
+ $sub_m = new TestMessage_Sub();
+ $sub_m->setA(1);
+ $arr []= $sub_m;
+ $this->assertSame(1, $arr[0]->getA());
+
+ $null = null;
+ $arr []= $null;
+ $this->assertNull($arr[1]);
+
+ $this->assertEquals(2, count($arr));
+
+ for ($i = 0; $i < count($arr); $i++) {
+ $arr[$i] = $null;
+ $this->assertNull($arr[$i]);
+ }
+
+ // Test set.
+ $arr [0]= $sub_m;
+ $this->assertSame(1, $arr[0]->getA());
+
+ $arr [1]= $null;
+ $this->assertNull($arr[1]);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testMessageAppendIntFail()
+ {
+ $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+ $arr []= 1;
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testMessageSetIntFail()
+ {
+ $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+ $arr []= new TestMessage_Sub;
+ $arr [0]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testMessageAppendStringFail()
+ {
+ $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+ $arr []= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testMessageSetStringFail()
+ {
+ $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+ $arr []= new TestMessage_Sub;
+ $arr [0]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testMessageAppendOtherMessageFail()
+ {
+ $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+ $arr []= new TestMessage;
+ }
+
+ #########################################################
+ # Test offset type
+ #########################################################
+
+ public function testOffset()
+ {
+ $arr = new RepeatedField(GPBType::INT32);
+ $arr []= 0;
+
+ $arr [0]= 1;
+ $this->assertSame(1, $arr[0]);
+ $this->assertSame(1, count($arr));
+
+ $arr ['0']= 2;
+ $this->assertSame(2, $arr['0']);
+ $this->assertSame(2, $arr[0]);
+ $this->assertSame(1, count($arr));
+
+ $arr [0.0]= 3;
+ $this->assertSame(3, $arr[0.0]);
+ $this->assertSame(1, count($arr));
+ }
+
+ public function testInsertRemoval()
+ {
+ $arr = new RepeatedField(GPBType::INT32);
+
+ $arr []= 0;
+ $arr []= 1;
+ $arr []= 2;
+ $this->assertSame(3, count($arr));
+
+ unset($arr[2]);
+ $this->assertSame(2, count($arr));
+ $this->assertSame(0, $arr[0]);
+ $this->assertSame(1, $arr[1]);
+
+ $arr [] = 3;
+ $this->assertSame(3, count($arr));
+ $this->assertSame(0, $arr[0]);
+ $this->assertSame(1, $arr[1]);
+ $this->assertSame(3, $arr[2]);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testRemoveMiddleFail()
+ {
+ $arr = new RepeatedField(GPBType::INT32);
+
+ $arr []= 0;
+ $arr []= 1;
+ $arr []= 2;
+ $this->assertSame(3, count($arr));
+
+ unset($arr[1]);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testRemoveEmptyFail()
+ {
+ $arr = new RepeatedField(GPBType::INT32);
+
+ unset($arr[0]);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testMessageOffsetFail()
+ {
+ $arr = new RepeatedField(GPBType::INT32);
+ $arr []= 0;
+ $arr [new TestMessage_Sub()]= 0;
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testStringOffsetFail()
+ {
+ $arr = new RepeatedField(GPBType::INT32);
+ $arr []= 0;
+ $arr ['abc']= 0;
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testSetNonExistedOffsetFail()
+ {
+ $arr = new RepeatedField(GPBType::INT32);
+ $arr [0]= 0;
+ }
+
+ #########################################################
+ # Test memory leak
+ #########################################################
+
+ public function testCycleLeak()
+ {
+ $arr = new RepeatedField(GPBType::MESSAGE, TestMessage::class);
+ $arr []= new TestMessage;
+ $arr[0]->SetRepeatedRecursive($arr);
+
+ // Clean up memory before test.
+ gc_collect_cycles();
+ $start = memory_get_usage();
+ unset($arr);
+
+ // Explicitly trigger garbage collection.
+ gc_collect_cycles();
+
+ $end = memory_get_usage();
+ $this->assertLessThan($start, $end);
+ }
+}
diff --git a/php/tests/autoload.php b/php/tests/autoload.php
deleted file mode 100644
index af88ba01..00000000
--- a/php/tests/autoload.php
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-
-require_once('test.pb.php');
-require_once('test_util.php');
diff --git a/php/tests/encode_decode_test.php b/php/tests/encode_decode_test.php
new file mode 100644
index 00000000..d07907c0
--- /dev/null
+++ b/php/tests/encode_decode_test.php
@@ -0,0 +1,136 @@
+<?php
+
+require_once('test.pb.php');
+require_once('test_base.php');
+require_once('test_util.php');
+
+use Google\Protobuf\RepeatedField;
+use Google\Protobuf\GPBType;
+use Foo\TestEnum;
+use Foo\TestMessage;
+use Foo\TestMessage_Sub;
+use Foo\TestPackedMessage;
+use Foo\TestUnpackedMessage;
+
+class EncodeDecodeTest extends TestBase
+{
+
+ public function testEncode()
+ {
+ $from = new TestMessage();
+ $this->expectEmptyFields($from);
+ $this->setFields($from);
+ $this->expectFields($from);
+
+ $data = $from->encode();
+ $this->assertSame(TestUtil::getGoldenTestMessage(), $data);
+ }
+
+ public function testDecode()
+ {
+ $to = new TestMessage();
+ $to->decode(TestUtil::getGoldenTestMessage());
+ $this->expectFields($to);
+ }
+
+ public function testEncodeDecode()
+ {
+ $from = new TestMessage();
+ $this->expectEmptyFields($from);
+ $this->setFields($from);
+ $this->expectFields($from);
+
+ $data = $from->encode();
+
+ $to = new TestMessage();
+ $to->decode($data);
+ $this->expectFields($to);
+ }
+
+ public function testEncodeDecodeEmpty()
+ {
+ $from = new TestMessage();
+ $this->expectEmptyFields($from);
+
+ $data = $from->encode();
+
+ $to = new TestMessage();
+ $to->decode($data);
+ $this->expectEmptyFields($to);
+ }
+
+ public function testEncodeDecodeOneof()
+ {
+ $m = new TestMessage();
+
+ $m->setOneofInt32(1);
+ $data = $m->encode();
+ $n = new TestMessage();
+ $n->decode($data);
+ $this->assertSame(1, $n->getOneofInt32());
+
+ $m->setOneofFloat(2.0);
+ $data = $m->encode();
+ $n = new TestMessage();
+ $n->decode($data);
+ $this->assertSame(2.0, $n->getOneofFloat());
+
+ $m->setOneofString('abc');
+ $data = $m->encode();
+ $n = new TestMessage();
+ $n->decode($data);
+ $this->assertSame('abc', $n->getOneofString());
+
+ $sub_m = new TestMessage_Sub();
+ $sub_m->setA(1);
+ $m->setOneofMessage($sub_m);
+ $data = $m->encode();
+ $n = new TestMessage();
+ $n->decode($data);
+ $this->assertSame(1, $n->getOneofMessage()->getA());
+ }
+
+ public function testPackedEncode()
+ {
+ $from = new TestPackedMessage();
+ TestUtil::setTestPackedMessage($from);
+ $this->assertSame(TestUtil::getGoldenTestPackedMessage(),
+ $from->encode());
+ }
+
+ public function testPackedDecodePacked()
+ {
+ $to = new TestPackedMessage();
+ $to->decode(TestUtil::getGoldenTestPackedMessage());
+ TestUtil::assertTestPackedMessage($to);
+ }
+
+ public function testPackedDecodeUnpacked()
+ {
+ $to = new TestPackedMessage();
+ $to->decode(TestUtil::getGoldenTestUnpackedMessage());
+ TestUtil::assertTestPackedMessage($to);
+ }
+
+ public function testUnpackedEncode()
+ {
+ $from = new TestUnpackedMessage();
+ TestUtil::setTestPackedMessage($from);
+ $this->assertSame(TestUtil::getGoldenTestUnpackedMessage(),
+ $from->encode());
+ }
+
+ public function testUnpackedDecodePacked()
+ {
+ $to = new TestUnpackedMessage();
+ $to->decode(TestUtil::getGoldenTestPackedMessage());
+ TestUtil::assertTestPackedMessage($to);
+ }
+
+ public function testUnpackedDecodeUnpacked()
+ {
+ $to = new TestUnpackedMessage();
+ $to->decode(TestUtil::getGoldenTestUnpackedMessage());
+ TestUtil::assertTestPackedMessage($to);
+ }
+}
diff --git a/php/tests/generated_class_test.php b/php/tests/generated_class_test.php
new file mode 100644
index 00000000..56466cae
--- /dev/null
+++ b/php/tests/generated_class_test.php
@@ -0,0 +1,557 @@
+<?php
+
+require_once('test.pb.php');
+require_once('test_util.php');
+
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBType;
+use Foo\TestEnum;
+use Foo\TestMessage;
+use Foo\TestMessage_Sub;
+
+class GeneratedClassTest extends PHPUnit_Framework_TestCase
+{
+
+ #########################################################
+ # Test field accessors.
+ #########################################################
+
+ public function testSetterGetter()
+ {
+ $m = new TestMessage();
+ $m->setOptionalInt32(1);
+ $this->assertSame(1, $m->getOptionalInt32());
+ }
+
+ #########################################################
+ # Test int32 field.
+ #########################################################
+
+ public function testInt32Field()
+ {
+ $m = new TestMessage();
+
+ // Set integer.
+ $m->setOptionalInt32(MAX_INT32);
+ $this->assertSame(MAX_INT32, $m->getOptionalInt32());
+ $m->setOptionalInt32(MIN_INT32);
+ $this->assertSame(MIN_INT32, $m->getOptionalInt32());
+
+ // Set float.
+ $m->setOptionalInt32(1.1);
+ $this->assertSame(1, $m->getOptionalInt32());
+ $m->setOptionalInt32(MAX_INT32_FLOAT);
+ $this->assertSame(MAX_INT32, $m->getOptionalInt32());
+ $m->setOptionalInt32(MIN_INT32_FLOAT);
+ $this->assertSame(MIN_INT32, $m->getOptionalInt32());
+
+ // Set string.
+ $m->setOptionalInt32('2');
+ $this->assertSame(2, $m->getOptionalInt32());
+ $m->setOptionalInt32('3.1');
+ $this->assertSame(3, $m->getOptionalInt32());
+ $m->setOptionalInt32(MAX_INT32_STRING);
+ $this->assertSame(MAX_INT32, $m->getOptionalInt32());
+ $m->setOptionalInt32(MIN_INT32_STRING);
+ $this->assertSame(MIN_INT32, $m->getOptionalInt32());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt32FieldInvalidTypeFail()
+ {
+ $m = new TestMessage();
+ $m->setOptionalInt32(new TestMessage());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt32FieldInvalidStringFail()
+ {
+ $m = new TestMessage();
+ $m->setOptionalInt32('abc');
+ }
+
+ #########################################################
+ # Test uint32 field.
+ #########################################################
+
+ public function testUint32Field()
+ {
+ $m = new TestMessage();
+
+ // Set integer.
+ $m->setOptionalUint32(MAX_UINT32);
+ $this->assertSame(-1, $m->getOptionalUint32());
+ $m->setOptionalUint32(-1);
+ $this->assertSame(-1, $m->getOptionalUint32());
+ $m->setOptionalUint32(MIN_UINT32);
+ $this->assertSame(MIN_INT32, $m->getOptionalUint32());
+
+ // Set float.
+ $m->setOptionalUint32(1.1);
+ $this->assertSame(1, $m->getOptionalUint32());
+ $m->setOptionalUint32(MAX_UINT32_FLOAT);
+ $this->assertSame(-1, $m->getOptionalUint32());
+ $m->setOptionalUint32(-1.0);
+ $this->assertSame(-1, $m->getOptionalUint32());
+ $m->setOptionalUint32(MIN_UINT32_FLOAT);
+ $this->assertSame(MIN_INT32, $m->getOptionalUint32());
+
+ // Set string.
+ $m->setOptionalUint32('2');
+ $this->assertSame(2, $m->getOptionalUint32());
+ $m->setOptionalUint32('3.1');
+ $this->assertSame(3, $m->getOptionalUint32());
+ $m->setOptionalUint32(MAX_UINT32_STRING);
+ $this->assertSame(-1, $m->getOptionalUint32());
+ $m->setOptionalUint32('-1.0');
+ $this->assertSame(-1, $m->getOptionalUint32());
+ $m->setOptionalUint32(MIN_UINT32_STRING);
+ $this->assertSame(MIN_INT32, $m->getOptionalUint32());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint32FieldInvalidTypeFail()
+ {
+ $m = new TestMessage();
+ $m->setOptionalUint32(new TestMessage());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint32FieldInvalidStringFail()
+ {
+ $m = new TestMessage();
+ $m->setOptionalUint32('abc');
+ }
+
+ #########################################################
+ # Test int64 field.
+ #########################################################
+
+ public function testInt64Field()
+ {
+ $m = new TestMessage();
+
+ // Set integer.
+ $m->setOptionalInt64(MAX_INT64);
+ $this->assertSame(MAX_INT64, $m->getOptionalInt64());
+ $m->setOptionalInt64(MIN_INT64);
+ $this->assertEquals(MIN_INT64, $m->getOptionalInt64());
+
+ // Set float.
+ $m->setOptionalInt64(1.1);
+ $this->assertSame(1, $m->getOptionalInt64());
+
+ // Set string.
+ $m->setOptionalInt64('2');
+ $this->assertSame(2, $m->getOptionalInt64());
+ $m->setOptionalInt64('3.1');
+ $this->assertSame(3, $m->getOptionalInt64());
+ $m->setOptionalInt64(MAX_INT64_STRING);
+ $this->assertSame(MAX_INT64, $m->getOptionalInt64());
+ $m->setOptionalInt64(MIN_INT64_STRING);
+ $this->assertEquals(MIN_INT64, $m->getOptionalInt64());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt64FieldInvalidTypeFail()
+ {
+ $m = new TestMessage();
+ $m->setOptionalInt64(new TestMessage());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt64FieldInvalidStringFail()
+ {
+ $m = new TestMessage();
+ $m->setOptionalInt64('abc');
+ }
+
+ #########################################################
+ # Test uint64 field.
+ #########################################################
+
+ public function testUint64Field()
+ {
+ $m = new TestMessage();
+
+ // Set integer.
+ $m->setOptionalUint64(MAX_UINT64);
+ $this->assertEquals(MAX_UINT64, $m->getOptionalUint64());
+
+ // Set float.
+ $m->setOptionalUint64(1.1);
+ $this->assertSame(1, $m->getOptionalUint64());
+
+ // Set string.
+ $m->setOptionalUint64('2');
+ $this->assertSame(2, $m->getOptionalUint64());
+ $m->setOptionalUint64('3.1');
+ $this->assertSame(3, $m->getOptionalUint64());
+ $m->setOptionalUint64(MAX_UINT64_STRING);
+ $this->assertEquals(MAX_UINT64, $m->getOptionalUint64());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint64FieldInvalidTypeFail()
+ {
+ $m = new TestMessage();
+ $m->setOptionalUint64(new TestMessage());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint64FieldInvalidStringFail()
+ {
+ $m = new TestMessage();
+ $m->setOptionalUint64('abc');
+ }
+
+ #########################################################
+ # Test enum field.
+ #########################################################
+
+ public function testEnumField()
+ {
+ $m = new TestMessage();
+
+ // Set enum.
+ $m->setOptionalEnum(TestEnum::ONE);
+ $this->assertEquals(TestEnum::ONE, $m->getOptionalEnum());
+
+ // Set integer.
+ $m->setOptionalEnum(1);
+ $this->assertEquals(TestEnum::ONE, $m->getOptionalEnum());
+
+ // Set float.
+ $m->setOptionalEnum(1.1);
+ $this->assertEquals(TestEnum::ONE, $m->getOptionalEnum());
+
+ // Set string.
+ $m->setOptionalEnum("1");
+ $this->assertEquals(TestEnum::ONE, $m->getOptionalEnum());
+ }
+
+ #########################################################
+ # Test float field.
+ #########################################################
+
+ public function testFloatField()
+ {
+ $m = new TestMessage();
+
+ // Set integer.
+ $m->setOptionalFloat(1);
+ $this->assertEquals(1.0, $m->getOptionalFloat(), '', MAX_FLOAT_DIFF);
+
+ // Set float.
+ $m->setOptionalFloat(1.1);
+ $this->assertEquals(1.1, $m->getOptionalFloat(), '', MAX_FLOAT_DIFF);
+
+ // Set string.
+ $m->setOptionalFloat('2');
+ $this->assertEquals(2.0, $m->getOptionalFloat(), '', MAX_FLOAT_DIFF);
+ $m->setOptionalFloat('3.1');
+ $this->assertEquals(3.1, $m->getOptionalFloat(), '', MAX_FLOAT_DIFF);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testFloatFieldInvalidTypeFail()
+ {
+ $m = new TestMessage();
+ $m->setOptionalFloat(new TestMessage());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testFloatFieldInvalidStringFail()
+ {
+ $m = new TestMessage();
+ $m->setOptionalFloat('abc');
+ }
+
+ #########################################################
+ # Test double field.
+ #########################################################
+
+ public function testDoubleField()
+ {
+ $m = new TestMessage();
+
+ // Set integer.
+ $m->setOptionalDouble(1);
+ $this->assertEquals(1.0, $m->getOptionalDouble(), '', MAX_FLOAT_DIFF);
+
+ // Set float.
+ $m->setOptionalDouble(1.1);
+ $this->assertEquals(1.1, $m->getOptionalDouble(), '', MAX_FLOAT_DIFF);
+
+ // Set string.
+ $m->setOptionalDouble('2');
+ $this->assertEquals(2.0, $m->getOptionalDouble(), '', MAX_FLOAT_DIFF);
+ $m->setOptionalDouble('3.1');
+ $this->assertEquals(3.1, $m->getOptionalDouble(), '', MAX_FLOAT_DIFF);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testDoubleFieldInvalidTypeFail()
+ {
+ $m = new TestMessage();
+ $m->setOptionalDouble(new TestMessage());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testDoubleFieldInvalidStringFail()
+ {
+ $m = new TestMessage();
+ $m->setOptionalDouble('abc');
+ }
+
+ #########################################################
+ # Test bool field.
+ #########################################################
+
+ public function testBoolField()
+ {
+ $m = new TestMessage();
+
+ // Set bool.
+ $m->setOptionalBool(true);
+ $this->assertSame(true, $m->getOptionalBool());
+
+ // Set integer.
+ $m->setOptionalBool(-1);
+ $this->assertSame(true, $m->getOptionalBool());
+
+ // Set float.
+ $m->setOptionalBool(1.1);
+ $this->assertSame(true, $m->getOptionalBool());
+
+ // Set string.
+ $m->setOptionalBool('');
+ $this->assertSame(false, $m->getOptionalBool());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testBoolFieldInvalidStringFail()
+ {
+ $m = new TestMessage();
+ $m->setOptionalBool(new TestMessage());
+ }
+
+ #########################################################
+ # Test string field.
+ #########################################################
+
+ public function testStringField()
+ {
+ $m = new TestMessage();
+
+ // Set string.
+ $m->setOptionalString('abc');
+ $this->assertSame('abc', $m->getOptionalString());
+
+ // Set integer.
+ $m->setOptionalString(1);
+ $this->assertSame('1', $m->getOptionalString());
+
+ // Set double.
+ $m->setOptionalString(1.1);
+ $this->assertSame('1.1', $m->getOptionalString());
+
+ // Set bool.
+ $m->setOptionalString(true);
+ $this->assertSame('1', $m->getOptionalString());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testStringFieldInvalidUTF8Fail()
+ {
+ $m = new TestMessage();
+ $hex = hex2bin("ff");
+ $m->setOptionalString($hex);
+ }
+
+ #########################################################
+ # Test bytes field.
+ #########################################################
+
+ public function testBytesField()
+ {
+ $m = new TestMessage();
+
+ // Set string.
+ $m->setOptionalBytes('abc');
+ $this->assertSame('abc', $m->getOptionalBytes());
+
+ // Set integer.
+ $m->setOptionalBytes(1);
+ $this->assertSame('1', $m->getOptionalBytes());
+
+ // Set double.
+ $m->setOptionalBytes(1.1);
+ $this->assertSame('1.1', $m->getOptionalBytes());
+
+ // Set bool.
+ $m->setOptionalBytes(true);
+ $this->assertSame('1', $m->getOptionalBytes());
+ }
+
+ public function testBytesFieldInvalidUTF8Success()
+ {
+ $m = new TestMessage();
+ $hex = hex2bin("ff");
+ $m->setOptionalBytes($hex);
+ }
+
+ #########################################################
+ # Test message field.
+ #########################################################
+
+ public function testMessageField()
+ {
+ $m = new TestMessage();
+
+ $sub_m = new TestMessage_Sub();
+ $sub_m->setA(1);
+ $m->setOptionalMessage($sub_m);
+ $this->assertSame(1, $m->getOptionalMessage()->getA());
+
+ $null = null;
+ $m->setOptionalMessage($null);
+ $this->assertNull($m->getOptionalMessage());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testMessageFieldWrongTypeFail()
+ {
+ $m = new TestMessage();
+ $a = 1;
+ $m->setOptionalMessage($a);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testMessageFieldWrongClassFail()
+ {
+ $m = new TestMessage();
+ $m->setOptionalMessage(new TestMessage());
+ }
+
+ #########################################################
+ # Test repeated field.
+ #########################################################
+
+ public function testRepeatedField()
+ {
+ $m = new TestMessage();
+
+ $repeated_int32 = new RepeatedField(GPBType::INT32);
+ $m->setRepeatedInt32($repeated_int32);
+ $this->assertSame($repeated_int32, $m->getRepeatedInt32());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testRepeatedFieldWrongTypeFail()
+ {
+ $m = new TestMessage();
+ $a = 1;
+ $m->setRepeatedInt32($a);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testRepeatedFieldWrongObjectFail()
+ {
+ $m = new TestMessage();
+ $m->setRepeatedInt32($m);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testRepeatedFieldWrongRepeatedTypeFail()
+ {
+ $m = new TestMessage();
+
+ $repeated_int32 = new RepeatedField(GPBType::UINT32);
+ $m->setRepeatedInt32($repeated_int32);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testRepeatedFieldWrongRepeatedMessageClassFail()
+ {
+ $m = new TestMessage();
+
+ $repeated_message = new RepeatedField(GPBType::MESSAGE,
+ TestMessage::class);
+ $m->setRepeatedMessage($repeated_message);
+ }
+
+ #########################################################
+ # Test oneof field.
+ #########################################################
+
+ public function testOneofField() {
+ $m = new TestMessage();
+
+ $m->setOneofInt32(1);
+ $this->assertSame(1, $m->getOneofInt32());
+ $this->assertSame(0.0, $m->getOneofFloat());
+ $this->assertSame('', $m->getOneofString());
+ $this->assertSame(NULL, $m->getOneofMessage());
+
+ $m->setOneofFloat(2.0);
+ $this->assertSame(0, $m->getOneofInt32());
+ $this->assertSame(2.0, $m->getOneofFloat());
+ $this->assertSame('', $m->getOneofString());
+ $this->assertSame(NULL, $m->getOneofMessage());
+
+ $m->setOneofString('abc');
+ $this->assertSame(0, $m->getOneofInt32());
+ $this->assertSame(0.0, $m->getOneofFloat());
+ $this->assertSame('abc', $m->getOneofString());
+ $this->assertSame(NULL, $m->getOneofMessage());
+
+ $sub_m = new TestMessage_Sub();
+ $sub_m->setA(1);
+ $m->setOneofMessage($sub_m);
+ $this->assertSame(0, $m->getOneofInt32());
+ $this->assertSame(0.0, $m->getOneofFloat());
+ $this->assertSame('', $m->getOneofString());
+ $this->assertSame(1, $m->getOneofMessage()->getA());
+ }
+}
diff --git a/php/tests/map_field_test.php b/php/tests/map_field_test.php
new file mode 100644
index 00000000..d79d0da3
--- /dev/null
+++ b/php/tests/map_field_test.php
@@ -0,0 +1,648 @@
+<?php
+
+require_once('test.pb.php');
+require_once('test_util.php');
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\MapField;
+use Foo\TestMessage;
+use Foo\TestMessage_Sub;
+
+class MapFieldTest extends PHPUnit_Framework_TestCase {
+
+ #########################################################
+ # Test int32 field.
+ #########################################################
+
+ public function testInt32() {
+ $arr = new MapField(GPBType::INT32, GPBType::INT32);
+
+ // Test integer argument.
+ $arr[MAX_INT32] = MAX_INT32;
+ $this->assertSame(MAX_INT32, $arr[MAX_INT32]);
+ $arr[MIN_INT32] = MIN_INT32;
+ $this->assertSame(MIN_INT32, $arr[MIN_INT32]);
+ $this->assertEquals(2, count($arr));
+ $this->assertTrue(isset($arr[MAX_INT32]));
+ $this->assertTrue(isset($arr[MIN_INT32]));
+ unset($arr[MAX_INT32]);
+ unset($arr[MIN_INT32]);
+ $this->assertEquals(0, count($arr));
+
+ // Test float argument.
+ $arr[1.9] = 1.9;
+ $arr[2.1] = 2.1;
+ $this->assertSame(1, $arr[1]);
+ $this->assertSame(2, $arr[2]);
+ $arr[MAX_INT32_FLOAT] = MAX_INT32_FLOAT;
+ $this->assertSame(MAX_INT32, $arr[MAX_INT32]);
+ $arr[MIN_INT32_FLOAT] = MIN_INT32_FLOAT;
+ $this->assertSame(MIN_INT32, $arr[MIN_INT32]);
+ $this->assertEquals(4, count($arr));
+ unset($arr[1.9]);
+ unset($arr[2.9]);
+ unset($arr[MAX_INT32_FLOAT]);
+ unset($arr[MIN_INT32_FLOAT]);
+ $this->assertEquals(0, count($arr));
+
+ // Test string argument.
+ $arr['2'] = '2';
+ $this->assertSame(2, $arr[2]);
+ $arr['3.1'] = '3.1';
+ $this->assertSame(3, $arr[3]);
+ $arr[MAX_INT32_STRING] = MAX_INT32_STRING;
+ $this->assertSame(MAX_INT32, $arr[MAX_INT32]);
+ $this->assertEquals(3, count($arr));
+ unset($arr['2']);
+ unset($arr['3.1']);
+ unset($arr[MAX_INT32_STRING]);
+ $this->assertEquals(0, count($arr));
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt32SetStringKeyFail()
+ {
+ $arr = new MapField(GPBType::INT32, GPBType::INT32);
+ $arr ['abc']= 0;
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt32SetStringValueFail()
+ {
+ $arr = new MapField(GPBType::INT32, GPBType::INT32);
+ $arr [0]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt32SetMessageKeyFail()
+ {
+ $arr = new MapField(GPBType::INT32, GPBType::INT32);
+ $arr [new TestMessage_Sub()]= 0;
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt32SetMessageValueFail()
+ {
+ $arr = new MapField(GPBType::INT32, GPBType::INT32);
+ $arr [0]= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test uint32 field.
+ #########################################################
+
+ public function testUint32() {
+ $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
+
+ // Test integer argument.
+ $arr[MAX_UINT32] = MAX_UINT32;
+ $this->assertSame(-1, $arr[-1]);
+ $this->assertEquals(1, count($arr));
+ unset($arr[MAX_UINT32]);
+ $this->assertEquals(0, count($arr));
+
+ $arr[-1] = -1;
+ $this->assertSame(-1, $arr[-1]);
+ $arr[MIN_UINT32] = MIN_UINT32;
+ $this->assertSame(MIN_UINT32, $arr[MIN_UINT32]);
+ $this->assertEquals(2, count($arr));
+ unset($arr[-1]);
+ unset($arr[MIN_UINT32]);
+ $this->assertEquals(0, count($arr));
+
+ // Test float argument.
+ $arr[MAX_UINT32_FLOAT] = MAX_UINT32_FLOAT;
+ $this->assertSame(-1, $arr[-1]);
+ $this->assertEquals(1, count($arr));
+ unset($arr[MAX_UINT32_FLOAT]);
+ $this->assertEquals(0, count($arr));
+
+ $arr[3.1] = 3.1;
+ $this->assertSame(3, $arr[3]);
+ $arr[-1.0] = -1.0;
+ $this->assertSame(-1, $arr[-1]);
+ $arr[MIN_UINT32_FLOAT] = MIN_UINT32_FLOAT;
+ $this->assertSame(MIN_UINT32, $arr[MIN_UINT32]);
+ $this->assertEquals(3, count($arr));
+ unset($arr[3.1]);
+ unset($arr[-1.0]);
+ unset($arr[MIN_UINT32_FLOAT]);
+ $this->assertEquals(0, count($arr));
+
+ // Test string argument.
+ $arr[MAX_UINT32_STRING] = MAX_UINT32_STRING;
+ $this->assertSame(-1, $arr[-1]);
+ $this->assertEquals(1, count($arr));
+ unset($arr[MAX_UINT32_STRING]);
+ $this->assertEquals(0, count($arr));
+
+ $arr['7'] = '7';
+ $this->assertSame(7, $arr[7]);
+ $arr['3.1'] = '3.1';
+ $this->assertSame(3, $arr[3]);
+ $arr['-1.0'] = '-1.0';
+ $this->assertSame(-1, $arr[-1]);
+ $arr[MIN_UINT32_STRING] = MIN_UINT32_STRING;
+ $this->assertSame(MIN_UINT32, $arr[MIN_UINT32]);
+ $this->assertEquals(4, count($arr));
+ unset($arr['7']);
+ unset($arr['3.1']);
+ unset($arr['-1.0']);
+ unset($arr[MIN_UINT32_STRING]);
+ $this->assertEquals(0, count($arr));
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint32SetStringKeyFail()
+ {
+ $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
+ $arr ['abc']= 0;
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint32SetStringValueFail()
+ {
+ $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
+ $arr [0]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint32SetMessageKeyFail()
+ {
+ $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
+ $arr [new TestMessage_Sub()]= 0;
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint32SetMessageValueFail()
+ {
+ $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
+ $arr [0]= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test int64 field.
+ #########################################################
+
+ public function testInt64() {
+ $arr = new MapField(GPBType::INT64, GPBType::INT64);
+
+ // Test integer argument.
+ $arr[MAX_INT64] = MAX_INT64;
+ $this->assertSame(MAX_INT64, $arr[MAX_INT64]);
+ $arr[MIN_INT64] = MIN_INT64;
+ $this->assertEquals(MIN_INT64, $arr[MIN_INT64]);
+ $this->assertEquals(2, count($arr));
+ unset($arr[MAX_INT64]);
+ unset($arr[MIN_INT64]);
+ $this->assertEquals(0, count($arr));
+
+ // Test float argument.
+ $arr[1.1] = 1.1;
+ $this->assertSame(1, $arr[1]);
+ $this->assertEquals(1, count($arr));
+ unset($arr[1.1]);
+ $this->assertEquals(0, count($arr));
+
+ // Test string argument.
+ $arr['2'] = '2';
+ $this->assertSame(2, $arr[2]);
+ $arr['3.1'] = '3.1';
+ $this->assertSame(3, $arr[3]);
+ $arr[MAX_INT64_STRING] = MAX_INT64_STRING;
+ $this->assertSame(MAX_INT64, $arr[MAX_INT64]);
+ $arr[MIN_INT64_STRING] = MIN_INT64_STRING;
+ $this->assertEquals(MIN_INT64, $arr[MIN_INT64]);
+ $this->assertEquals(4, count($arr));
+ unset($arr['2']);
+ unset($arr['3.1']);
+ unset($arr[MAX_INT64_STRING]);
+ unset($arr[MIN_INT64_STRING]);
+ $this->assertEquals(0, count($arr));
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt64SetStringKeyFail()
+ {
+ $arr = new MapField(GPBType::INT64, GPBType::INT64);
+ $arr ['abc']= 0;
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt64SetStringValueFail()
+ {
+ $arr = new MapField(GPBType::INT64, GPBType::INT64);
+ $arr [0]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt64SetMessageKeyFail()
+ {
+ $arr = new MapField(GPBType::INT64, GPBType::INT64);
+ $arr [new TestMessage_Sub()]= 0;
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInt64SetMessageValueFail()
+ {
+ $arr = new MapField(GPBType::INT64, GPBType::INT64);
+ $arr [0]= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test uint64 field.
+ #########################################################
+
+ public function testUint64() {
+ $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
+
+ // Test integer argument.
+ $arr[MAX_UINT64] = MAX_UINT64;
+ $this->assertEquals(MAX_UINT64, $arr[MAX_UINT64]);
+ $this->assertEquals(1, count($arr));
+ unset($arr[MAX_UINT64]);
+ $this->assertEquals(0, count($arr));
+
+ // Test float argument.
+ $arr[1.1] = 1.1;
+ $this->assertSame(1, $arr[1]);
+ $this->assertEquals(1, count($arr));
+ unset($arr[1.1]);
+ $this->assertEquals(0, count($arr));
+
+ // Test string argument.
+ $arr['2'] = '2';
+ $this->assertSame(2, $arr[2]);
+ $arr['3.1'] = '3.1';
+ $this->assertSame(3, $arr[3]);
+ $arr[MAX_UINT64_STRING] = MAX_UINT64_STRING;
+ $this->assertEquals(MAX_UINT64, $arr[MAX_UINT64]);
+ $this->assertEquals(3, count($arr));
+ unset($arr['2']);
+ unset($arr['3.1']);
+ unset($arr[MAX_UINT64_STRING]);
+ $this->assertEquals(0, count($arr));
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint64SetStringKeyFail()
+ {
+ $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
+ $arr ['abc']= 0;
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint64SetStringValueFail()
+ {
+ $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
+ $arr [0]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint64SetMessageKeyFail()
+ {
+ $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
+ $arr [new TestMessage_Sub()]= 0;
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testUint64SetMessageValueFail()
+ {
+ $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
+ $arr [0]= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test float field.
+ #########################################################
+
+ public function testFloat() {
+ $arr = new MapField(GPBType::INT32, GPBType::FLOAT);
+
+ // Test set.
+ $arr[0] = 1;
+ $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
+
+ $arr[1] = 1.1;
+ $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
+
+ $arr[2] = '2';
+ $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
+ $arr[3] = '3.1';
+ $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
+
+ $this->assertEquals(4, count($arr));
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testFloatSetStringValueFail()
+ {
+ $arr = new MapField(GPBType::INT64, GPBType::FLOAT);
+ $arr [0]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testFloatSetMessageValueFail()
+ {
+ $arr = new MapField(GPBType::INT64, GPBType::FLOAT);
+ $arr [0]= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test double field.
+ #########################################################
+
+ public function testDouble() {
+ $arr = new MapField(GPBType::INT32, GPBType::DOUBLE);
+
+ // Test set.
+ $arr[0] = 1;
+ $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
+
+ $arr[1] = 1.1;
+ $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
+
+ $arr[2] = '2';
+ $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
+ $arr[3] = '3.1';
+ $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
+
+ $this->assertEquals(4, count($arr));
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testDoubleSetStringValueFail()
+ {
+ $arr = new MapField(GPBType::INT64, GPBType::DOUBLE);
+ $arr [0]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testDoubleSetMessageValueFail()
+ {
+ $arr = new MapField(GPBType::INT64, GPBType::DOUBLE);
+ $arr [0]= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test bool field.
+ #########################################################
+
+ public function testBool() {
+ $arr = new MapField(GPBType::BOOL, GPBType::BOOL);
+
+ // Test boolean.
+ $arr[True] = True;
+ $this->assertSame(True, $arr[True]);
+ $this->assertEquals(1, count($arr));
+ unset($arr[True]);
+ $this->assertEquals(0, count($arr));
+
+ $arr[False] = False;
+ $this->assertSame(False, $arr[False]);
+ $this->assertEquals(1, count($arr));
+ unset($arr[False]);
+ $this->assertEquals(0, count($arr));
+
+ // Test integer.
+ $arr[-1] = -1;
+ $this->assertSame(True, $arr[True]);
+ $this->assertEquals(1, count($arr));
+ unset($arr[-1]);
+ $this->assertEquals(0, count($arr));
+
+ $arr[0] = 0;
+ $this->assertSame(False, $arr[False]);
+ $this->assertEquals(1, count($arr));
+ unset($arr[0]);
+ $this->assertEquals(0, count($arr));
+
+ // Test float.
+ $arr[1.1] = 1.1;
+ $this->assertSame(True, $arr[True]);
+ $this->assertEquals(1, count($arr));
+ unset($arr[1.1]);
+ $this->assertEquals(0, count($arr));
+
+ $arr[0.0] = 0.0;
+ $this->assertSame(False, $arr[False]);
+ $this->assertEquals(1, count($arr));
+ unset($arr[0.0]);
+ $this->assertEquals(0, count($arr));
+
+ // Test string.
+ $arr['a'] = 'a';
+ $this->assertSame(True, $arr[True]);
+ $this->assertEquals(1, count($arr));
+ unset($arr['a']);
+ $this->assertEquals(0, count($arr));
+
+ $arr[''] = '';
+ $this->assertSame(False, $arr[False]);
+ $this->assertEquals(1, count($arr));
+ unset($arr['']);
+ $this->assertEquals(0, count($arr));
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testBoolSetMessageKeyFail()
+ {
+ $arr = new MapField(GPBType::BOOL, GPBType::BOOL);
+ $arr [new TestMessage_Sub()]= true;
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testBoolSetMessageValueFail()
+ {
+ $arr = new MapField(GPBType::BOOL, GPBType::BOOL);
+ $arr [true]= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test string field.
+ #########################################################
+
+ public function testString() {
+ $arr = new MapField(GPBType::STRING, GPBType::STRING);
+
+ // Test set.
+ $arr['abc'] = 'abc';
+ $this->assertSame('abc', $arr['abc']);
+ $this->assertEquals(1, count($arr));
+ unset($arr['abc']);
+ $this->assertEquals(0, count($arr));
+
+ $arr[1] = 1;
+ $this->assertSame('1', $arr['1']);
+ $this->assertEquals(1, count($arr));
+ unset($arr[1]);
+ $this->assertEquals(0, count($arr));
+
+ $arr[1.1] = 1.1;
+ $this->assertSame('1.1', $arr['1.1']);
+ $this->assertEquals(1, count($arr));
+ unset($arr[1.1]);
+ $this->assertEquals(0, count($arr));
+
+ $arr[True] = True;
+ $this->assertSame('1', $arr['1']);
+ $this->assertEquals(1, count($arr));
+ unset($arr[True]);
+ $this->assertEquals(0, count($arr));
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testStringSetInvalidUTF8KeyFail()
+ {
+ $arr = new MapField(GPBType::STRING, GPBType::STRING);
+ $arr[hex2bin("ff")]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testStringSetInvalidUTF8ValueFail()
+ {
+ $arr = new MapField(GPBType::STRING, GPBType::STRING);
+ $arr ['abc']= hex2bin("ff");
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testStringSetMessageKeyFail()
+ {
+ $arr = new MapField(GPBType::STRING, GPBType::STRING);
+ $arr [new TestMessage_Sub()]= 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testStringSetMessageValueFail()
+ {
+ $arr = new MapField(GPBType::STRING, GPBType::STRING);
+ $arr ['abc']= new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test message field.
+ #########################################################
+
+ public function testMessage() {
+ $arr = new MapField(GPBType::INT32,
+ GPBType::MESSAGE, TestMessage_Sub::class);
+
+ // Test append.
+ $sub_m = new TestMessage_Sub();
+ $sub_m->setA(1);
+ $arr[0] = $sub_m;
+ $this->assertSame(1, $arr[0]->getA());
+
+ $null = NULL;
+ $arr[1] = $null;
+ $this->assertNull($arr[1]);
+
+ $this->assertEquals(2, count($arr));
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testMessageSetIntValueFail()
+ {
+ $arr =
+ new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
+ $arr[0] = 0;
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testMessageSetStringValueFail()
+ {
+ $arr =
+ new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
+ $arr[0] = 'abc';
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testMessageSetOtherMessageValueFail()
+ {
+ $arr =
+ new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
+ $arr[0] = new TestMessage_Sub();
+ }
+
+ #########################################################
+ # Test memory leak
+ #########################################################
+
+ // TODO(teboring): Add it back.
+ // public function testCycleLeak()
+ // {
+ // $arr = new MapField(GPBType::INT32,
+ // GPBType::MESSAGE, TestMessage::class);
+ // $arr [0]= new TestMessage;
+ // $arr[0]->SetMapRecursive($arr);
+
+ // // Clean up memory before test.
+ // gc_collect_cycles();
+ // $start = memory_get_usage();
+ // unset($arr);
+
+ // // Explicitly trigger garbage collection.
+ // gc_collect_cycles();
+
+ // $end = memory_get_usage();
+ // $this->assertLessThan($start, $end);
+ // }
+}
diff --git a/php/tests/memory_leak_test.php b/php/tests/memory_leak_test.php
new file mode 100644
index 00000000..ec54597b
--- /dev/null
+++ b/php/tests/memory_leak_test.php
@@ -0,0 +1,73 @@
+<?php
+
+# phpunit has memory leak by itself. Thus, it cannot be used to test memory leak.
+
+require_once('test.pb.php');
+require_once('test_util.php');
+
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBType;
+use Foo\TestMessage;
+use Foo\TestMessage_Sub;
+
+$from = new TestMessage();
+TestUtil::setTestMessage($from);
+TestUtil::assertTestMessage($from);
+
+$data = $from->encode();
+
+$to = new TestMessage();
+$to->decode($data);
+
+TestUtil::assertTestMessage($to);
+
+$from->setRecursive($from);
+
+$arr = new RepeatedField(GPBType::MESSAGE, TestMessage::class);
+$arr []= new TestMessage;
+$arr[0]->SetRepeatedRecursive($arr);
+
+// Test oneof fields.
+$m = new TestMessage();
+
+$m->setOneofInt32(1);
+assert(1 === $m->getOneofInt32());
+assert(0.0 === $m->getOneofFloat());
+assert('' === $m->getOneofString());
+assert(NULL === $m->getOneofMessage());
+$data = $m->encode();
+$n = new TestMessage();
+$n->decode($data);
+assert(1 === $n->getOneofInt32());
+
+$m->setOneofFloat(2.0);
+assert(0 === $m->getOneofInt32());
+assert(2.0 === $m->getOneofFloat());
+assert('' === $m->getOneofString());
+assert(NULL === $m->getOneofMessage());
+$data = $m->encode();
+$n = new TestMessage();
+$n->decode($data);
+assert(2.0 === $n->getOneofFloat());
+
+$m->setOneofString('abc');
+assert(0 === $m->getOneofInt32());
+assert(0.0 === $m->getOneofFloat());
+assert('abc' === $m->getOneofString());
+assert(NULL === $m->getOneofMessage());
+$data = $m->encode();
+$n = new TestMessage();
+$n->decode($data);
+assert('abc' === $n->getOneofString());
+
+$sub_m = new TestMessage_Sub();
+$sub_m->setA(1);
+$m->setOneofMessage($sub_m);
+assert(0 === $m->getOneofInt32());
+assert(0.0 === $m->getOneofFloat());
+assert('' === $m->getOneofString());
+assert(1 === $m->getOneofMessage()->getA());
+$data = $m->encode();
+$n = new TestMessage();
+$n->decode($data);
+assert(1 === $n->getOneofMessage()->getA());
diff --git a/php/tests/php_implementation_test.php b/php/tests/php_implementation_test.php
new file mode 100644
index 00000000..82941dd2
--- /dev/null
+++ b/php/tests/php_implementation_test.php
@@ -0,0 +1,443 @@
+<?php
+
+require_once('test.pb.php');
+require_once('test_base.php');
+require_once('test_util.php');
+
+use Foo\TestMessage;
+use Foo\TestMessage_Sub;
+use Foo\TestPackedMessage;
+use Google\Protobuf\Internal\InputStream;
+use Google\Protobuf\Internal\FileDescriptorSet;
+use Google\Protobuf\Internal\GPBUtil;
+use Google\Protobuf\Internal\Int64;
+use Google\Protobuf\Internal\Uint64;
+use Google\Protobuf\Internal\GPBLabel;
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\GPBWire;
+use Google\Protobuf\Internal\OutputStream;
+use Google\Protobuf\Internal\RepeatedField;
+
+class ImplementationTest extends TestBase
+{
+
+ public function testReadInt32()
+ {
+ $value = null;
+
+ // Positive number.
+ $input = new InputStream(hex2bin("01"));
+ GPBWire::readInt32($input, $value);
+ $this->assertSame(1, $value);
+
+ // Negative number.
+ $input = new InputStream(hex2bin("ffffffff0f"));
+ GPBWire::readInt32($input, $value);
+ $this->assertSame(-1, $value);
+
+ // Discard overflow bits.
+ $input = new InputStream(hex2bin("ffffffff7f"));
+ GPBWire::readInt32($input, $value);
+ $this->assertSame(-1, $value);
+ }
+
+ public function testReadUint32()
+ {
+ $value = null;
+
+ // Positive number.
+ $input = new InputStream(hex2bin("01"));
+ GPBWire::readUint32($input, $value);
+ $this->assertSame(1, $value);
+
+ // Max uint32.
+ $input = new InputStream(hex2bin("ffffffff0f"));
+ GPBWire::readUint32($input, $value);
+ $this->assertSame(-1, $value);
+
+ // Discard overflow bits.
+ $input = new InputStream(hex2bin("ffffffff7f"));
+ GPBWire::readUint32($input, $value);
+ $this->assertSame(-1, $value);
+ }
+
+ public function testReadInt64()
+ {
+ $value = null;
+
+ // Positive number.
+ $input = new InputStream(hex2bin("01"));
+ GPBWire::readInt64($input, $value);
+ $this->assertSame(1, $value->toInteger());
+
+ // Negative number.
+ $input = new InputStream(hex2bin("ffffffffffffffffff01"));
+ GPBWire::readInt64($input, $value);
+ $this->assertSame(-1, $value->toInteger());
+
+ // Discard overflow bits.
+ $input = new InputStream(hex2bin("ffffffffffffffffff0f"));
+ GPBWire::readInt64($input, $value);
+ $this->assertSame(-1, $value->toInteger());
+ }
+
+ public function testReadUint64()
+ {
+ $value = null;
+
+ // Positive number.
+ $input = new InputStream(hex2bin("01"));
+ GPBWire::readUint64($input, $value);
+ $this->assertSame(1, $value->toInteger());
+
+ // Negative number.
+ $input = new InputStream(hex2bin("FFFFFFFFFFFFFFFFFF01"));
+ GPBWire::readUint64($input, $value);
+ $this->assertSame(-1, $value->toInteger());
+
+ // Discard overflow bits.
+ $input = new InputStream(hex2bin("FFFFFFFFFFFFFFFFFF0F"));
+ GPBWire::readUint64($input, $value);
+ $this->assertSame(-1, $value->toInteger());
+ }
+
+ public function testReadSint32()
+ {
+ $value = null;
+
+ $input = new InputStream(hex2bin("00"));
+ GPBWire::readSint32($input, $value);
+ $this->assertSame(0, $value);
+
+ $input = new InputStream(hex2bin("01"));
+ GPBWire::readSint32($input, $value);
+ $this->assertSame(-1, $value);
+
+ $input = new InputStream(hex2bin("02"));
+ GPBWire::readSint32($input, $value);
+ $this->assertSame(1, $value);
+ }
+
+ public function testReadSint64()
+ {
+ $value = null;
+
+ $input = new InputStream(hex2bin("00"));
+ GPBWire::readSint64($input, $value);
+ $this->assertEquals(GPBUtil::Int64(0), $value);
+
+ $input = new InputStream(hex2bin("01"));
+ GPBWire::readSint64($input, $value);
+ $this->assertEquals(GPBUtil::Int64(-1), $value);
+
+ $input = new InputStream(hex2bin("02"));
+ GPBWire::readSint64($input, $value);
+ $this->assertEquals(GPBUtil::Int64(1), $value);
+ }
+
+ public function testReadFixed32()
+ {
+ $value = null;
+ $input = new InputStream(hex2bin("12345678"));
+ GPBWire::readFixed32($input, $value);
+ $this->assertSame(0x78563412, $value);
+ }
+
+ public function testReadFixed64()
+ {
+ $value = null;
+ $input = new InputStream(hex2bin("1234567812345678"));
+ GPBWire::readFixed64($input, $value);
+ $this->assertEquals(Uint64::newValue(0x78563412, 0x78563412), $value);
+ }
+
+ public function testReadSfixed32()
+ {
+ $value = null;
+ $input = new InputStream(hex2bin("12345678"));
+ GPBWire::readSfixed32($input, $value);
+ $this->assertSame(0x78563412, $value);
+ }
+
+ public function testReadFloat()
+ {
+ $value = null;
+ $input = new InputStream(hex2bin("0000803F"));
+ GPBWire::readFloat($input, $value);
+ $this->assertSame(1.0, $value);
+ }
+
+ public function testReadBool()
+ {
+ $value = null;
+
+ $input = new InputStream(hex2bin("00"));
+ GPBWire::readBool($input, $value);
+ $this->assertSame(false, $value);
+
+ $input = new InputStream(hex2bin("01"));
+ GPBWire::readBool($input, $value);
+ $this->assertSame(true, $value);
+ }
+
+ public function testReadDouble()
+ {
+ $value = null;
+ $input = new InputStream(hex2bin("000000000000F03F"));
+ GPBWire::readDouble($input, $value);
+ $this->assertSame(1.0, $value);
+ }
+
+ public function testReadSfixed64()
+ {
+ $value = null;
+ $input = new InputStream(hex2bin("1234567812345678"));
+ GPBWire::readSfixed64($input, $value);
+ $this->assertEquals(Int64::newValue(0x78563412, 0x78563412), $value);
+ }
+
+ public function testZigZagEncodeDecode()
+ {
+ $this->assertSame(0, GPBWire::zigZagEncode32(0));
+ $this->assertSame(1, GPBWire::zigZagEncode32(-1));
+ $this->assertSame(2, GPBWire::zigZagEncode32(1));
+ $this->assertSame(3, GPBWire::zigZagEncode32(-2));
+ $this->assertSame(0x7FFFFFFE, GPBWire::zigZagEncode32(0x3FFFFFFF));
+ $this->assertSame(0x7FFFFFFF, GPBWire::zigZagEncode32(0xC0000000));
+ $this->assertSame(-2, GPBWire::zigZagEncode32(0x7FFFFFFF));
+ $this->assertSame(-1, GPBWire::zigZagEncode32(0x80000000));
+
+ $this->assertSame(0, GPBWire::zigZagDecode32(0));
+ $this->assertSame(-1, GPBWire::zigZagDecode32(1));
+ $this->assertSame(1, GPBWire::zigZagDecode32(2));
+ $this->assertSame(-2, GPBWire::zigZagDecode32(3));
+ $this->assertSame(0x3FFFFFFF, GPBWire::zigZagDecode32(0x7FFFFFFE));
+ $this->assertSame(-1073741824, GPBWire::zigZagDecode32(0x7FFFFFFF));
+ $this->assertSame(0x7FFFFFFF, GPBWire::zigZagDecode32(0xFFFFFFFE));
+ $this->assertSame(-2147483648, GPBWire::zigZagDecode32(0xFFFFFFFF));
+
+ $this->assertEquals(GPBUtil::Uint64(0),
+ GPBWire::zigZagEncode64(GPBUtil::Int64(0)));
+ $this->assertEquals(GPBUtil::Uint64(1),
+ GPBWire::zigZagEncode64(GPBUtil::Int64(-1)));
+ $this->assertEquals(GPBUtil::Uint64(2),
+ GPBWire::zigZagEncode64(GPBUtil::Int64(1)));
+ $this->assertEquals(GPBUtil::Uint64(3),
+ GPBWire::zigZagEncode64(GPBUtil::Int64(-2)));
+ $this->assertEquals(
+ GPBUtil::Uint64(0x000000007FFFFFFE),
+ GPBWire::zigZagEncode64(GPBUtil::Int64(0x000000003FFFFFFF)));
+ $this->assertEquals(
+ GPBUtil::Uint64(0x000000007FFFFFFF),
+ GPBWire::zigZagEncode64(GPBUtil::Int64(0xFFFFFFFFC0000000)));
+ $this->assertEquals(
+ GPBUtil::Uint64(0x00000000FFFFFFFE),
+ GPBWire::zigZagEncode64(GPBUtil::Int64(0x000000007FFFFFFF)));
+ $this->assertEquals(
+ GPBUtil::Uint64(0x00000000FFFFFFFF),
+ GPBWire::zigZagEncode64(GPBUtil::Int64(0xFFFFFFFF80000000)));
+ $this->assertEquals(
+ Uint64::newValue(4294967295, 4294967294),
+ GPBWire::zigZagEncode64(GPBUtil::Int64(0x7FFFFFFFFFFFFFFF)));
+ $this->assertEquals(
+ Uint64::newValue(4294967295, 4294967295),
+ GPBWire::zigZagEncode64(GPBUtil::Int64(0x8000000000000000)));
+
+ $this->assertEquals(GPBUtil::Int64(0),
+ GPBWire::zigZagDecode64(GPBUtil::Uint64(0)));
+ $this->assertEquals(GPBUtil::Int64(-1),
+ GPBWire::zigZagDecode64(GPBUtil::Uint64(1)));
+ $this->assertEquals(GPBUtil::Int64(1),
+ GPBWire::zigZagDecode64(GPBUtil::Uint64(2)));
+ $this->assertEquals(GPBUtil::Int64(-2),
+ GPBWire::zigZagDecode64(GPBUtil::Uint64(3)));
+
+ // Round trip
+ $this->assertSame(0, GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(0)));
+ $this->assertSame(1, GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(1)));
+ $this->assertSame(-1, GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(-1)));
+ $this->assertSame(14927,
+ GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(14927)));
+ $this->assertSame(-3612,
+ GPBWire::zigZagDecode32(GPBWire::zigZagEncode32(-3612)));
+ }
+
+ public function testDecode()
+ {
+ $m = new TestMessage();
+ $m->decode(TestUtil::getGoldenTestMessage());
+ TestUtil::assertTestMessage($m);
+ }
+
+ public function testDescriptorDecode()
+ {
+ $file_desc_set = new FileDescriptorSet();
+ $file_desc_set->decode(hex2bin(
+ "0a3b0a12746573745f696e636c7564652e70726f746f120362617222180a" .
+ "0b54657374496e636c75646512090a0161180120012805620670726f746f33"));
+
+ $this->assertSame(1, sizeof($file_desc_set->getFile()));
+
+ $file_desc = $file_desc_set->getFile()[0];
+ $this->assertSame("test_include.proto", $file_desc->getName());
+ $this->assertSame("bar", $file_desc->getPackage());
+ $this->assertSame(0, sizeof($file_desc->getDependency()));
+ $this->assertSame(1, sizeof($file_desc->getMessageType()));
+ $this->assertSame(0, sizeof($file_desc->getEnumType()));
+ $this->assertSame("proto3", $file_desc->getSyntax());
+
+ $desc = $file_desc->getMessageType()[0];
+ $this->assertSame("TestInclude", $desc->getName());
+ $this->assertSame(1, sizeof($desc->getField()));
+ $this->assertSame(0, sizeof($desc->getNestedType()));
+ $this->assertSame(0, sizeof($desc->getEnumType()));
+ $this->assertSame(0, sizeof($desc->getOneofDecl()));
+
+ $field = $desc->getField()[0];
+ $this->assertSame("a", $field->getName());
+ $this->assertSame(1, $field->getNumber());
+ $this->assertSame(GPBLabel::OPTIONAL, $field->getLabel());
+ $this->assertSame(GPBType::INT32, $field->getType());
+ }
+
+ public function testReadVarint64()
+ {
+ $var = 0;
+
+ // Empty buffer.
+ $input = new InputStream(hex2bin(''));
+ $this->assertFalse($input->readVarint64($var));
+
+ // The largest varint is 10 bytes long.
+ $input = new InputStream(hex2bin('8080808080808080808001'));
+ $this->assertFalse($input->readVarint64($var));
+
+ // Corrupted varint.
+ $input = new InputStream(hex2bin('808080'));
+ $this->assertFalse($input->readVarint64($var));
+
+ // Normal case.
+ $input = new InputStream(hex2bin('808001'));
+ $this->assertTrue($input->readVarint64($var));
+ $this->assertSame(16384, $var->toInteger());
+ $this->assertFalse($input->readVarint64($var));
+
+ // Read two varint.
+ $input = new InputStream(hex2bin('808001808002'));
+ $this->assertTrue($input->readVarint64($var));
+ $this->assertSame(16384, $var->toInteger());
+ $this->assertTrue($input->readVarint64($var));
+ $this->assertSame(32768, $var->toInteger());
+ $this->assertFalse($input->readVarint64($var));
+ }
+
+ public function testReadVarint32()
+ {
+ $var = 0;
+
+ // Empty buffer.
+ $input = new InputStream(hex2bin(''));
+ $this->assertFalse($input->readVarint32($var));
+
+ // The largest varint is 10 bytes long.
+ $input = new InputStream(hex2bin('8080808080808080808001'));
+ $this->assertFalse($input->readVarint32($var));
+
+ // Corrupted varint.
+ $input = new InputStream(hex2bin('808080'));
+ $this->assertFalse($input->readVarint32($var));
+
+ // Normal case.
+ $input = new InputStream(hex2bin('808001'));
+ $this->assertTrue($input->readVarint32($var));
+ $this->assertSame(16384, $var);
+ $this->assertFalse($input->readVarint32($var));
+
+ // Read two varint.
+ $input = new InputStream(hex2bin('808001808002'));
+ $this->assertTrue($input->readVarint32($var));
+ $this->assertSame(16384, $var);
+ $this->assertTrue($input->readVarint32($var));
+ $this->assertSame(32768, $var);
+ $this->assertFalse($input->readVarint32($var));
+
+ // Read a 64-bit integer. High-order bits should be discarded.
+ $input = new InputStream(hex2bin('808081808001'));
+ $this->assertTrue($input->readVarint32($var));
+ $this->assertSame(16384, $var);
+ $this->assertFalse($input->readVarint32($var));
+ }
+
+ public function testReadTag()
+ {
+ $input = new InputStream(hex2bin('808001'));
+ $tag = $input->readTag();
+ $this->assertSame(16384, $tag);
+ $tag = $input->readTag();
+ $this->assertSame(0, $tag);
+ }
+
+ public function testPushPopLimit()
+ {
+ $input = new InputStream(hex2bin('808001'));
+ $old_limit = $input->pushLimit(0);
+ $tag = $input->readTag();
+ $this->assertSame(0, $tag);
+ $input->popLimit($old_limit);
+ $tag = $input->readTag();
+ $this->assertSame(16384, $tag);
+ }
+
+ public function testReadRaw()
+ {
+ $input = new InputStream(hex2bin('808001'));
+ $buffer = null;
+
+ $this->assertTrue($input->readRaw(3, $buffer));
+ $this->assertSame(hex2bin('808001'), $buffer);
+
+ $this->assertFalse($input->readRaw(1, $buffer));
+ }
+
+ public function testWriteVarint32()
+ {
+ $output = new OutputStream(3);
+ $output->writeVarint32(16384);
+ $this->assertSame(hex2bin('808001'), $output->getData());
+ }
+
+ public function testWriteVarint64()
+ {
+ $output = new OutputStream(10);
+ $output->writeVarint64(-43);
+ $this->assertSame(hex2bin('D5FFFFFFFFFFFFFFFF01'), $output->getData());
+ }
+
+ public function testWriteLittleEndian32()
+ {
+ $output = new OutputStream(4);
+ $output->writeLittleEndian32(46);
+ $this->assertSame(hex2bin('2E000000'), $output->getData());
+ }
+
+ public function testWriteLittleEndian64()
+ {
+ $output = new OutputStream(8);
+ $output->writeLittleEndian64(47);
+ $this->assertSame(hex2bin('2F00000000000000'), $output->getData());
+ }
+
+ public function testByteSize()
+ {
+ $m = new TestMessage();
+ TestUtil::setTestMessage($m);
+ $this->assertSame(447, $m->byteSize());
+ }
+
+ public function testPackedByteSize()
+ {
+ $m = new TestPackedMessage();
+ TestUtil::setTestPackedMessage($m);
+ $this->assertSame(156, $m->byteSize());
+ }
+}
diff --git a/php/tests/test.pb.php b/php/tests/test.pb.php
new file mode 100644
index 00000000..ed316b6e
--- /dev/null
+++ b/php/tests/test.pb.php
@@ -0,0 +1,1385 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: test.proto
+
+namespace Foo;
+
+require_once('test_include.pb.php');
+use Google\Protobuf\Internal\DescriptorPool;
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+class TestMessage extends \Google\Protobuf\Internal\Message
+{
+ private $optional_int32 = 0;
+ private $optional_int64 = 0;
+ private $optional_uint32 = 0;
+ private $optional_uint64 = 0;
+ private $optional_sint32 = 0;
+ private $optional_sint64 = 0;
+ private $optional_fixed32 = 0;
+ private $optional_fixed64 = 0;
+ private $optional_sfixed32 = 0;
+ private $optional_sfixed64 = 0;
+ private $optional_float = 0.0;
+ private $optional_double = 0.0;
+ private $optional_bool = false;
+ private $optional_string = '';
+ private $optional_bytes = '';
+ private $optional_enum = 0;
+ private $optional_message = null;
+ private $optional_included_message = null;
+ private $recursive = null;
+ private $repeated_int32;
+ private $repeated_int64;
+ private $repeated_uint32;
+ private $repeated_uint64;
+ private $repeated_sint32;
+ private $repeated_sint64;
+ private $repeated_fixed32;
+ private $repeated_fixed64;
+ private $repeated_sfixed32;
+ private $repeated_sfixed64;
+ private $repeated_float;
+ private $repeated_double;
+ private $repeated_bool;
+ private $repeated_string;
+ private $repeated_bytes;
+ private $repeated_enum;
+ private $repeated_message;
+ private $repeated_recursive;
+ private $map_int32_int32;
+ private $map_int64_int64;
+ private $map_uint32_uint32;
+ private $map_uint64_uint64;
+ private $map_sint32_sint32;
+ private $map_sint64_sint64;
+ private $map_fixed32_fixed32;
+ private $map_fixed64_fixed64;
+ private $map_sfixed32_sfixed32;
+ private $map_sfixed64_sfixed64;
+ private $map_int32_float;
+ private $map_int32_double;
+ private $map_bool_bool;
+ private $map_string_string;
+ private $map_int32_bytes;
+ private $map_int32_enum;
+ private $map_int32_message;
+ private $map_recursive;
+ protected $my_oneof;
+
+ public function getOptionalInt32()
+ {
+ return $this->optional_int32;
+ }
+
+ public function setOptionalInt32($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->optional_int32 = $var;
+ }
+
+ public function getOptionalInt64()
+ {
+ return $this->optional_int64;
+ }
+
+ public function setOptionalInt64($var)
+ {
+ GPBUtil::checkInt64($var);
+ $this->optional_int64 = $var;
+ }
+
+ public function getOptionalUint32()
+ {
+ return $this->optional_uint32;
+ }
+
+ public function setOptionalUint32($var)
+ {
+ GPBUtil::checkUint32($var);
+ $this->optional_uint32 = $var;
+ }
+
+ public function getOptionalUint64()
+ {
+ return $this->optional_uint64;
+ }
+
+ public function setOptionalUint64($var)
+ {
+ GPBUtil::checkUint64($var);
+ $this->optional_uint64 = $var;
+ }
+
+ public function getOptionalSint32()
+ {
+ return $this->optional_sint32;
+ }
+
+ public function setOptionalSint32($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->optional_sint32 = $var;
+ }
+
+ public function getOptionalSint64()
+ {
+ return $this->optional_sint64;
+ }
+
+ public function setOptionalSint64($var)
+ {
+ GPBUtil::checkInt64($var);
+ $this->optional_sint64 = $var;
+ }
+
+ public function getOptionalFixed32()
+ {
+ return $this->optional_fixed32;
+ }
+
+ public function setOptionalFixed32($var)
+ {
+ GPBUtil::checkUint32($var);
+ $this->optional_fixed32 = $var;
+ }
+
+ public function getOptionalFixed64()
+ {
+ return $this->optional_fixed64;
+ }
+
+ public function setOptionalFixed64($var)
+ {
+ GPBUtil::checkUint64($var);
+ $this->optional_fixed64 = $var;
+ }
+
+ public function getOptionalSfixed32()
+ {
+ return $this->optional_sfixed32;
+ }
+
+ public function setOptionalSfixed32($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->optional_sfixed32 = $var;
+ }
+
+ public function getOptionalSfixed64()
+ {
+ return $this->optional_sfixed64;
+ }
+
+ public function setOptionalSfixed64($var)
+ {
+ GPBUtil::checkInt64($var);
+ $this->optional_sfixed64 = $var;
+ }
+
+ public function getOptionalFloat()
+ {
+ return $this->optional_float;
+ }
+
+ public function setOptionalFloat($var)
+ {
+ GPBUtil::checkFloat($var);
+ $this->optional_float = $var;
+ }
+
+ public function getOptionalDouble()
+ {
+ return $this->optional_double;
+ }
+
+ public function setOptionalDouble($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->optional_double = $var;
+ }
+
+ public function getOptionalBool()
+ {
+ return $this->optional_bool;
+ }
+
+ public function setOptionalBool($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->optional_bool = $var;
+ }
+
+ public function getOptionalString()
+ {
+ return $this->optional_string;
+ }
+
+ public function setOptionalString($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->optional_string = $var;
+ }
+
+ public function getOptionalBytes()
+ {
+ return $this->optional_bytes;
+ }
+
+ public function setOptionalBytes($var)
+ {
+ GPBUtil::checkString($var, False);
+ $this->optional_bytes = $var;
+ }
+
+ public function getOptionalEnum()
+ {
+ return $this->optional_enum;
+ }
+
+ public function setOptionalEnum($var)
+ {
+ GPBUtil::checkEnum($var, \Foo\TestEnum::class);
+ $this->optional_enum = $var;
+ }
+
+ public function getOptionalMessage()
+ {
+ return $this->optional_message;
+ }
+
+ public function setOptionalMessage(&$var)
+ {
+ GPBUtil::checkMessage($var, \Foo\TestMessage_Sub::class);
+ $this->optional_message = $var;
+ }
+
+ public function getOptionalIncludedMessage()
+ {
+ return $this->optional_included_message;
+ }
+
+ public function setOptionalIncludedMessage(&$var)
+ {
+ GPBUtil::checkMessage($var, \Bar\TestInclude::class);
+ $this->optional_included_message = $var;
+ }
+
+ public function getRecursive()
+ {
+ return $this->recursive;
+ }
+
+ public function setRecursive(&$var)
+ {
+ GPBUtil::checkMessage($var, \Foo\TestMessage::class);
+ $this->recursive = $var;
+ }
+
+ public function getRepeatedInt32()
+ {
+ return $this->repeated_int32;
+ }
+
+ public function setRepeatedInt32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::INT32);
+ $this->repeated_int32 = $var;
+ }
+
+ public function getRepeatedInt64()
+ {
+ return $this->repeated_int64;
+ }
+
+ public function setRepeatedInt64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::INT64);
+ $this->repeated_int64 = $var;
+ }
+
+ public function getRepeatedUint32()
+ {
+ return $this->repeated_uint32;
+ }
+
+ public function setRepeatedUint32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::UINT32);
+ $this->repeated_uint32 = $var;
+ }
+
+ public function getRepeatedUint64()
+ {
+ return $this->repeated_uint64;
+ }
+
+ public function setRepeatedUint64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::UINT64);
+ $this->repeated_uint64 = $var;
+ }
+
+ public function getRepeatedSint32()
+ {
+ return $this->repeated_sint32;
+ }
+
+ public function setRepeatedSint32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::SINT32);
+ $this->repeated_sint32 = $var;
+ }
+
+ public function getRepeatedSint64()
+ {
+ return $this->repeated_sint64;
+ }
+
+ public function setRepeatedSint64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::SINT64);
+ $this->repeated_sint64 = $var;
+ }
+
+ public function getRepeatedFixed32()
+ {
+ return $this->repeated_fixed32;
+ }
+
+ public function setRepeatedFixed32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::FIXED32);
+ $this->repeated_fixed32 = $var;
+ }
+
+ public function getRepeatedFixed64()
+ {
+ return $this->repeated_fixed64;
+ }
+
+ public function setRepeatedFixed64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::FIXED64);
+ $this->repeated_fixed64 = $var;
+ }
+
+ public function getRepeatedSfixed32()
+ {
+ return $this->repeated_sfixed32;
+ }
+
+ public function setRepeatedSfixed32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::SFIXED32);
+ $this->repeated_sfixed32 = $var;
+ }
+
+ public function getRepeatedSfixed64()
+ {
+ return $this->repeated_sfixed64;
+ }
+
+ public function setRepeatedSfixed64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::SFIXED64);
+ $this->repeated_sfixed64 = $var;
+ }
+
+ public function getRepeatedFloat()
+ {
+ return $this->repeated_float;
+ }
+
+ public function setRepeatedFloat(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::FLOAT);
+ $this->repeated_float = $var;
+ }
+
+ public function getRepeatedDouble()
+ {
+ return $this->repeated_double;
+ }
+
+ public function setRepeatedDouble(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::DOUBLE);
+ $this->repeated_double = $var;
+ }
+
+ public function getRepeatedBool()
+ {
+ return $this->repeated_bool;
+ }
+
+ public function setRepeatedBool(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::BOOL);
+ $this->repeated_bool = $var;
+ }
+
+ public function getRepeatedString()
+ {
+ return $this->repeated_string;
+ }
+
+ public function setRepeatedString(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::STRING);
+ $this->repeated_string = $var;
+ }
+
+ public function getRepeatedBytes()
+ {
+ return $this->repeated_bytes;
+ }
+
+ public function setRepeatedBytes(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::BYTES);
+ $this->repeated_bytes = $var;
+ }
+
+ public function getRepeatedEnum()
+ {
+ return $this->repeated_enum;
+ }
+
+ public function setRepeatedEnum(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::ENUM, Foo\TestEnum::class);
+ $this->repeated_enum = $var;
+ }
+
+ public function getRepeatedMessage()
+ {
+ return $this->repeated_message;
+ }
+
+ public function setRepeatedMessage(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Foo\TestMessage_Sub::class);
+ $this->repeated_message = $var;
+ }
+
+ public function getRepeatedRecursive()
+ {
+ return $this->repeated_recursive;
+ }
+
+ public function setRepeatedRecursive(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::MESSAGE, \Foo\TestMessage::class);
+ $this->repeated_recursive = $var;
+ }
+
+ public function getOneofInt32()
+ {
+ return $this->readOneof(51);
+ }
+
+ public function setOneofInt32($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->writeOneof(51, $var);
+ }
+
+ public function getOneofInt64()
+ {
+ return $this->readOneof(52);
+ }
+
+ public function setOneofInt64($var)
+ {
+ GPBUtil::checkInt64($var);
+ $this->writeOneof(52, $var);
+ }
+
+ public function getOneofUint32()
+ {
+ return $this->readOneof(53);
+ }
+
+ public function setOneofUint32($var)
+ {
+ GPBUtil::checkUint32($var);
+ $this->writeOneof(53, $var);
+ }
+
+ public function getOneofUint64()
+ {
+ return $this->readOneof(54);
+ }
+
+ public function setOneofUint64($var)
+ {
+ GPBUtil::checkUint64($var);
+ $this->writeOneof(54, $var);
+ }
+
+ public function getOneofSint32()
+ {
+ return $this->readOneof(55);
+ }
+
+ public function setOneofSint32($var)
+ {
+ GPBUtil::checkUint32($var);
+ $this->writeOneof(55, $var);
+ }
+
+ public function getOneofSint64()
+ {
+ return $this->readOneof(56);
+ }
+
+ public function setOneofSint64($var)
+ {
+ GPBUtil::checkUint64($var);
+ $this->writeOneof(56, $var);
+ }
+
+ public function getOneofFixed32()
+ {
+ return $this->readOneof(57);
+ }
+
+ public function setOneofFixed32($var)
+ {
+ GPBUtil::checkUint32($var);
+ $this->writeOneof(57, $var);
+ }
+
+ public function getOneofFixed64()
+ {
+ return $this->readOneof(58);
+ }
+
+ public function setOneofFixed64($var)
+ {
+ GPBUtil::checkUint64($var);
+ $this->writeOneof(58, $var);
+ }
+
+ public function getOneofSfixed32()
+ {
+ return $this->readOneof(59);
+ }
+
+ public function setOneofSfixed32($var)
+ {
+ GPBUtil::checkUint32($var);
+ $this->writeOneof(59, $var);
+ }
+
+ public function getOneofSfixed64()
+ {
+ return $this->readOneof(60);
+ }
+
+ public function setOneofSfixed64($var)
+ {
+ GPBUtil::checkUint64($var);
+ $this->writeOneof(60, $var);
+ }
+
+ public function getOneofDouble()
+ {
+ return $this->readOneof(61);
+ }
+
+ public function setOneofDouble($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->writeOneof(61, $var);
+ }
+
+ public function getOneofFloat()
+ {
+ return $this->readOneof(62);
+ }
+
+ public function setOneofFloat($var)
+ {
+ GPBUtil::checkFloat($var);
+ $this->writeOneof(62, $var);
+ }
+
+ public function getOneofBool()
+ {
+ return $this->readOneof(63);
+ }
+
+ public function setOneofBool($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->writeOneof(63, $var);
+ }
+
+ public function getOneofString()
+ {
+ return $this->readOneof(64);
+ }
+
+ public function setOneofString($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->writeOneof(64, $var);
+ }
+
+ public function getOneofBytes()
+ {
+ return $this->readOneof(65);
+ }
+
+ public function setOneofBytes($var)
+ {
+ GPBUtil::checkString($var, False);
+ $this->writeOneof(65, $var);
+ }
+
+ public function getOneofEnum()
+ {
+ return $this->readOneof(66);
+ }
+
+ public function setOneofEnum($var)
+ {
+ GPBUtil::checkEnum($var, \Foo\TestEnum::class);
+ $this->writeOneof(66, $var);
+ }
+
+ public function getOneofMessage()
+ {
+ return $this->readOneof(67);
+ }
+
+ public function setOneofMessage(&$var)
+ {
+ GPBUtil::checkMessage($var, \Foo\TestMessage_Sub::class);
+ $this->writeOneof(67, $var);
+ }
+
+ public function getMapInt32Int32()
+ {
+ return $this->map_int32_int32;
+ }
+
+ public function setMapInt32Int32(&$var)
+ {
+ $this->map_int32_int32 = $var;
+ }
+
+ public function getMapInt64Int64()
+ {
+ return $this->map_int64_int64;
+ }
+
+ public function setMapInt64Int64(&$var)
+ {
+ $this->map_int64_int64 = $var;
+ }
+
+ public function getMapUint32Uint32()
+ {
+ return $this->map_uint32_uint32;
+ }
+
+ public function setMapUint32Uint32(&$var)
+ {
+ $this->map_uint32_uint32 = $var;
+ }
+
+ public function getMapUint64Uint64()
+ {
+ return $this->map_uint64_uint64;
+ }
+
+ public function setMapUint64Uint64(&$var)
+ {
+ $this->map_uint64_uint64 = $var;
+ }
+
+ public function getMapSint32Sint32()
+ {
+ return $this->map_sint32_sint32;
+ }
+
+ public function setMapSint32Sint32(&$var)
+ {
+ $this->map_sint32_sint32 = $var;
+ }
+
+ public function getMapSint64Sint64()
+ {
+ return $this->map_sint64_sint64;
+ }
+
+ public function setMapSint64Sint64(&$var)
+ {
+ $this->map_sint64_sint64 = $var;
+ }
+
+ public function getMapFixed32Fixed32()
+ {
+ return $this->map_fixed32_fixed32;
+ }
+
+ public function setMapFixed32Fixed32(&$var)
+ {
+ $this->map_fixed32_fixed32 = $var;
+ }
+
+ public function getMapFixed64Fixed64()
+ {
+ return $this->map_fixed64_fixed64;
+ }
+
+ public function setMapFixed64Fixed64(&$var)
+ {
+ $this->map_fixed64_fixed64 = $var;
+ }
+
+ public function getMapSfixed32Sfixed32()
+ {
+ return $this->map_sfixed32_sfixed32;
+ }
+
+ public function setMapSfixed32Sfixed32(&$var)
+ {
+ $this->map_sfixed32_sfixed32 = $var;
+ }
+
+ public function getMapSfixed64Sfixed64()
+ {
+ return $this->map_sfixed64_sfixed64;
+ }
+
+ public function setMapSfixed64Sfixed64(&$var)
+ {
+ $this->map_sfixed64_sfixed64 = $var;
+ }
+
+ public function getMapInt32Float()
+ {
+ return $this->map_int32_float;
+ }
+
+ public function setMapInt32Float(&$var)
+ {
+ $this->map_int32_float = $var;
+ }
+
+ public function getMapInt32Double()
+ {
+ return $this->map_int32_double;
+ }
+
+ public function setMapInt32Double(&$var)
+ {
+ $this->map_int32_double = $var;
+ }
+
+ public function getMapBoolBool()
+ {
+ return $this->map_bool_bool;
+ }
+
+ public function setMapBoolBool(&$var)
+ {
+ $this->map_bool_bool = $var;
+ }
+
+ public function getMapStringString()
+ {
+ return $this->map_string_string;
+ }
+
+ public function setMapStringString(&$var)
+ {
+ $this->map_string_string = $var;
+ }
+
+ public function getMapInt32Bytes()
+ {
+ return $this->map_int32_bytes;
+ }
+
+ public function setMapInt32Bytes(&$var)
+ {
+ $this->map_int32_bytes = $var;
+ }
+
+ public function getMapInt32Enum()
+ {
+ return $this->map_int32_enum;
+ }
+
+ public function setMapInt32Enum(&$var)
+ {
+ $this->map_int32_enum = $var;
+ }
+
+ public function getMapInt32Message()
+ {
+ return $this->map_int32_message;
+ }
+
+ public function setMapInt32Message(&$var)
+ {
+ $this->map_int32_message = $var;
+ }
+
+ public function getMapRecursive()
+ {
+ return $this->map_recursive;
+ }
+
+ public function setMapRecursive(&$var)
+ {
+ $this->map_recursive = $var;
+ }
+
+ public function getMyOneof()
+ {
+ return $this->my_oneof;
+ }
+
+}
+
+class TestMessage_Sub extends \Google\Protobuf\Internal\Message
+{
+ private $a = 0;
+
+ public function getA()
+ {
+ return $this->a;
+ }
+
+ public function setA($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->a = $var;
+ }
+
+}
+
+class TestPackedMessage extends \Google\Protobuf\Internal\Message
+{
+ private $repeated_int32;
+ private $repeated_int64;
+ private $repeated_uint32;
+ private $repeated_uint64;
+ private $repeated_sint32;
+ private $repeated_sint64;
+ private $repeated_fixed32;
+ private $repeated_fixed64;
+ private $repeated_sfixed32;
+ private $repeated_sfixed64;
+ private $repeated_float;
+ private $repeated_double;
+ private $repeated_bool;
+ private $repeated_enum;
+
+ public function getRepeatedInt32()
+ {
+ return $this->repeated_int32;
+ }
+
+ public function setRepeatedInt32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::INT32);
+ $this->repeated_int32 = $var;
+ }
+
+ public function getRepeatedInt64()
+ {
+ return $this->repeated_int64;
+ }
+
+ public function setRepeatedInt64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::INT64);
+ $this->repeated_int64 = $var;
+ }
+
+ public function getRepeatedUint32()
+ {
+ return $this->repeated_uint32;
+ }
+
+ public function setRepeatedUint32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::UINT32);
+ $this->repeated_uint32 = $var;
+ }
+
+ public function getRepeatedUint64()
+ {
+ return $this->repeated_uint64;
+ }
+
+ public function setRepeatedUint64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::UINT64);
+ $this->repeated_uint64 = $var;
+ }
+
+ public function getRepeatedSint32()
+ {
+ return $this->repeated_sint32;
+ }
+
+ public function setRepeatedSint32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::SINT32);
+ $this->repeated_sint32 = $var;
+ }
+
+ public function getRepeatedSint64()
+ {
+ return $this->repeated_sint64;
+ }
+
+ public function setRepeatedSint64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::SINT64);
+ $this->repeated_sint64 = $var;
+ }
+
+ public function getRepeatedFixed32()
+ {
+ return $this->repeated_fixed32;
+ }
+
+ public function setRepeatedFixed32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::FIXED32);
+ $this->repeated_fixed32 = $var;
+ }
+
+ public function getRepeatedFixed64()
+ {
+ return $this->repeated_fixed64;
+ }
+
+ public function setRepeatedFixed64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::FIXED64);
+ $this->repeated_fixed64 = $var;
+ }
+
+ public function getRepeatedSfixed32()
+ {
+ return $this->repeated_sfixed32;
+ }
+
+ public function setRepeatedSfixed32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::SFIXED32);
+ $this->repeated_sfixed32 = $var;
+ }
+
+ public function getRepeatedSfixed64()
+ {
+ return $this->repeated_sfixed64;
+ }
+
+ public function setRepeatedSfixed64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::SFIXED64);
+ $this->repeated_sfixed64 = $var;
+ }
+
+ public function getRepeatedFloat()
+ {
+ return $this->repeated_float;
+ }
+
+ public function setRepeatedFloat(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::FLOAT);
+ $this->repeated_float = $var;
+ }
+
+ public function getRepeatedDouble()
+ {
+ return $this->repeated_double;
+ }
+
+ public function setRepeatedDouble(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::DOUBLE);
+ $this->repeated_double = $var;
+ }
+
+ public function getRepeatedBool()
+ {
+ return $this->repeated_bool;
+ }
+
+ public function setRepeatedBool(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::BOOL);
+ $this->repeated_bool = $var;
+ }
+
+ public function getRepeatedEnum()
+ {
+ return $this->repeated_enum;
+ }
+
+ public function setRepeatedEnum(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::ENUM, Foo\TestEnum::class);
+ $this->repeated_enum = $var;
+ }
+
+}
+
+class TestUnpackedMessage extends \Google\Protobuf\Internal\Message
+{
+ private $repeated_int32;
+ private $repeated_int64;
+ private $repeated_uint32;
+ private $repeated_uint64;
+ private $repeated_sint32;
+ private $repeated_sint64;
+ private $repeated_fixed32;
+ private $repeated_fixed64;
+ private $repeated_sfixed32;
+ private $repeated_sfixed64;
+ private $repeated_float;
+ private $repeated_double;
+ private $repeated_bool;
+ private $repeated_enum;
+
+ public function getRepeatedInt32()
+ {
+ return $this->repeated_int32;
+ }
+
+ public function setRepeatedInt32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::INT32);
+ $this->repeated_int32 = $var;
+ }
+
+ public function getRepeatedInt64()
+ {
+ return $this->repeated_int64;
+ }
+
+ public function setRepeatedInt64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::INT64);
+ $this->repeated_int64 = $var;
+ }
+
+ public function getRepeatedUint32()
+ {
+ return $this->repeated_uint32;
+ }
+
+ public function setRepeatedUint32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::UINT32);
+ $this->repeated_uint32 = $var;
+ }
+
+ public function getRepeatedUint64()
+ {
+ return $this->repeated_uint64;
+ }
+
+ public function setRepeatedUint64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::UINT64);
+ $this->repeated_uint64 = $var;
+ }
+
+ public function getRepeatedSint32()
+ {
+ return $this->repeated_sint32;
+ }
+
+ public function setRepeatedSint32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::SINT32);
+ $this->repeated_sint32 = $var;
+ }
+
+ public function getRepeatedSint64()
+ {
+ return $this->repeated_sint64;
+ }
+
+ public function setRepeatedSint64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::SINT64);
+ $this->repeated_sint64 = $var;
+ }
+
+ public function getRepeatedFixed32()
+ {
+ return $this->repeated_fixed32;
+ }
+
+ public function setRepeatedFixed32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::FIXED32);
+ $this->repeated_fixed32 = $var;
+ }
+
+ public function getRepeatedFixed64()
+ {
+ return $this->repeated_fixed64;
+ }
+
+ public function setRepeatedFixed64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::FIXED64);
+ $this->repeated_fixed64 = $var;
+ }
+
+ public function getRepeatedSfixed32()
+ {
+ return $this->repeated_sfixed32;
+ }
+
+ public function setRepeatedSfixed32(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::SFIXED32);
+ $this->repeated_sfixed32 = $var;
+ }
+
+ public function getRepeatedSfixed64()
+ {
+ return $this->repeated_sfixed64;
+ }
+
+ public function setRepeatedSfixed64(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::SFIXED64);
+ $this->repeated_sfixed64 = $var;
+ }
+
+ public function getRepeatedFloat()
+ {
+ return $this->repeated_float;
+ }
+
+ public function setRepeatedFloat(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::FLOAT);
+ $this->repeated_float = $var;
+ }
+
+ public function getRepeatedDouble()
+ {
+ return $this->repeated_double;
+ }
+
+ public function setRepeatedDouble(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::DOUBLE);
+ $this->repeated_double = $var;
+ }
+
+ public function getRepeatedBool()
+ {
+ return $this->repeated_bool;
+ }
+
+ public function setRepeatedBool(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::BOOL);
+ $this->repeated_bool = $var;
+ }
+
+ public function getRepeatedEnum()
+ {
+ return $this->repeated_enum;
+ }
+
+ public function setRepeatedEnum(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, GPBType::ENUM, Foo\TestEnum::class);
+ $this->repeated_enum = $var;
+ }
+
+}
+
+class TestEnum
+{
+ const ZERO = 0;
+ const ONE = 1;
+}
+
+$pool = DescriptorPool::getGeneratedPool();
+
+$pool->internalAddGeneratedFile(hex2bin(
+ "0a83250a0a746573742e70726f746f1203666f6f1a12746573745f696e63" .
+ "6c7564652e70726f746f22be1d0a0b546573744d65737361676512160a0e" .
+ "6f7074696f6e616c5f696e74333218012001280512160a0e6f7074696f6e" .
+ "616c5f696e74363418022001280312170a0f6f7074696f6e616c5f75696e" .
+ "74333218032001280d12170a0f6f7074696f6e616c5f75696e7436341804" .
+ "2001280412170a0f6f7074696f6e616c5f73696e74333218052001281112" .
+ "170a0f6f7074696f6e616c5f73696e74363418062001281212180a106f70" .
+ "74696f6e616c5f6669786564333218072001280712180a106f7074696f6e" .
+ "616c5f6669786564363418082001280612190a116f7074696f6e616c5f73" .
+ "6669786564333218092001280f12190a116f7074696f6e616c5f73666978" .
+ "65643634180a2001281012160a0e6f7074696f6e616c5f666c6f6174180b" .
+ "2001280212170a0f6f7074696f6e616c5f646f75626c65180c2001280112" .
+ "150a0d6f7074696f6e616c5f626f6f6c180d2001280812170a0f6f707469" .
+ "6f6e616c5f737472696e67180e2001280912160a0e6f7074696f6e616c5f" .
+ "6279746573180f2001280c12240a0d6f7074696f6e616c5f656e756d1810" .
+ "2001280e320d2e666f6f2e54657374456e756d122e0a106f7074696f6e61" .
+ "6c5f6d65737361676518112001280b32142e666f6f2e546573744d657373" .
+ "6167652e53756212330a196f7074696f6e616c5f696e636c756465645f6d" .
+ "65737361676518122001280b32102e6261722e54657374496e636c756465" .
+ "12230a0972656375727369766518132001280b32102e666f6f2e54657374" .
+ "4d65737361676512160a0e72657065617465645f696e743332181f200328" .
+ "0512160a0e72657065617465645f696e74363418202003280312170a0f72" .
+ "657065617465645f75696e74333218212003280d12170a0f726570656174" .
+ "65645f75696e74363418222003280412170a0f72657065617465645f7369" .
+ "6e74333218232003281112170a0f72657065617465645f73696e74363418" .
+ "242003281212180a1072657065617465645f666978656433321825200328" .
+ "0712180a1072657065617465645f6669786564363418262003280612190a" .
+ "1172657065617465645f736669786564333218272003280f12190a117265" .
+ "7065617465645f736669786564363418282003281012160a0e7265706561" .
+ "7465645f666c6f617418292003280212170a0f72657065617465645f646f" .
+ "75626c65182a2003280112150a0d72657065617465645f626f6f6c182b20" .
+ "03280812170a0f72657065617465645f737472696e67182c200328091216" .
+ "0a0e72657065617465645f6279746573182d2003280c12240a0d72657065" .
+ "617465645f656e756d182e2003280e320d2e666f6f2e54657374456e756d" .
+ "122e0a1072657065617465645f6d657373616765182f2003280b32142e66" .
+ "6f6f2e546573744d6573736167652e537562122c0a127265706561746564" .
+ "5f72656375727369766518302003280b32102e666f6f2e546573744d6573" .
+ "7361676512150a0b6f6e656f665f696e743332183320012805480012150a" .
+ "0b6f6e656f665f696e743634183420012803480012160a0c6f6e656f665f" .
+ "75696e74333218352001280d480012160a0c6f6e656f665f75696e743634" .
+ "183620012804480012160a0c6f6e656f665f73696e74333218372001280d" .
+ "480012160a0c6f6e656f665f73696e743634183820012804480012170a0d" .
+ "6f6e656f665f6669786564333218392001280d480012170a0d6f6e656f66" .
+ "5f66697865643634183a20012804480012180a0e6f6e656f665f73666978" .
+ "65643332183b2001280d480012180a0e6f6e656f665f7366697865643634" .
+ "183c20012804480012160a0c6f6e656f665f646f75626c65183d20012801" .
+ "480012150a0b6f6e656f665f666c6f6174183e20012802480012140a0a6f" .
+ "6e656f665f626f6f6c183f20012808480012160a0c6f6e656f665f737472" .
+ "696e67184020012809480012150a0b6f6e656f665f627974657318412001" .
+ "280c480012230a0a6f6e656f665f656e756d18422001280e320d2e666f6f" .
+ "2e54657374456e756d4800122d0a0d6f6e656f665f6d6573736167651843" .
+ "2001280b32142e666f6f2e546573744d6573736167652e5375624800123c" .
+ "0a0f6d61705f696e7433325f696e74333218472003280b32232e666f6f2e" .
+ "546573744d6573736167652e4d6170496e743332496e743332456e747279" .
+ "123c0a0f6d61705f696e7436345f696e74363418482003280b32232e666f" .
+ "6f2e546573744d6573736167652e4d6170496e743634496e743634456e74" .
+ "727912400a116d61705f75696e7433325f75696e74333218492003280b32" .
+ "252e666f6f2e546573744d6573736167652e4d617055696e74333255696e" .
+ "743332456e74727912400a116d61705f75696e7436345f75696e74363418" .
+ "4a2003280b32252e666f6f2e546573744d6573736167652e4d617055696e" .
+ "74363455696e743634456e74727912400a116d61705f73696e7433325f73" .
+ "696e743332184b2003280b32252e666f6f2e546573744d6573736167652e" .
+ "4d617053696e74333253696e743332456e74727912400a116d61705f7369" .
+ "6e7436345f73696e743634184c2003280b32252e666f6f2e546573744d65" .
+ "73736167652e4d617053696e74363453696e743634456e74727912440a13" .
+ "6d61705f666978656433325f66697865643332184d2003280b32272e666f" .
+ "6f2e546573744d6573736167652e4d617046697865643332466978656433" .
+ "32456e74727912440a136d61705f666978656436345f6669786564363418" .
+ "4e2003280b32272e666f6f2e546573744d6573736167652e4d6170466978" .
+ "6564363446697865643634456e74727912480a156d61705f736669786564" .
+ "33325f7366697865643332184f2003280b32292e666f6f2e546573744d65" .
+ "73736167652e4d617053666978656433325366697865643332456e747279" .
+ "12480a156d61705f73666978656436345f73666978656436341850200328" .
+ "0b32292e666f6f2e546573744d6573736167652e4d617053666978656436" .
+ "345366697865643634456e747279123c0a0f6d61705f696e7433325f666c" .
+ "6f617418512003280b32232e666f6f2e546573744d6573736167652e4d61" .
+ "70496e743332466c6f6174456e747279123e0a106d61705f696e7433325f" .
+ "646f75626c6518522003280b32242e666f6f2e546573744d657373616765" .
+ "2e4d6170496e743332446f75626c65456e74727912380a0d6d61705f626f" .
+ "6f6c5f626f6f6c18532003280b32212e666f6f2e546573744d6573736167" .
+ "652e4d6170426f6f6c426f6f6c456e74727912400a116d61705f73747269" .
+ "6e675f737472696e6718542003280b32252e666f6f2e546573744d657373" .
+ "6167652e4d6170537472696e67537472696e67456e747279123c0a0f6d61" .
+ "705f696e7433325f627974657318552003280b32232e666f6f2e54657374" .
+ "4d6573736167652e4d6170496e7433324279746573456e747279123a0a0e" .
+ "6d61705f696e7433325f656e756d18562003280b32222e666f6f2e546573" .
+ "744d6573736167652e4d6170496e743332456e756d456e74727912400a11" .
+ "6d61705f696e7433325f6d65737361676518572003280b32252e666f6f2e" .
+ "546573744d6573736167652e4d6170496e7433324d657373616765456e74" .
+ "727912390a0d6d61705f72656375727369766518582003280b32222e666f" .
+ "6f2e546573744d6573736167652e4d6170526563757273697665456e7472" .
+ "791a340a124d6170496e743332496e743332456e747279120b0a036b6579" .
+ "180120012805120d0a0576616c75651802200128053a0238011a340a124d" .
+ "6170496e743634496e743634456e747279120b0a036b6579180120012803" .
+ "120d0a0576616c75651802200128033a0238011a360a144d617055696e74" .
+ "333255696e743332456e747279120b0a036b657918012001280d120d0a05" .
+ "76616c756518022001280d3a0238011a360a144d617055696e7436345569" .
+ "6e743634456e747279120b0a036b6579180120012804120d0a0576616c75" .
+ "651802200128043a0238011a360a144d617053696e74333253696e743332" .
+ "456e747279120b0a036b6579180120012811120d0a0576616c7565180220" .
+ "0128113a0238011a360a144d617053696e74363453696e743634456e7472" .
+ "79120b0a036b6579180120012812120d0a0576616c75651802200128123a" .
+ "0238011a380a164d61704669786564333246697865643332456e74727912" .
+ "0b0a036b6579180120012807120d0a0576616c75651802200128073a0238" .
+ "011a380a164d61704669786564363446697865643634456e747279120b0a" .
+ "036b6579180120012806120d0a0576616c75651802200128063a0238011a" .
+ "3a0a184d617053666978656433325366697865643332456e747279120b0a" .
+ "036b657918012001280f120d0a0576616c756518022001280f3a0238011a" .
+ "3a0a184d617053666978656436345366697865643634456e747279120b0a" .
+ "036b6579180120012810120d0a0576616c75651802200128103a0238011a" .
+ "340a124d6170496e743332466c6f6174456e747279120b0a036b65791801" .
+ "20012805120d0a0576616c75651802200128023a0238011a350a134d6170" .
+ "496e743332446f75626c65456e747279120b0a036b657918012001280512" .
+ "0d0a0576616c75651802200128013a0238011a320a104d6170426f6f6c42" .
+ "6f6f6c456e747279120b0a036b6579180120012808120d0a0576616c7565" .
+ "1802200128083a0238011a360a144d6170537472696e67537472696e6745" .
+ "6e747279120b0a036b6579180120012809120d0a0576616c756518022001" .
+ "28093a0238011a340a124d6170496e7433324279746573456e747279120b" .
+ "0a036b6579180120012805120d0a0576616c756518022001280c3a023801" .
+ "1a420a114d6170496e743332456e756d456e747279120b0a036b65791801" .
+ "20012805121c0a0576616c756518022001280e320d2e666f6f2e54657374" .
+ "456e756d3a0238011a4c0a144d6170496e7433324d657373616765456e74" .
+ "7279120b0a036b657918012001280512230a0576616c756518022001280b" .
+ "32142e666f6f2e546573744d6573736167652e5375623a0238011a450a11" .
+ "4d6170526563757273697665456e747279120b0a036b6579180120012805" .
+ "121f0a0576616c756518022001280b32102e666f6f2e546573744d657373" .
+ "6167653a0238011a100a0353756212090a0161180120012805420a0a086d" .
+ "795f6f6e656f6622b7030a11546573745061636b65644d65737361676512" .
+ "1a0a0e72657065617465645f696e743332185a2003280542021001121a0a" .
+ "0e72657065617465645f696e743634185b2003280342021001121b0a0f72" .
+ "657065617465645f75696e743332185c2003280d42021001121b0a0f7265" .
+ "7065617465645f75696e743634185d2003280442021001121b0a0f726570" .
+ "65617465645f73696e743332185e2003281142021001121b0a0f72657065" .
+ "617465645f73696e743634185f2003281242021001121c0a107265706561" .
+ "7465645f6669786564333218602003280742021001121c0a107265706561" .
+ "7465645f6669786564363418612003280642021001121d0a117265706561" .
+ "7465645f736669786564333218622003280f42021001121d0a1172657065" .
+ "617465645f736669786564363418632003281042021001121a0a0e726570" .
+ "65617465645f666c6f617418642003280242021001121b0a0f7265706561" .
+ "7465645f646f75626c651865200328014202100112190a0d726570656174" .
+ "65645f626f6f6c1866200328084202100112280a0d72657065617465645f" .
+ "656e756d18672003280e320d2e666f6f2e54657374456e756d4202100122" .
+ "b9030a1354657374556e7061636b65644d657373616765121a0a0e726570" .
+ "65617465645f696e743332185a2003280542021000121a0a0e7265706561" .
+ "7465645f696e743634185b2003280342021000121b0a0f72657065617465" .
+ "645f75696e743332185c2003280d42021000121b0a0f7265706561746564" .
+ "5f75696e743634185d2003280442021000121b0a0f72657065617465645f" .
+ "73696e743332185e2003281142021000121b0a0f72657065617465645f73" .
+ "696e743634185f2003281242021000121c0a1072657065617465645f6669" .
+ "786564333218602003280742021000121c0a1072657065617465645f6669" .
+ "786564363418612003280642021000121d0a1172657065617465645f7366" .
+ "69786564333218622003280f42021000121d0a1172657065617465645f73" .
+ "6669786564363418632003281042021000121a0a0e72657065617465645f" .
+ "666c6f617418642003280242021000121b0a0f72657065617465645f646f" .
+ "75626c651865200328014202100012190a0d72657065617465645f626f6f" .
+ "6c1866200328084202100012280a0d72657065617465645f656e756d1867" .
+ "2003280e320d2e666f6f2e54657374456e756d420210002a1d0a08546573" .
+ "74456e756d12080a045a45524f100012070a034f4e451001620670726f74" .
+ "6f33"
+));
+
diff --git a/php/tests/test.proto b/php/tests/test.proto
new file mode 100644
index 00000000..15709c83
--- /dev/null
+++ b/php/tests/test.proto
@@ -0,0 +1,136 @@
+syntax = "proto3";
+
+import 'test_include.proto';
+
+package foo;
+
+message TestMessage {
+ // Singular
+ int32 optional_int32 = 1;
+ int64 optional_int64 = 2;
+ uint32 optional_uint32 = 3;
+ uint64 optional_uint64 = 4;
+ sint32 optional_sint32 = 5;
+ sint64 optional_sint64 = 6;
+ fixed32 optional_fixed32 = 7;
+ fixed64 optional_fixed64 = 8;
+ sfixed32 optional_sfixed32 = 9;
+ sfixed64 optional_sfixed64 = 10;
+ float optional_float = 11;
+ double optional_double = 12;
+ bool optional_bool = 13;
+ string optional_string = 14;
+ bytes optional_bytes = 15;
+
+ TestEnum optional_enum = 16;
+ Sub optional_message = 17;
+ bar.TestInclude optional_included_message = 18;
+ TestMessage recursive = 19;
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+
+ repeated TestEnum repeated_enum = 46;
+ repeated Sub repeated_message = 47;
+ repeated TestMessage repeated_recursive = 48;
+
+ oneof my_oneof {
+ int32 oneof_int32 = 51;
+ int64 oneof_int64 = 52;
+ uint32 oneof_uint32 = 53;
+ uint64 oneof_uint64 = 54;
+ uint32 oneof_sint32 = 55;
+ uint64 oneof_sint64 = 56;
+ uint32 oneof_fixed32 = 57;
+ uint64 oneof_fixed64 = 58;
+ uint32 oneof_sfixed32 = 59;
+ uint64 oneof_sfixed64 = 60;
+ double oneof_double = 61;
+ float oneof_float = 62;
+ bool oneof_bool = 63;
+ string oneof_string = 64;
+ bytes oneof_bytes = 65;
+ TestEnum oneof_enum = 66;
+ Sub oneof_message = 67;
+ }
+
+ map<int32, int32> map_int32_int32 = 71;
+ map<int64, int64> map_int64_int64 = 72;
+ map<uint32, uint32> map_uint32_uint32 = 73;
+ map<uint64, uint64> map_uint64_uint64 = 74;
+ map<sint32, sint32> map_sint32_sint32 = 75;
+ map<sint64, sint64> map_sint64_sint64 = 76;
+ map<fixed32, fixed32> map_fixed32_fixed32 = 77;
+ map<fixed64, fixed64> map_fixed64_fixed64 = 78;
+ map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 79;
+ map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 80;
+ map<int32, float> map_int32_float = 81;
+ map<int32, double> map_int32_double = 82;
+ map<bool, bool> map_bool_bool = 83;
+ map<string, string> map_string_string = 84;
+ map<int32, bytes> map_int32_bytes = 85;
+ map<int32, TestEnum> map_int32_enum = 86;
+ map<int32, Sub> map_int32_message = 87;
+
+ map<int32, TestMessage> map_recursive = 88;
+
+ message Sub {
+ int32 a = 1;
+ }
+
+ // NestedMessage nested_message = 90;
+}
+
+enum TestEnum {
+ ZERO = 0;
+ ONE = 1;
+}
+
+message TestPackedMessage {
+ repeated int32 repeated_int32 = 90 [packed = true];
+ repeated int64 repeated_int64 = 91 [packed = true];
+ repeated uint32 repeated_uint32 = 92 [packed = true];
+ repeated uint64 repeated_uint64 = 93 [packed = true];
+ repeated sint32 repeated_sint32 = 94 [packed = true];
+ repeated sint64 repeated_sint64 = 95 [packed = true];
+ repeated fixed32 repeated_fixed32 = 96 [packed = true];
+ repeated fixed64 repeated_fixed64 = 97 [packed = true];
+ repeated sfixed32 repeated_sfixed32 = 98 [packed = true];
+ repeated sfixed64 repeated_sfixed64 = 99 [packed = true];
+ repeated float repeated_float = 100 [packed = true];
+ repeated double repeated_double = 101 [packed = true];
+ repeated bool repeated_bool = 102 [packed = true];
+ repeated TestEnum repeated_enum = 103 [packed = true];
+}
+
+// Need to be in sync with TestPackedMessage.
+message TestUnpackedMessage {
+ repeated int32 repeated_int32 = 90 [packed = false];
+ repeated int64 repeated_int64 = 91 [packed = false];
+ repeated uint32 repeated_uint32 = 92 [packed = false];
+ repeated uint64 repeated_uint64 = 93 [packed = false];
+ repeated sint32 repeated_sint32 = 94 [packed = false];
+ repeated sint64 repeated_sint64 = 95 [packed = false];
+ repeated fixed32 repeated_fixed32 = 96 [packed = false];
+ repeated fixed64 repeated_fixed64 = 97 [packed = false];
+ repeated sfixed32 repeated_sfixed32 = 98 [packed = false];
+ repeated sfixed64 repeated_sfixed64 = 99 [packed = false];
+ repeated float repeated_float = 100 [packed = false];
+ repeated double repeated_double = 101 [packed = false];
+ repeated bool repeated_bool = 102 [packed = false];
+ repeated TestEnum repeated_enum = 103 [packed = false];
+}
diff --git a/php/tests/test.sh b/php/tests/test.sh
new file mode 100755
index 00000000..52833edb
--- /dev/null
+++ b/php/tests/test.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+cd ../ext/google/protobuf/
+make clean
+set -e
+
+phpize && ./configure --enable-debug CFLAGS='-g -O0' && make
+cd -
+
+tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php )
+
+for t in "${tests[@]}"
+do
+ echo "****************************"
+ echo "* $t"
+ echo "****************************"
+ php -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` $t
+ echo ""
+done
+
+# Make sure to run the memory test in debug mode.
+php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
+
+USE_ZEND_ALLOC=0 valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
diff --git a/php/tests/test_base.php b/php/tests/test_base.php
new file mode 100644
index 00000000..25f18f74
--- /dev/null
+++ b/php/tests/test_base.php
@@ -0,0 +1,92 @@
+<?php
+
+use Foo\TestMessage;
+use Foo\TestMessage_Sub;
+
+class TestBase extends PHPUnit_Framework_TestCase
+{
+
+ public function setFields(TestMessage $m)
+ {
+ TestUtil::setTestMessage($m);
+ }
+
+ public function expectFields(TestMessage $m)
+ {
+ $this->assertSame(-42, $m->getOptionalInt32());
+ $this->assertSame(42, $m->getOptionalUint32());
+ $this->assertSame(-43, $m->getOptionalInt64());
+ $this->assertSame(43, $m->getOptionalUint64());
+ $this->assertSame(-44, $m->getOptionalSint32());
+ $this->assertSame(-45, $m->getOptionalSint64());
+ $this->assertSame(46, $m->getOptionalFixed32());
+ $this->assertSame(47, $m->getOptionalFixed64());
+ $this->assertSame(-46, $m->getOptionalSfixed32());
+ $this->assertSame(-47, $m->getOptionalSfixed64());
+ $this->assertSame(1.5, $m->getOptionalFloat());
+ $this->assertSame(1.6, $m->getOptionalDouble());
+ $this->assertSame(true, $m->getOptionalBool());
+ $this->assertSame('a', $m->getOptionalString());
+ $this->assertSame('b', $m->getOptionalBytes());
+ $this->assertSame(33, $m->getOptionalMessage()->getA());
+
+ $this->assertEquals(-42, $m->getRepeatedInt32()[0]);
+ $this->assertEquals(42, $m->getRepeatedUint32()[0]);
+ $this->assertEquals(-43, $m->getRepeatedInt64()[0]);
+ $this->assertEquals(43, $m->getRepeatedUint64()[0]);
+ $this->assertEquals(-44, $m->getRepeatedSint32()[0]);
+ $this->assertEquals(-45, $m->getRepeatedSint64()[0]);
+ $this->assertEquals(46, $m->getRepeatedFixed32()[0]);
+ $this->assertEquals(47, $m->getRepeatedFixed64()[0]);
+ $this->assertEquals(-46, $m->getRepeatedSfixed32()[0]);
+ $this->assertEquals(-47, $m->getRepeatedSfixed64()[0]);
+ $this->assertEquals(1.5, $m->getRepeatedFloat()[0]);
+ $this->assertEquals(1.6, $m->getRepeatedDouble()[0]);
+ $this->assertEquals(true, $m->getRepeatedBool()[0]);
+ $this->assertEquals('a', $m->getRepeatedString()[0]);
+ $this->assertEquals('b', $m->getRepeatedBytes()[0]);
+ $this->assertEquals(34, $m->getRepeatedMessage()[0]->GetA());
+
+ $this->assertEquals(-52, $m->getRepeatedInt32()[1]);
+ $this->assertEquals(52, $m->getRepeatedUint32()[1]);
+ $this->assertEquals(-53, $m->getRepeatedInt64()[1]);
+ $this->assertEquals(53, $m->getRepeatedUint64()[1]);
+ $this->assertEquals(-54, $m->getRepeatedSint32()[1]);
+ $this->assertEquals(-55, $m->getRepeatedSint64()[1]);
+ $this->assertEquals(56, $m->getRepeatedFixed32()[1]);
+ $this->assertEquals(57, $m->getRepeatedFixed64()[1]);
+ $this->assertEquals(-56, $m->getRepeatedSfixed32()[1]);
+ $this->assertEquals(-57, $m->getRepeatedSfixed64()[1]);
+ $this->assertEquals(2.5, $m->getRepeatedFloat()[1]);
+ $this->assertEquals(2.6, $m->getRepeatedDouble()[1]);
+ $this->assertEquals(false, $m->getRepeatedBool()[1]);
+ $this->assertEquals('c', $m->getRepeatedString()[1]);
+ $this->assertEquals('d', $m->getRepeatedBytes()[1]);
+ $this->assertEquals(35, $m->getRepeatedMessage()[1]->GetA());
+ }
+
+ public function expectEmptyFields(TestMessage $m)
+ {
+ $this->assertSame(0, $m->getOptionalInt32());
+ $this->assertSame(0, $m->getOptionalUint32());
+ $this->assertSame(0, $m->getOptionalInt64());
+ $this->assertSame(0, $m->getOptionalUint64());
+ $this->assertSame(0, $m->getOptionalSint32());
+ $this->assertSame(0, $m->getOptionalSint64());
+ $this->assertSame(0, $m->getOptionalFixed32());
+ $this->assertSame(0, $m->getOptionalFixed64());
+ $this->assertSame(0, $m->getOptionalSfixed32());
+ $this->assertSame(0, $m->getOptionalSfixed64());
+ $this->assertSame(0.0, $m->getOptionalFloat());
+ $this->assertSame(0.0, $m->getOptionalDouble());
+ $this->assertSame(false, $m->getOptionalBool());
+ $this->assertSame('', $m->getOptionalString());
+ $this->assertSame('', $m->getOptionalBytes());
+ $this->assertNull($m->getOptionalMessage());
+ }
+
+ // This test is to avoid the warning of no test by php unit.
+ public function testNone()
+ {
+ }
+}
diff --git a/php/tests/test_include.pb.php b/php/tests/test_include.pb.php
new file mode 100644
index 00000000..2c43cc41
--- /dev/null
+++ b/php/tests/test_include.pb.php
@@ -0,0 +1,36 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: test_include.proto
+
+namespace Bar;
+
+use Google\Protobuf\Internal\DescriptorPool;
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+class TestInclude extends \Google\Protobuf\Internal\Message
+{
+ private $a = 0;
+
+ public function getA()
+ {
+ return $this->a;
+ }
+
+ public function setA($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->a = $var;
+ }
+
+}
+
+$pool = DescriptorPool::getGeneratedPool();
+
+$pool->internalAddGeneratedFile(hex2bin(
+ "0a3b0a12746573745f696e636c7564652e70726f746f120362617222180a" .
+ "0b54657374496e636c75646512090a0161180120012805620670726f746f" .
+ "33"
+));
+
diff --git a/php/tests/test_util.php b/php/tests/test_util.php
new file mode 100644
index 00000000..decd1a78
--- /dev/null
+++ b/php/tests/test_util.php
@@ -0,0 +1,393 @@
+<?php
+
+use Foo\TestEnum;
+use Foo\TestMessage;
+use Foo\TestMessage_Sub;
+use Foo\TestPackedMessage;
+use Foo\TestUnpackedMessage;
+
+define('MAX_FLOAT_DIFF', 0.000001);
+
+if (PHP_INT_SIZE == 8) {
+ define('MAX_INT_STRING', '9223372036854775807');
+ define('MAX_INT_UPPER_STRING', '9223372036854775808');
+} else {
+ define('MAX_INT_STRING', '2147483647');
+ define('MAX_INT_UPPER_STRING', '2147483648');
+}
+
+define('MAX_INT32', 2147483647);
+define('MAX_INT32_FLOAT', 2147483647.0);
+define('MAX_INT32_STRING', '2147483647');
+
+define('MIN_INT32', -2147483648);
+define('MIN_INT32_FLOAT', -2147483648.0);
+define('MIN_INT32_STRING', '-2147483648');
+
+define('MAX_UINT32', 4294967295);
+define('MAX_UINT32_FLOAT', 4294967295.0);
+define('MAX_UINT32_STRING', '4294967295');
+
+define('MIN_UINT32', -2147483648);
+define('MIN_UINT32_FLOAT', -2147483648.0);
+define('MIN_UINT32_STRING', '-2147483648');
+
+define('MAX_INT64', 9223372036854775807);
+define('MAX_INT64_STRING', '9223372036854775807');
+
+define('MIN_INT64_STRING', '-9223372036854775808');
+if (PHP_INT_SIZE === 8) {
+ define('MIN_INT64', -9223372036854775808);
+} else {
+ define('MIN_INT64', MIN_INT64_STRING);
+}
+
+define('MAX_UINT64_STRING', '-9223372036854775808');
+define('MAX_UINT64', MAX_UINT64_STRING);
+
+class TestUtil
+{
+
+ public static function setTestMessage(TestMessage $m)
+ {
+ $m->setOptionalInt32(-42);
+ $m->setOptionalInt64(-43);
+ $m->setOptionalUint32(42);
+ $m->setOptionalUint64(43);
+ $m->setOptionalSint32(-44);
+ $m->setOptionalSint64(-45);
+ $m->setOptionalFixed32(46);
+ $m->setOptionalFixed64(47);
+ $m->setOptionalSfixed32(-46);
+ $m->setOptionalSfixed64(-47);
+ $m->setOptionalFloat(1.5);
+ $m->setOptionalDouble(1.6);
+ $m->setOptionalBool(true);
+ $m->setOptionalString('a');
+ $m->setOptionalBytes('b');
+ $m->setOptionalEnum(TestEnum::ONE);
+ $m->setOptionalMessage(new TestMessage_Sub());
+ $m->getOptionalMessage()->SetA(33);
+
+ $m->getRepeatedInt32() []= -42;
+ $m->getRepeatedInt64() []= -43;
+ $m->getRepeatedUint32() []= 42;
+ $m->getRepeatedUint64() []= 43;
+ $m->getRepeatedSint32() []= -44;
+ $m->getRepeatedSint64() []= -45;
+ $m->getRepeatedFixed32() []= 46;
+ $m->getRepeatedFixed64() []= 47;
+ $m->getRepeatedSfixed32() []= -46;
+ $m->getRepeatedSfixed64() []= -47;
+ $m->getRepeatedFloat() []= 1.5;
+ $m->getRepeatedDouble() []= 1.6;
+ $m->getRepeatedBool() []= true;
+ $m->getRepeatedString() []= 'a';
+ $m->getRepeatedBytes() []= 'b';
+ $m->getRepeatedEnum() []= TestEnum::ZERO;
+ $m->getRepeatedMessage() []= new TestMessage_Sub();
+ $m->getRepeatedMessage()[0]->setA(34);
+
+ $m->getRepeatedInt32() []= -52;
+ $m->getRepeatedInt64() []= -53;
+ $m->getRepeatedUint32() []= 52;
+ $m->getRepeatedUint64() []= 53;
+ $m->getRepeatedSint32() []= -54;
+ $m->getRepeatedSint64() []= -55;
+ $m->getRepeatedFixed32() []= 56;
+ $m->getRepeatedFixed64() []= 57;
+ $m->getRepeatedSfixed32() []= -56;
+ $m->getRepeatedSfixed64() []= -57;
+ $m->getRepeatedFloat() []= 2.5;
+ $m->getRepeatedDouble() []= 2.6;
+ $m->getRepeatedBool() []= false;
+ $m->getRepeatedString() []= 'c';
+ $m->getRepeatedBytes() []= 'd';
+ $m->getRepeatedEnum() []= TestEnum::ONE;
+ $m->getRepeatedMessage() []= new TestMessage_Sub();
+ $m->getRepeatedMessage()[1]->SetA(35);
+
+ $m->getMapInt32Int32()[-62] = -62;
+ $m->getMapInt64Int64()[-63] = -63;
+ $m->getMapUint32Uint32()[62] = 62;
+ $m->getMapUint64Uint64()[63] = 63;
+ $m->getMapSint32Sint32()[-64] = -64;
+ $m->getMapSint64Sint64()[-65] = -65;
+ $m->getMapFixed32Fixed32()[66] = 66;
+ $m->getMapFixed64Fixed64()[67] = 67;
+ $m->getMapInt32Float()[1] = 3.5;
+ $m->getMapInt32Double()[1] = 3.6;
+ $m->getMapBoolBool()[true] = true;
+ $m->getMapStringString()['e'] = 'e';
+ $m->getMapInt32Bytes()[1] = 'f';
+ $m->getMapInt32Enum()[1] = TestEnum::ONE;
+ $m->getMapInt32Message()[1] = new TestMessage_Sub();
+ $m->getMapInt32Message()[1]->SetA(36);
+ }
+
+ public static function assertTestMessage(TestMessage $m)
+ {
+ assert(-42 === $m->getOptionalInt32());
+ assert(42 === $m->getOptionalUint32());
+ assert(-43 === $m->getOptionalInt64());
+ assert(43 === $m->getOptionalUint64());
+ assert(-44 === $m->getOptionalSint32());
+ assert(-45 === $m->getOptionalSint64());
+ assert(46 === $m->getOptionalFixed32());
+ assert(47 === $m->getOptionalFixed64());
+ assert(-46 === $m->getOptionalSfixed32());
+ assert(-47 === $m->getOptionalSfixed64());
+ assert(1.5 === $m->getOptionalFloat());
+ assert(1.6 === $m->getOptionalDouble());
+ assert(true=== $m->getOptionalBool());
+ assert('a' === $m->getOptionalString());
+ assert('b' === $m->getOptionalBytes());
+ assert(TestEnum::ONE === $m->getOptionalEnum());
+ assert(33 === $m->getOptionalMessage()->getA());
+
+ assert(-42 === $m->getRepeatedInt32()[0]);
+ assert(42 === $m->getRepeatedUint32()[0]);
+ assert(-43 === $m->getRepeatedInt64()[0]);
+ assert(43 === $m->getRepeatedUint64()[0]);
+ assert(-44 === $m->getRepeatedSint32()[0]);
+ assert(-45 === $m->getRepeatedSint64()[0]);
+ assert(46 === $m->getRepeatedFixed32()[0]);
+ assert(47 === $m->getRepeatedFixed64()[0]);
+ assert(-46 === $m->getRepeatedSfixed32()[0]);
+ assert(-47 === $m->getRepeatedSfixed64()[0]);
+ assert(1.5 === $m->getRepeatedFloat()[0]);
+ assert(1.6 === $m->getRepeatedDouble()[0]);
+ assert(true=== $m->getRepeatedBool()[0]);
+ assert('a' === $m->getRepeatedString()[0]);
+ assert('b' === $m->getRepeatedBytes()[0]);
+ assert(TestEnum::ZERO === $m->getRepeatedEnum()[0]);
+ assert(34 === $m->getRepeatedMessage()[0]->getA());
+
+ assert(-52 === $m->getRepeatedInt32()[1]);
+ assert(52 === $m->getRepeatedUint32()[1]);
+ assert(-53 === $m->getRepeatedInt64()[1]);
+ assert(53 === $m->getRepeatedUint64()[1]);
+ assert(-54 === $m->getRepeatedSint32()[1]);
+ assert(-55 === $m->getRepeatedSint64()[1]);
+ assert(56 === $m->getRepeatedFixed32()[1]);
+ assert(57 === $m->getRepeatedFixed64()[1]);
+ assert(-56 === $m->getRepeatedSfixed32()[1]);
+ assert(-57 === $m->getRepeatedSfixed64()[1]);
+ assert(2.5 === $m->getRepeatedFloat()[1]);
+ assert(2.6 === $m->getRepeatedDouble()[1]);
+ assert(false === $m->getRepeatedBool()[1]);
+ assert('c' === $m->getRepeatedString()[1]);
+ assert('d' === $m->getRepeatedBytes()[1]);
+ assert(TestEnum::ONE === $m->getRepeatedEnum()[1]);
+ assert(35 === $m->getRepeatedMessage()[1]->getA());
+
+ assert(-62 === $m->getMapInt32Int32()[-62]);
+ assert(-63 === $m->getMapInt64Int64()[-63]);
+ assert(62 === $m->getMapUint32Uint32()[62]);
+ assert(63 === $m->getMapUint64Uint64()[63]);
+ assert(-64 === $m->getMapSint32Sint32()[-64]);
+ assert(-65 === $m->getMapSint64Sint64()[-65]);
+ assert(66 === $m->getMapFixed32Fixed32()[66]);
+ assert(67 === $m->getMapFixed64Fixed64()[67]);
+ assert(3.5 === $m->getMapInt32Float()[1]);
+ assert(3.6 === $m->getMapInt32Double()[1]);
+ assert(true === $m->getMapBoolBool()[true]);
+ assert('e' === $m->getMapStringString()['e']);
+ assert('f' === $m->getMapInt32Bytes()[1]);
+ assert(TestEnum::ONE === $m->getMapInt32Enum()[1]);
+ assert(36 === $m->getMapInt32Message()[1]->GetA());
+ }
+
+ public static function getGoldenTestMessage()
+ {
+ return hex2bin(
+ "08D6FFFFFF0F" .
+ "10D5FFFFFFFFFFFFFFFF01" .
+ "182A" .
+ "202B" .
+ "2857" .
+ "3059" .
+ "3D2E000000" .
+ "412F00000000000000" .
+ "4DD2FFFFFF" .
+ "51D1FFFFFFFFFFFFFF" .
+ "5D0000C03F" .
+ "619A9999999999F93F" .
+ "6801" .
+ "720161" .
+ "7A0162" .
+ "800101" .
+ "8A01020821" .
+
+ "F801D6FFFFFF0F" .
+ "F801CCFFFFFF0F" .
+ "8002D5FFFFFFFFFFFFFFFF01" .
+ "8002CBFFFFFFFFFFFFFFFF01" .
+ "88022A" .
+ "880234" .
+ "90022B" .
+ "900235" .
+ "980257" .
+ "98026B" .
+ "A00259" .
+ "A0026D" .
+ "AD022E000000" .
+ "AD0238000000" .
+ "B1022F00000000000000" .
+ "B1023900000000000000" .
+ "BD02D2FFFFFF" .
+ "BD02C8FFFFFF" .
+ "C102D1FFFFFFFFFFFFFF" .
+ "C102C7FFFFFFFFFFFFFF" .
+ "CD020000C03F" .
+ "CD0200002040" .
+ "D1029A9999999999F93F" .
+ "D102CDCCCCCCCCCC0440" .
+ "D80201" .
+ "D80200" .
+ "E2020161" .
+ "E2020163" .
+ "EA020162" .
+ "EA020164" .
+ "F00200" .
+ "F00201" .
+ "FA02020822" .
+ "FA02020823" .
+
+ "BA040C08C2FFFFFF0F10C2FFFFFF0F" .
+ "C2041608C1FFFFFFFFFFFFFFFF0110C1FFFFFFFFFFFFFFFF01" .
+ "CA0404083E103E" .
+ "D20404083F103F" .
+ "DA0404087f107F" .
+ "E20406088101108101" .
+ "EA040A0D420000001542000000" .
+ "F20412094300000000000000114300000000000000" .
+ "8A050708011500006040" .
+ "92050B080111CDCCCCCCCCCC0C40" .
+ "9A050408011001" .
+ "A205060a0165120165" .
+ "AA05050801120166" .
+ "B2050408011001" .
+ "Ba0506080112020824"
+ );
+ }
+
+ public static function setTestPackedMessage($m)
+ {
+ $m->getRepeatedInt32()[] = -42;
+ $m->getRepeatedInt32()[] = -52;
+ $m->getRepeatedInt64()[] = -43;
+ $m->getRepeatedInt64()[] = -53;
+ $m->getRepeatedUint32()[] = 42;
+ $m->getRepeatedUint32()[] = 52;
+ $m->getRepeatedUint64()[] = 43;
+ $m->getRepeatedUint64()[] = 53;
+ $m->getRepeatedSint32()[] = -44;
+ $m->getRepeatedSint32()[] = -54;
+ $m->getRepeatedSint64()[] = -45;
+ $m->getRepeatedSint64()[] = -55;
+ $m->getRepeatedFixed32()[] = 46;
+ $m->getRepeatedFixed32()[] = 56;
+ $m->getRepeatedFixed64()[] = 47;
+ $m->getRepeatedFixed64()[] = 57;
+ $m->getRepeatedSfixed32()[] = -46;
+ $m->getRepeatedSfixed32()[] = -56;
+ $m->getRepeatedSfixed64()[] = -47;
+ $m->getRepeatedSfixed64()[] = -57;
+ $m->getRepeatedFloat()[] = 1.5;
+ $m->getRepeatedFloat()[] = 2.5;
+ $m->getRepeatedDouble()[] = 1.6;
+ $m->getRepeatedDouble()[] = 2.6;
+ $m->getRepeatedBool()[] = true;
+ $m->getRepeatedBool()[] = false;
+ $m->getRepeatedEnum()[] = TestEnum::ONE;
+ $m->getRepeatedEnum()[] = TestEnum::ZERO;
+ }
+
+ public static function assertTestPackedMessage($m)
+ {
+ assert(2 === count($m->getRepeatedInt32()));
+ assert(2 === count($m->getRepeatedInt64()));
+ assert(2 === count($m->getRepeatedUint32()));
+ assert(2 === count($m->getRepeatedUint64()));
+ assert(2 === count($m->getRepeatedSint32()));
+ assert(2 === count($m->getRepeatedSint64()));
+ assert(2 === count($m->getRepeatedFixed32()));
+ assert(2 === count($m->getRepeatedFixed64()));
+ assert(2 === count($m->getRepeatedSfixed32()));
+ assert(2 === count($m->getRepeatedSfixed64()));
+ assert(2 === count($m->getRepeatedFloat()));
+ assert(2 === count($m->getRepeatedDouble()));
+ assert(2 === count($m->getRepeatedBool()));
+ assert(2 === count($m->getRepeatedEnum()));
+
+ assert(-42 === $m->getRepeatedInt32()[0]);
+ assert(-52 === $m->getRepeatedInt32()[1]);
+ assert(-43 === $m->getRepeatedInt64()[0]);
+ assert(-53 === $m->getRepeatedInt64()[1]);
+ assert(42 === $m->getRepeatedUint32()[0]);
+ assert(52 === $m->getRepeatedUint32()[1]);
+ assert(43 === $m->getRepeatedUint64()[0]);
+ assert(53 === $m->getRepeatedUint64()[1]);
+ assert(-44 === $m->getRepeatedSint32()[0]);
+ assert(-54 === $m->getRepeatedSint32()[1]);
+ assert(-45 === $m->getRepeatedSint64()[0]);
+ assert(-55 === $m->getRepeatedSint64()[1]);
+ assert(46 === $m->getRepeatedFixed32()[0]);
+ assert(56 === $m->getRepeatedFixed32()[1]);
+ assert(47 === $m->getRepeatedFixed64()[0]);
+ assert(57 === $m->getRepeatedFixed64()[1]);
+ assert(-46 === $m->getRepeatedSfixed32()[0]);
+ assert(-56 === $m->getRepeatedSfixed32()[1]);
+ assert(-47 === $m->getRepeatedSfixed64()[0]);
+ assert(-57 === $m->getRepeatedSfixed64()[1]);
+ assert(1.5 === $m->getRepeatedFloat()[0]);
+ assert(2.5 === $m->getRepeatedFloat()[1]);
+ assert(1.6 === $m->getRepeatedDouble()[0]);
+ assert(2.6 === $m->getRepeatedDouble()[1]);
+ assert(true === $m->getRepeatedBool()[0]);
+ assert(false === $m->getRepeatedBool()[1]);
+ assert(TestEnum::ONE === $m->getRepeatedEnum()[0]);
+ assert(TestEnum::ZERO === $m->getRepeatedEnum()[1]);
+ }
+
+ public static function getGoldenTestPackedMessage()
+ {
+ return hex2bin(
+ "D2050AD6FFFFFF0FCCFFFFFF0F" .
+ "DA0514D5FFFFFFFFFFFFFFFF01CBFFFFFFFFFFFFFFFF01" .
+ "E205022A34" .
+ "EA05022B35" .
+ "F20502576B" .
+ "FA0502596D" .
+ "8206082E00000038000000" .
+ "8A06102F000000000000003900000000000000" .
+ "920608D2FFFFFFC8FFFFFF" .
+ "9A0610D1FFFFFFFFFFFFFFC7FFFFFFFFFFFFFF" .
+ "A206080000C03F00002040" .
+ "AA06109A9999999999F93FCDCCCCCCCCCC0440" .
+ "B206020100" .
+ "BA06020100"
+ );
+ }
+
+ public static function getGoldenTestUnpackedMessage()
+ {
+ return hex2bin(
+ "D005D6FFFFFF0FD005CCFFFFFF0F" .
+ "D805D5FFFFFFFFFFFFFFFF01D805CBFFFFFFFFFFFFFFFF01" .
+ "E0052AE00534" .
+ "E8052BE80535" .
+ "F00557F0056B" .
+ "F80559F8056D" .
+ "85062E000000850638000000" .
+ "89062F0000000000000089063900000000000000" .
+ "9506D2FFFFFF9506C8FFFFFF" .
+ "9906D1FFFFFFFFFFFFFF9906C7FFFFFFFFFFFFFF" .
+ "A5060000C03FA50600002040" .
+ "A9069A9999999999F93FA906CDCCCCCCCCCC0440" .
+ "B00601B00600" .
+ "B80601B80600"
+ );
+ }
+}
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 00000000..d311c509
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="./vendor/autoload.php"
+ colors="true">
+ <testsuites>
+ <testsuite name="protobuf-tests">
+ <file>php/tests/php_implementation_test.php</file>
+ <file>php/tests/array_test.php</file>
+ <file>php/tests/encode_decode_test.php</file>
+ <file>php/tests/generated_class_test.php</file>
+ <file>php/tests/map_field_test.php</file>
+ </testsuite>
+ </testsuites>
+</phpunit>
diff --git a/src/Makefile.am b/src/Makefile.am
index f70e9550..13952e5b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -162,6 +162,7 @@ nobase_include_HEADERS = \
google/protobuf/compiler/js/js_generator.h \
google/protobuf/compiler/objectivec/objectivec_generator.h \
google/protobuf/compiler/objectivec/objectivec_helpers.h \
+ google/protobuf/compiler/php/php_generator.h \
google/protobuf/compiler/python/python_generator.h \
google/protobuf/compiler/ruby/ruby_generator.h \
google/protobuf/util/type_resolver.h \
@@ -443,6 +444,7 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/objectivec/objectivec_oneof.h \
google/protobuf/compiler/objectivec/objectivec_primitive_field.cc \
google/protobuf/compiler/objectivec/objectivec_primitive_field.h \
+ google/protobuf/compiler/php/php_generator.cc \
google/protobuf/compiler/python/python_generator.cc \
google/protobuf/compiler/ruby/ruby_generator.cc \
google/protobuf/compiler/csharp/csharp_doc_comment.cc \
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index 2f3c5b8f..b83b8f32 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -35,8 +35,7 @@
#include <google/protobuf/compiler/python/python_generator.h>
#include <google/protobuf/compiler/java/java_generator.h>
#include <google/protobuf/compiler/javanano/javanano_generator.h>
-// TODO(teboring): Add it back when php implementation is ready
-// #include <google/protobuf/compiler/php/php_generator.h>
+#include <google/protobuf/compiler/php/php_generator.h>
#include <google/protobuf/compiler/ruby/ruby_generator.h>
#include <google/protobuf/compiler/csharp/csharp_generator.h>
#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
@@ -68,11 +67,10 @@ int main(int argc, char* argv[]) {
cli.RegisterGenerator("--javanano_out", &javanano_generator,
"Generate Java Nano source file.");
- // TODO(teboring): Add it back when php implementation is ready
// PHP
- // google::protobuf::compiler::php::Generator php_generator;
- // cli.RegisterGenerator("--php_out", &php_generator,
- // "Generate PHP source file.");
+ google::protobuf::compiler::php::Generator php_generator;
+ cli.RegisterGenerator("--php_out", &php_generator,
+ "Generate PHP source file.");
// Ruby
google::protobuf::compiler::ruby::Generator rb_generator;
diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc
new file mode 100644
index 00000000..75ddb405
--- /dev/null
+++ b/src/google/protobuf/compiler/php/php_generator.cc
@@ -0,0 +1,781 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/php/php_generator.h>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <sstream>
+
+using google::protobuf::internal::scoped_ptr;
+
+const std::string kDescriptorFile = "google/protobuf/descriptor.proto";
+const std::string kDescriptorPackageName = "Google\\Protobuf\\Internal";
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace php {
+
+// Forward decls.
+std::string PhpName(const std::string& full_name, bool is_descriptor);
+std::string DefaultForField(google::protobuf::FieldDescriptor* field);
+std::string IntToString(int32 value);
+std::string GeneratedFileName(const std::string& proto_file,
+ bool is_descriptor);
+std::string LabelForField(google::protobuf::FieldDescriptor* field);
+std::string TypeName(google::protobuf::FieldDescriptor* field);
+std::string UnderscoresToCamelCase(const string& name, bool cap_first_letter);
+std::string EscapeDollor(const string& to_escape);
+std::string BinaryToHex(const string& binary);
+void GenerateMessage(const string& name_prefix,
+ const google::protobuf::Descriptor* message,
+ bool is_descriptor,
+ google::protobuf::io::Printer* printer);
+void GenerateEnum(const google::protobuf::EnumDescriptor* en,
+ google::protobuf::io::Printer* printer);
+void Indent(google::protobuf::io::Printer* printer);
+void Outdent(google::protobuf::io::Printer* printer);
+
+std::string MessageName(const google::protobuf::Descriptor* message,
+ bool is_descriptor) {
+ string message_name = message->name();
+ const google::protobuf::Descriptor* descriptor = message->containing_type();
+ while (descriptor != NULL) {
+ message_name = descriptor->name() + '_' + message_name;
+ descriptor = descriptor->containing_type();
+ }
+ return PhpName(message->file()->package(), is_descriptor) + '\\' +
+ message_name;
+}
+
+std::string MessageFullName(const google::protobuf::Descriptor* message,
+ bool is_descriptor) {
+ if (is_descriptor) {
+ return StringReplace(message->full_name(),
+ "google.protobuf",
+ "google.protobuf.internal", false);
+ } else {
+ return message->full_name();
+ }
+}
+
+std::string EnumFullName(const google::protobuf::EnumDescriptor* envm,
+ bool is_descriptor) {
+ if (is_descriptor) {
+ return StringReplace(envm->full_name(),
+ "google.protobuf",
+ "google.protobuf.internal", false);
+ } else {
+ return envm->full_name();
+ }
+}
+
+std::string EnumClassName(const google::protobuf::EnumDescriptor* envm) {
+ string enum_class_name = envm->name();
+ const google::protobuf::Descriptor* descriptor = envm->containing_type();
+ while (descriptor != NULL) {
+ enum_class_name = descriptor->name() + '_' + enum_class_name;
+ descriptor = descriptor->containing_type();
+ }
+ return enum_class_name;
+}
+
+std::string EnumName(const google::protobuf::EnumDescriptor* envm,
+ bool is_descriptor) {
+ string enum_name = EnumClassName(envm);
+ return PhpName(envm->file()->package(), is_descriptor) + '\\' + enum_name;
+}
+
+std::string PhpName(const std::string& full_name, bool is_descriptor) {
+ if (is_descriptor) {
+ return kDescriptorPackageName;
+ }
+
+ std::string result;
+ bool cap_next_letter = true;
+ for (int i = 0; i < full_name.size(); i++) {
+ if ('a' <= full_name[i] && full_name[i] <= 'z' && cap_next_letter) {
+ result += full_name[i] + ('A' - 'a');
+ cap_next_letter = false;
+ } else if (full_name[i] == '.') {
+ result += '\\';
+ cap_next_letter = true;
+ } else {
+ result += full_name[i];
+ cap_next_letter = false;
+ }
+ }
+ return result;
+}
+
+std::string DefaultForField(const google::protobuf::FieldDescriptor* field) {
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_FIXED64:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_SFIXED64:
+ case FieldDescriptor::TYPE_ENUM: return "0";
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_FLOAT: return "0.0";
+ case FieldDescriptor::TYPE_BOOL: return "false";
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_BYTES: return "''";
+ case FieldDescriptor::TYPE_MESSAGE:
+ case FieldDescriptor::TYPE_GROUP: return "null";
+ default: assert(false); return "";
+ }
+}
+
+std::string GeneratedFileName(const std::string& proto_file,
+ bool is_descriptor) {
+ if (is_descriptor) {
+ return "descriptor_internal.pb.php";
+ } else {
+ int lastindex = proto_file.find_last_of(".");
+ return proto_file.substr(0, lastindex) + ".pb.php";
+ }
+}
+
+std::string IntToString(int32 value) {
+ std::ostringstream os;
+ os << value;
+ return os.str();
+}
+
+std::string LabelForField(const google::protobuf::FieldDescriptor* field) {
+ switch (field->label()) {
+ case FieldDescriptor::LABEL_OPTIONAL: return "optional";
+ case FieldDescriptor::LABEL_REQUIRED: return "required";
+ case FieldDescriptor::LABEL_REPEATED: return "repeated";
+ default: assert(false); return "";
+ }
+}
+
+std::string TypeName(const google::protobuf::FieldDescriptor* field) {
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_INT32: return "int32";
+ case FieldDescriptor::TYPE_INT64: return "int64";
+ case FieldDescriptor::TYPE_UINT32: return "uint32";
+ case FieldDescriptor::TYPE_UINT64: return "uint64";
+ case FieldDescriptor::TYPE_SINT32: return "sint32";
+ case FieldDescriptor::TYPE_SINT64: return "sint64";
+ case FieldDescriptor::TYPE_FIXED32: return "fixed32";
+ case FieldDescriptor::TYPE_FIXED64: return "fixed64";
+ case FieldDescriptor::TYPE_SFIXED32: return "sfixed32";
+ case FieldDescriptor::TYPE_SFIXED64: return "sfixed64";
+ case FieldDescriptor::TYPE_DOUBLE: return "double";
+ case FieldDescriptor::TYPE_FLOAT: return "float";
+ case FieldDescriptor::TYPE_BOOL: return "bool";
+ case FieldDescriptor::TYPE_ENUM: return "enum";
+ case FieldDescriptor::TYPE_STRING: return "string";
+ case FieldDescriptor::TYPE_BYTES: return "bytes";
+ case FieldDescriptor::TYPE_MESSAGE: return "message";
+ case FieldDescriptor::TYPE_GROUP: return "group";
+ default: assert(false); return "";
+ }
+}
+
+std::string EnumOrMessageSuffix(
+ const google::protobuf::FieldDescriptor* field, bool is_descriptor) {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ return ", '" + MessageFullName(field->message_type(), is_descriptor) + "'";
+ }
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ return ", '" + EnumFullName(field->enum_type(), is_descriptor) + "'";
+ }
+ return "";
+}
+
+// Converts a name to camel-case. If cap_first_letter is true, capitalize the
+// first letter.
+std::string UnderscoresToCamelCase(const string& input, bool cap_first_letter) {
+ std::string result;
+ for (int i = 0; i < input.size(); i++) {
+ if ('a' <= input[i] && input[i] <= 'z') {
+ if (cap_first_letter) {
+ result += input[i] + ('A' - 'a');
+ } else {
+ result += input[i];
+ }
+ cap_first_letter = false;
+ } else if ('A' <= input[i] && input[i] <= 'Z') {
+ if (i == 0 && !cap_first_letter) {
+ // Force first letter to lower-case unless explicitly told to
+ // capitalize it.
+ result += input[i] + ('a' - 'A');
+ } else {
+ // Capital letters after the first are left as-is.
+ result += input[i];
+ }
+ cap_first_letter = false;
+ } else if ('0' <= input[i] && input[i] <= '9') {
+ result += input[i];
+ cap_first_letter = true;
+ } else {
+ cap_first_letter = true;
+ }
+ }
+ // Add a trailing "_" if the name should be altered.
+ if (input[input.size() - 1] == '#') {
+ result += '_';
+ }
+ return result;
+}
+
+std::string EscapeDollor(const string& to_escape) {
+ return StringReplace(to_escape, "$", "\\$", true);
+}
+
+std::string BinaryToHex(const string& src) {
+ string dest;
+ size_t i;
+ unsigned char symbol[16] = {
+ '0', '1', '2', '3',
+ '4', '5', '6', '7',
+ '8', '9', 'a', 'b',
+ 'c', 'd', 'e', 'f',
+ };
+
+ dest.resize(src.size() * 2);
+ char* append_ptr = &dest[0];
+
+ for (i = 0; i < src.size(); i++) {
+ *append_ptr++ = symbol[(src[i] & 0xf0) >> 4];
+ *append_ptr++ = symbol[src[i] & 0x0f];
+ }
+
+ return dest;
+}
+
+void Indent(google::protobuf::io::Printer* printer) {
+ printer->Indent();
+ printer->Indent();
+}
+void Outdent(google::protobuf::io::Printer* printer) {
+ printer->Outdent();
+ printer->Outdent();
+}
+
+void GenerateField(const google::protobuf::FieldDescriptor* field,
+ google::protobuf::io::Printer* printer, bool is_descriptor) {
+ if (field->is_repeated()) {
+ printer->Print(
+ "private $@name@;\n",
+ "name", field->name());
+ } else if (field->containing_oneof()) {
+ // Oneof fields are handled by GenerateOneofField.
+ return;
+ } else {
+ printer->Print(
+ "private $@name@ = @default@;\n",
+ "name", field->name(),
+ "default", DefaultForField(field));
+ }
+
+ if (is_descriptor) {
+ printer->Print(
+ "private $has_@name@ = false;\n",
+ "name", field->name());
+ }
+}
+
+void GenerateOneofField(const google::protobuf::OneofDescriptor* oneof,
+ google::protobuf::io::Printer* printer) {
+ // Oneof property needs to be protected in order to be accessed by parent
+ // class in implementation.
+ printer->Print(
+ "protected $@name@;\n",
+ "name", oneof->name());
+}
+
+void GenerateFieldAccessor(const google::protobuf::FieldDescriptor* field,
+ bool is_descriptor,
+ google::protobuf::io::Printer* printer) {
+ const OneofDescriptor* oneof = field->containing_oneof();
+
+ // Generate getter.
+ if (oneof != NULL) {
+ printer->Print(
+ "public function get@camel_name@()\n"
+ "{\n"
+ " return $this->readOneof(@number@);\n"
+ "}\n\n",
+ "camel_name", UnderscoresToCamelCase(field->name(), true),
+ "number", IntToString(field->number()));
+ } else {
+ printer->Print(
+ "public function get@camel_name@()\n"
+ "{\n"
+ " return $this->@name@;\n"
+ "}\n\n",
+ "camel_name", UnderscoresToCamelCase(field->name(), true), "name",
+ field->name());
+ }
+
+ // Generate setter.
+ printer->Print(
+ "public function set@camel_name@(@var@)\n"
+ "{\n",
+ "camel_name", UnderscoresToCamelCase(field->name(), true),
+ "var", (field->is_repeated() ||
+ field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
+ "&$var": "$var");
+
+ Indent(printer);
+
+ // Type check.
+ if (field->is_map()) {
+ } else if (field->is_repeated()) {
+ printer->Print(
+ "GPBUtil::checkRepeatedField($var, GPBType::@type@",
+ "type", ToUpper(field->type_name()));
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer->Print(
+ ", \\@class_name@);\n",
+ "class_name",
+ MessageName(field->message_type(), is_descriptor) + "::class");
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ printer->Print(
+ ", @class_name@);\n",
+ "class_name",
+ EnumName(field->enum_type(), is_descriptor) + "::class");
+ } else {
+ printer->Print(");\n");
+ }
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer->Print(
+ "GPBUtil::checkMessage($var, \\@class_name@::class);\n",
+ "class_name", MessageName(field->message_type(), is_descriptor));
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ printer->Print(
+ "GPBUtil::checkEnum($var, \\@class_name@::class);\n",
+ "class_name", EnumName(field->enum_type(), is_descriptor));
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ printer->Print(
+ "GPBUtil::checkString($var, @utf8@);\n",
+ "utf8",
+ field->type() == FieldDescriptor::TYPE_STRING ? "True": "False");
+ } else {
+ printer->Print(
+ "GPBUtil::check@type@($var);\n",
+ "type", UnderscoresToCamelCase(field->cpp_type_name(), true));
+ }
+
+ if (oneof != NULL) {
+ printer->Print(
+ "$this->writeOneof(@number@, $var);\n",
+ "number", IntToString(field->number()));
+ } else {
+ printer->Print(
+ "$this->@name@ = $var;\n",
+ "name", field->name());
+ }
+
+ // Set has bit for proto2 only.
+ if (is_descriptor) {
+ printer->Print(
+ "$this->has_@field_name@ = true;\n",
+ "field_name", field->name());
+ }
+
+ Outdent(printer);
+
+ printer->Print(
+ "}\n\n");
+
+ // Generate has method for proto2 only.
+ if (is_descriptor) {
+ printer->Print(
+ "public function has@camel_name@()\n"
+ "{\n"
+ " return $this->has_@field_name@;\n"
+ "}\n\n",
+ "camel_name", UnderscoresToCamelCase(field->name(), true),
+ "field_name", field->name());
+ }
+}
+
+void GenerateRepeatedFieldDecode(
+ const google::protobuf::FieldDescriptor* field,
+ google::protobuf::io::Printer* printer) {
+ printer->Print(
+ "if ($input->read@cap_wire_type@($var)) return False;\n"
+ "$this->get@cap_field_name@() []= $var;\n",
+ "cap_field_name", UnderscoresToCamelCase(field->name(), true),
+ "cap_wire_type", UnderscoresToCamelCase(field->type_name(), true));
+}
+
+void GeneratePrimitiveFieldDecode(
+ const google::protobuf::FieldDescriptor* field,
+ google::protobuf::io::Printer* printer) {
+ printer->Print(
+ "if ($input->read@cap_wire_type@($var)) return False;\n"
+ "$this->set@cap_field_name@($var);\n",
+ "cap_field_name", UnderscoresToCamelCase(field->name(), true),
+ "cap_wire_type", UnderscoresToCamelCase(field->type_name(), true));
+}
+
+void GenerateFieldDecode(const google::protobuf::FieldDescriptor* field,
+ google::protobuf::io::Printer* printer) {
+ printer->Print(
+ "case @number@:\n",
+ "number", IntToString(field->number()));
+ Indent(printer);
+
+ if (field->is_repeated()) {
+ GenerateRepeatedFieldDecode(field, printer);
+ } else {
+ GeneratePrimitiveFieldDecode(field, printer);
+ }
+
+ printer->Print(
+ "break;\n");
+ Outdent(printer);
+}
+
+void GenerateMessage(const string& name_prefix,
+ const google::protobuf::Descriptor* message,
+ bool is_descriptor,
+ google::protobuf::io::Printer* printer) {
+ // Don't generate MapEntry messages -- we use the PHP extension's native
+ // support for map fields instead.
+ if (message->options().map_entry()) {
+ return;
+ }
+
+ string message_name = name_prefix.empty()?
+ message->name() : name_prefix + "_" + message->name();
+
+ printer->Print(
+ "class @name@ extends \\Google\\Protobuf\\Internal\\Message\n"
+ "{\n",
+ "name", message_name);
+ Indent(printer);
+
+ // Field and oneof definitions.
+ for (int i = 0; i < message->field_count(); i++) {
+ const FieldDescriptor* field = message->field(i);
+ GenerateField(field, printer, is_descriptor);
+ }
+ for (int i = 0; i < message->oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof = message->oneof_decl(i);
+ GenerateOneofField(oneof, printer);
+ }
+ printer->Print("\n");
+
+ // Field and oneof accessors.
+ for (int i = 0; i < message->field_count(); i++) {
+ const FieldDescriptor* field = message->field(i);
+ GenerateFieldAccessor(field, is_descriptor, printer);
+ }
+ for (int i = 0; i < message->oneof_decl_count(); i++) {
+ const google::protobuf::OneofDescriptor* oneof = message->oneof_decl(i);
+ printer->Print(
+ "public function get@camel_name@()\n"
+ "{\n"
+ " return $this->@name@;\n"
+ "}\n\n",
+ "camel_name", UnderscoresToCamelCase(oneof->name(), true), "name",
+ oneof->name());
+ }
+
+ Outdent(printer);
+ printer->Print("}\n\n");
+
+ // Nested messages and enums.
+ for (int i = 0; i < message->nested_type_count(); i++) {
+ GenerateMessage(message_name, message->nested_type(i), is_descriptor,
+ printer);
+ }
+ for (int i = 0; i < message->enum_type_count(); i++) {
+ GenerateEnum(message->enum_type(i), printer);
+ }
+}
+
+void GenerateEnumToPool(const google::protobuf::EnumDescriptor* en,
+ bool is_descriptor,
+ google::protobuf::io::Printer* printer) {
+ printer->Print(
+ "$pool->addEnum('@name@', @class_name@::class)\n",
+ "name", EnumFullName(en, is_descriptor),
+ "class_name", en->name());
+ Indent(printer);
+
+ for (int i = 0; i < en->value_count(); i++) {
+ const EnumValueDescriptor* value = en->value(i);
+ printer->Print(
+ "->value(\"@name@\", @number@)\n",
+ "name", value->name(),
+ "number", IntToString(value->number()));
+ }
+ printer->Print("->finalizeToPool();\n\n");
+ Outdent(printer);
+}
+
+void GenerateMessageToPool(const string& name_prefix,
+ const google::protobuf::Descriptor* message,
+ bool is_descriptor,
+ google::protobuf::io::Printer* printer) {
+ // Don't generate MapEntry messages -- we use the PHP extension's native
+ // support for map fields instead.
+ if (message->options().map_entry()) {
+ return;
+ }
+ string class_name = name_prefix.empty()?
+ message->name() : name_prefix + "_" + message->name();
+
+ printer->Print(
+ "$pool->addMessage('@message@', @class_name@::class)\n",
+ "message", MessageFullName(message, is_descriptor),
+ "class_name", class_name);
+
+ Indent(printer);
+
+ for (int i = 0; i < message->field_count(); i++) {
+ const FieldDescriptor* field = message->field(i);
+ if (field->is_map()) {
+ const FieldDescriptor* key =
+ field->message_type()->FindFieldByName("key");
+ const FieldDescriptor* val =
+ field->message_type()->FindFieldByName("value");
+ printer->Print(
+ "->map('@field@', GPBType::@key@, "
+ "GPBType::@value@, @number@@other@)\n",
+ "field", field->name(),
+ "key", ToUpper(key->type_name()),
+ "value", ToUpper(val->type_name()),
+ "number", SimpleItoa(field->number()),
+ "other", EnumOrMessageSuffix(val, is_descriptor));
+ } else if (!field->containing_oneof()) {
+ printer->Print(
+ "->@label@('@field@', GPBType::@type@, @number@@other@)\n",
+ "field", field->name(),
+ "label", LabelForField(field),
+ "type", ToUpper(field->type_name()),
+ "number", SimpleItoa(field->number()),
+ "other", EnumOrMessageSuffix(field, is_descriptor));
+ }
+ }
+
+ // oneofs.
+ for (int i = 0; i < message->oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof = message->oneof_decl(i);
+ printer->Print("->oneof(@name@)\n",
+ "name", oneof->name());
+ Indent(printer);
+ for (int index = 0; index < oneof->field_count(); index++) {
+ const FieldDescriptor* field = oneof->field(index);
+ printer->Print(
+ "->value('@field@', GPBType::@type@, @number@@other@)\n",
+ "field", field->name(),
+ "type", ToUpper(field->type_name()),
+ "number", SimpleItoa(field->number()),
+ "other", EnumOrMessageSuffix(field, is_descriptor));
+ }
+ printer->Print("->finish()\n");
+ Outdent(printer);
+ }
+
+ printer->Print(
+ "->finalizeToPool();\n");
+
+ Outdent(printer);
+
+ printer->Print(
+ "\n");
+
+ for (int i = 0; i < message->nested_type_count(); i++) {
+ GenerateMessageToPool(class_name, message->nested_type(i), is_descriptor,
+ printer);
+ }
+ for (int i = 0; i < message->enum_type_count(); i++) {
+ GenerateEnumToPool(message->enum_type(i), is_descriptor, printer);
+ }
+}
+
+void GenerateAddFileToPool(const google::protobuf::FileDescriptor* file,
+ bool is_descriptor,
+ google::protobuf::io::Printer* printer) {
+ if (is_descriptor) {
+ printer->Print("$pool = DescriptorPool::getGeneratedPool();\n\n");
+
+ for (int i = 0; i < file->message_type_count(); i++) {
+ GenerateMessageToPool("", file->message_type(i), is_descriptor, printer);
+ }
+ for (int i = 0; i < file->enum_type_count(); i++) {
+ GenerateEnumToPool(file->enum_type(i), is_descriptor, printer);
+ }
+
+ printer->Print(
+ "$pool->finish();\n");
+ } else {
+ // Add messages and enums to descriptor pool.
+ printer->Print("$pool = DescriptorPool::getGeneratedPool();\n\n");
+
+ FileDescriptorSet files;
+ FileDescriptorProto* file_proto = files.add_file();
+ file->CopyTo(file_proto);
+ string files_data;
+ files.SerializeToString(&files_data);
+
+ printer->Print("$pool->internalAddGeneratedFile(hex2bin(\n");
+ Indent(printer);
+
+ // Only write 30 bytes per line.
+ static const int kBytesPerLine = 30;
+ for (int i = 0; i < files_data.size(); i += kBytesPerLine) {
+ printer->Print(
+ "\"@data@\"@dot@\n",
+ "data", BinaryToHex(files_data.substr(i, kBytesPerLine)),
+ "dot", i + kBytesPerLine < files_data.size() ? " ." : "");
+ }
+
+ Outdent(printer);
+ printer->Print(
+ "));\n\n");
+ }
+
+}
+
+void GenerateEnum(const google::protobuf::EnumDescriptor* en,
+ google::protobuf::io::Printer* printer) {
+ printer->Print(
+ "class @name@\n"
+ "{\n",
+ "name", EnumClassName(en));
+ Indent(printer);
+
+ for (int i = 0; i < en->value_count(); i++) {
+ const EnumValueDescriptor* value = en->value(i);
+ printer->Print("const @name@ = @number@;\n",
+ "name", value->name(),
+ "number", IntToString(value->number()));
+ }
+ Outdent(printer);
+ printer->Print("}\n\n");
+}
+
+void GenerateUseDeclaration(bool is_descriptor,
+ google::protobuf::io::Printer* printer) {
+ if (!is_descriptor) {
+ printer->Print(
+ "use Google\\Protobuf\\Internal\\DescriptorPool;\n"
+ "use Google\\Protobuf\\Internal\\GPBType;\n"
+ "use Google\\Protobuf\\Internal\\RepeatedField;\n"
+ "use Google\\Protobuf\\Internal\\GPBUtil;\n\n");
+ } else {
+ printer->Print(
+ "use Google\\Protobuf\\Internal\\DescriptorPool;\n"
+ "use Google\\Protobuf\\Internal\\GPBType;\n"
+ "use Google\\Protobuf\\Internal\\GPBWire;\n"
+ "use Google\\Protobuf\\Internal\\RepeatedField;\n"
+ "use Google\\Protobuf\\Internal\\InputStream;\n\n"
+ "use Google\\Protobuf\\Internal\\GPBUtil;\n\n");
+ }
+}
+
+void GenerateFile(const google::protobuf::FileDescriptor* file,
+ bool is_descriptor, google::protobuf::io::Printer* printer) {
+ printer->Print(
+ "<?php\n"
+ "# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "# source: @filename@\n"
+ "\n",
+ "filename", file->name());
+ if (!file->package().empty()) {
+ printer->Print("namespace @name@;\n\n",
+ "name", PhpName(file->package(), is_descriptor));
+ }
+
+ for (int i = 0; i < file->dependency_count(); i++) {
+ const std::string& name = file->dependency(i)->name();
+ printer->Print("require_once('@name@');\n", "name",
+ GeneratedFileName(name, is_descriptor));
+ }
+
+ GenerateUseDeclaration(is_descriptor, printer);
+
+ for (int i = 0; i < file->message_type_count(); i++) {
+ GenerateMessage("", file->message_type(i), is_descriptor, printer);
+ }
+ for (int i = 0; i < file->enum_type_count(); i++) {
+ GenerateEnum(file->enum_type(i), printer);
+ }
+
+ GenerateAddFileToPool(file, is_descriptor, printer);
+}
+
+bool Generator::Generate(
+ const FileDescriptor* file,
+ const string& parameter,
+ GeneratorContext* generator_context,
+ string* error) const {
+ bool is_descriptor = parameter == "internal";
+
+ if (is_descriptor && file->name() != kDescriptorFile) {
+ *error =
+ "Can only generate PHP code for google/protobuf/descriptor.proto.\n";
+ return false;
+ }
+
+ if (!is_descriptor && file->syntax() != FileDescriptor::SYNTAX_PROTO3) {
+ *error =
+ "Can only generate PHP code for proto3 .proto files.\n"
+ "Please add 'syntax = \"proto3\";' to the top of your .proto file.\n";
+ return false;
+ }
+
+ std::string filename = GeneratedFileName(file->name(), is_descriptor);
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(filename));
+ io::Printer printer(output.get(), '@');
+
+ GenerateFile(file, is_descriptor, &printer);
+
+ return true;
+}
+
+} // namespace php
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/php/php_generator.h b/src/google/protobuf/compiler/php/php_generator.h
new file mode 100644
index 00000000..ce2b000a
--- /dev/null
+++ b/src/google/protobuf/compiler/php/php_generator.h
@@ -0,0 +1,57 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__
+
+#include <google/protobuf/compiler/code_generator.h>
+
+#include <string>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace php {
+
+class LIBPROTOC_EXPORT Generator
+ : public google::protobuf::compiler::CodeGenerator {
+ virtual bool Generate(
+ const FileDescriptor* file,
+ const string& parameter,
+ GeneratorContext* generator_context,
+ string* error) const;
+};
+
+} // namespace php
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__