Compare commits

..

No commits in common. "master" and "xiaofeng" have entirely different histories.

88 changed files with 1462 additions and 3301 deletions

3
.gitignore vendored
View file

@ -65,9 +65,6 @@ src/js_embed
src/protoc
src/unittest_proto_middleman
# vim generated
*.swp
# Generated test scaffolding
src/no_warning_test.cc
src/no-warning-test

View file

@ -32,7 +32,6 @@ env:
- CONFIG=ruby22
- CONFIG=jruby
- CONFIG=php5.6_mac
- CONFIG=php7.0_mac
matrix:
exclude:
# It's nontrivial to programmatically install a new JDK from the command

View file

@ -1,111 +1,3 @@
2017-04-05 version 3.3.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
Planned Future Changes
* There are some changes that are not included in this release but are
planned for the near future:
- Preserve unknown fields in proto3: please read this doc:
https://docs.google.com/document/d/1KMRX-G91Aa-Y2FkEaHeeviLRRNblgIahbsk4wA14gRk/view
for the timeline and follow up this github issue:
https://github.com/google/protobuf/issues/272
for discussion.
- Make C++ implementation C++11 only: we plan to require C++11 to build
protobuf code starting from 3.4.0 or 3.5.0 release. Please join this
github issue:
https://github.com/google/protobuf/issues/2780
to provide your feedback.
C++
* Fixed map fields serialization of DynamicMessage to correctly serialize
both key and value regardless of their presence.
* Parser now rejects field number 0 correctly.
* New API Message::SpaceUsedLong() thats equivalent to
Message::SpaceUsed() but returns the value in size_t.
* JSON support
- New flag always_print_enums_as_ints in JsonPrintOptions.
- New flag preserve_proto_field_names in JsonPrintOptions. It will instruct
the JSON printer to use the original field name declared in the .proto
file instead of converting them to lowerCamelCase when printing JSON.
- JsonPrintOptions.always_print_primtive_fields now works for oneof message
fields.
- Fixed a bug that doesnt allow different fields to set the same json_name
value.
- Fixed a performance bug that causes excessive memory copy when printing
large messages.
* Various performance optimizations.
Java
* Map field setters eagerly validate inputs and throw NullPointerExceptions
as appropriate.
* Added ByteBuffer overloads to the generated parsing methods and the Parser
interface.
* proto3 enum's getNumber() method now throws on UNRECOGNIZED values.
* Output of JsonFormat is now locale independent.
Python
* Added FindServiceByName() in the pure-Python DescriptorPool. This works only
for descriptors added with DescriptorPool.Add(). Generated descriptor_pool
does not support this yet.
* Added a descriptor_pool parameter for parsing Any in text_format.Parse().
* descriptor_pool.FindFileContainingSymbol() now is able to find nested
extensions.
* Extending empty [] to repeated field now sets parent message presence.
PHP
* Added file option php_class_prefix. The prefix will be prepended to all
generated classes defined in the file.
* When encoding, negative int32 values are sign-extended to int64.
* Repeated/Map field setter accepts a regular PHP array. Type checking is
done on the array elements.
* encode/decode are renamed to serializeToString/mergeFromString.
* Added mergeFrom, clear method on Message.
* Fixed a bug that oneof accessor didnt return the field name that is
actually set.
* C extension now works with php7.
* This is the first GA release of PHP. We guarantee that old generated code
can always work with new runtime and new generated code.
Objective-C
* Fixed help for GPBTimestamp for dates before the epoch that contain
fractional seconds.
* Added GPBMessageDropUnknownFieldsRecursively() to remove unknowns from a
message and any sub messages.
* Addressed a threading race in extension registration/lookup.
* Increased the max message parsing depth to 100 to match the other languages.
* Removed some use of dispatch_once in favor of atomic compare/set since it
needs to be heap based.
* Fixes for new Xcode 8.3 warnings.
C#
* Fixed MapField.Values.CopyTo, which would throw an exception unnecessarily
if provided exactly the right size of array to copy to.
* Fixed enum JSON formatting when multiple names mapped to the same numeric
value.
* Added JSON formatting option to format enums as integers.
* Modified RepeatedField<T> to implement IReadOnlyList<T>.
* Introduced the start of custom option handling; it's not as pleasant as it
might be, but the information is at least present. We expect to extend code
generation to improve this in the future.
* Introduced ByteString.FromStream and ByteString.FromStreamAsync to
efficiently create a ByteString from a stream.
* Added whole-message deprecation, which decorates the class with [Obsolete].
Ruby
* Fixed Message#to_h for messages with map fields.
* Fixed memcpy() in binary gems to work for old glibc, without breaking the
build for non-glibc libcs like musl.
Javascript
* Added compatibility tests for version 3.0.0.
* Added conformance tests.
* Fixed serialization of extensions: we need to emit a value even if it is
falsy (like the number 0).
* Use closurebuilder.py in favor of calcdeps.py for compiling JavaScript.
2017-01-23 version 3.2.0 (C++/Java/Python/PHP/Ruby/Objective-C/C#/JavaScript/Lite)
General
* Added protoc version number to protoc plugin protocol. It can be used by

View file

@ -646,7 +646,6 @@ php_EXTRA_DIST= \
php/src/Google/Protobuf/Internal/EnumBuilderContext.php \
php/src/Google/Protobuf/Internal/GPBUtil.php \
php/src/Google/Protobuf/Internal/FieldOptions_CType.php \
php/src/Google/Protobuf/Internal/GPBDecodeException.php \
php/src/Google/Protobuf/descriptor.php \
php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php \
php/tests/array_test.php \
@ -657,7 +656,6 @@ php_EXTRA_DIST= \
php/tests/map_field_test.php \
php/tests/memory_leak_test.php \
php/tests/php_implementation_test.php \
php/tests/proto/test_import_descriptor_proto.proto \
php/tests/proto/test_include.proto \
php/tests/proto/test.proto \
php/tests/proto/test_prefix.proto \

View file

@ -5,7 +5,7 @@
# dependent projects use the :git notation to refer to the library.
Pod::Spec.new do |s|
s.name = 'Protobuf'
s.version = '3.3.0'
s.version = '3.2.0'
s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.'
s.homepage = 'https://github.com/google/protobuf'
s.license = '3-Clause BSD License'

View file

@ -17,7 +17,7 @@ AC_PREREQ(2.59)
# In the SVN trunk, the version should always be the next anticipated release
# version with the "-pre" suffix. (We used to use "-SNAPSHOT" but this pushed
# the size of one file name in the dist tarfile over the 99-char limit.)
AC_INIT([Protocol Buffers],[3.3.0],[protobuf@googlegroups.com],[protobuf])
AC_INIT([Protocol Buffers],[3.2.0],[protobuf@googlegroups.com],[protobuf])
AM_MAINTAINER_MODE([enable])

View file

@ -32,6 +32,7 @@ Recommended.JsonInput.StringFieldSingleQuoteValue
Recommended.JsonInput.StringFieldSurrogateInWrongOrder
Recommended.JsonInput.StringFieldUnpairedHighSurrogate
Recommended.JsonInput.StringFieldUnpairedLowSurrogate
Recommended.JsonInput.StringFieldUppercaseEscapeLetter
Recommended.JsonInput.Uint32MapFieldKeyNotQuoted
Recommended.JsonInput.Uint64MapFieldKeyNotQuoted
Required.JsonInput.EnumFieldNotQuoted

View file

@ -1,6 +1,4 @@
# All tests currently passing.
#
# JSON input or output tests are skipped (in conformance_objc.m) as mobile
# platforms don't support JSON wire format to avoid code bloat.
Required.ProtobufInput.IllegalZeroFieldNum_Case_0
Required.ProtobufInput.IllegalZeroFieldNum_Case_1
Required.ProtobufInput.IllegalZeroFieldNum_Case_2
Required.ProtobufInput.IllegalZeroFieldNum_Case_3

View file

@ -8,7 +8,6 @@ Recommended.JsonInput.DurationHas6FractionalDigits.Validator
Recommended.JsonInput.DurationHas9FractionalDigits.Validator
Recommended.JsonInput.DurationHasZeroFractionalDigit.Validator
Recommended.JsonInput.Int64FieldBeString.Validator
Recommended.JsonInput.MapFieldValueIsNull
Recommended.JsonInput.OneofZeroBool.JsonOutput
Recommended.JsonInput.OneofZeroBool.ProtobufOutput
Recommended.JsonInput.OneofZeroBytes.JsonOutput
@ -25,8 +24,6 @@ Recommended.JsonInput.OneofZeroUint32.JsonOutput
Recommended.JsonInput.OneofZeroUint32.ProtobufOutput
Recommended.JsonInput.OneofZeroUint64.JsonOutput
Recommended.JsonInput.OneofZeroUint64.ProtobufOutput
Recommended.JsonInput.RepeatedFieldMessageElementIsNull
Recommended.JsonInput.RepeatedFieldPrimitiveElementIsNull
Recommended.JsonInput.StringEndsWithEscapeChar
Recommended.JsonInput.StringFieldSurrogateInWrongOrder
Recommended.JsonInput.StringFieldUnpairedHighSurrogate
@ -130,12 +127,24 @@ Required.JsonInput.Int32FieldStringValue.JsonOutput
Required.JsonInput.Int32FieldStringValue.ProtobufOutput
Required.JsonInput.Int32FieldStringValueEscaped.JsonOutput
Required.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput
Required.JsonInput.Int32MapEscapedKey.JsonOutput
Required.JsonInput.Int32MapEscapedKey.ProtobufOutput
Required.JsonInput.Int32MapField.JsonOutput
Required.JsonInput.Int32MapField.ProtobufOutput
Required.JsonInput.Int64FieldMaxValue.JsonOutput
Required.JsonInput.Int64FieldMaxValue.ProtobufOutput
Required.JsonInput.Int64FieldMinValue.JsonOutput
Required.JsonInput.Int64FieldMinValue.ProtobufOutput
Required.JsonInput.Int64MapEscapedKey.JsonOutput
Required.JsonInput.Int64MapEscapedKey.ProtobufOutput
Required.JsonInput.Int64MapField.JsonOutput
Required.JsonInput.Int64MapField.ProtobufOutput
Required.JsonInput.MessageField.JsonOutput
Required.JsonInput.MessageField.ProtobufOutput
Required.JsonInput.MessageMapField.JsonOutput
Required.JsonInput.MessageMapField.ProtobufOutput
Required.JsonInput.MessageRepeatedField.JsonOutput
Required.JsonInput.MessageRepeatedField.ProtobufOutput
Required.JsonInput.OptionalBoolWrapper.JsonOutput
Required.JsonInput.OptionalBoolWrapper.ProtobufOutput
Required.JsonInput.OptionalBytesWrapper.JsonOutput
@ -156,13 +165,14 @@ Required.JsonInput.OptionalUint64Wrapper.JsonOutput
Required.JsonInput.OptionalUint64Wrapper.ProtobufOutput
Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
Required.JsonInput.PrimitiveRepeatedField.JsonOutput
Required.JsonInput.PrimitiveRepeatedField.ProtobufOutput
Required.JsonInput.RepeatedBoolWrapper.JsonOutput
Required.JsonInput.RepeatedBoolWrapper.ProtobufOutput
Required.JsonInput.RepeatedBytesWrapper.JsonOutput
Required.JsonInput.RepeatedBytesWrapper.ProtobufOutput
Required.JsonInput.RepeatedDoubleWrapper.JsonOutput
Required.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotInt
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
Required.JsonInput.RepeatedFloatWrapper.JsonOutput
Required.JsonInput.RepeatedFloatWrapper.ProtobufOutput
@ -176,15 +186,9 @@ Required.JsonInput.RepeatedUint32Wrapper.JsonOutput
Required.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
Required.JsonInput.RepeatedUint64Wrapper.JsonOutput
Required.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
Required.JsonInput.StringFieldEscape.JsonOutput
Required.JsonInput.StringFieldEscape.ProtobufOutput
Required.JsonInput.StringFieldNotAString
Required.JsonInput.StringFieldSurrogatePair.JsonOutput
Required.JsonInput.StringFieldSurrogatePair.ProtobufOutput
Required.JsonInput.StringFieldUnicodeEscape.JsonOutput
Required.JsonInput.StringFieldUnicodeEscape.ProtobufOutput
Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOutput
Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.ProtobufOutput
Required.JsonInput.Struct.JsonOutput
Required.JsonInput.Struct.ProtobufOutput
Required.JsonInput.TimestampMaxValue.JsonOutput
@ -199,8 +203,12 @@ Required.JsonInput.TimestampWithPositiveOffset.JsonOutput
Required.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
Required.JsonInput.Uint32FieldMaxFloatValue.JsonOutput
Required.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
Required.JsonInput.Uint32MapField.JsonOutput
Required.JsonInput.Uint32MapField.ProtobufOutput
Required.JsonInput.Uint64FieldMaxValue.JsonOutput
Required.JsonInput.Uint64FieldMaxValue.ProtobufOutput
Required.JsonInput.Uint64MapField.JsonOutput
Required.JsonInput.Uint64MapField.ProtobufOutput
Required.JsonInput.ValueAcceptBool.JsonOutput
Required.JsonInput.ValueAcceptBool.ProtobufOutput
Required.JsonInput.ValueAcceptFloat.JsonOutput

View file

@ -15,3 +15,6 @@ Required.ProtobufInput.IllegalZeroFieldNum_Case_0
Required.ProtobufInput.IllegalZeroFieldNum_Case_1
Required.ProtobufInput.IllegalZeroFieldNum_Case_2
Required.ProtobufInput.IllegalZeroFieldNum_Case_3
Required.ProtobufInput.RepeatedScalarSelectsLast.INT32.JsonOutput
Required.ProtobufInput.ValidDataRepeated.INT32.JsonOutput
Required.ProtobufInput.ValidDataRepeated.INT32.ProtobufOutput

View file

@ -5,7 +5,7 @@
<title>Google Protocol Buffers tools</title>
<summary>Tools for Protocol Buffers - Google's data interchange format.</summary>
<description>See project site for more info.</description>
<version>3.3.0</version>
<version>3.2.0</version>
<authors>Google Inc.</authors>
<owners>protobuf-packages</owners>
<licenseUrl>https://github.com/google/protobuf/blob/master/LICENSE</licenseUrl>

View file

@ -1,5 +1,5 @@
{
"version": "3.3.0",
"version": "3.2.0",
"title": "Google Protocol Buffers",
"description": "See project site for more info.",
"authors": [ "Google Inc." ],

View file

@ -6,7 +6,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.3.0</version>
<version>3.2.0</version>
</parent>
<artifactId>protobuf-java</artifactId>

View file

@ -11,7 +11,7 @@
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.3.0</version>
<version>3.2.0</version>
<packaging>pom</packaging>
<name>Protocol Buffers [Parent]</name>
@ -84,13 +84,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
<scope>test</scope>
<version>0.32</version>
<version>18.0</version>
</dependency>
</dependencies>
</dependencyManagement>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId>
<version>3.3.0</version>
<version>3.2.0</version>
</parent>
<artifactId>protobuf-java-util</artifactId>

View file

@ -12,5 +12,5 @@
export DOCKERFILE_DIR=jenkins/docker32
export DOCKER_RUN_SCRIPT=jenkins/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="php_all"
export TEST_SET="php_all_32"
./jenkins/build_and_run_docker.sh

View file

@ -129,7 +129,7 @@ ENV MVN mvn --batch-mode
RUN cd /tmp && \
git clone https://github.com/google/protobuf.git && \
cd protobuf && \
git reset --hard c2b3b3e04e7a023efe06f2107705b45428847800 && \
git reset 057a2851e41e9a0ad95d2cd76aba8bc39ba2e6e3 && \
./autogen.sh && \
./configure && \
make -j4 && \
@ -147,23 +147,6 @@ RUN cd php-5.5.38 && ./configure --enable-maintainer-zts --prefix=/usr/local/php
make && make install && cd ..
RUN cd php-5.5.38 && make clean && ./configure --prefix=/usr/local/php-5.5 && \
make && make install && cd ..
RUN wget http://am1.php.net/get/php-5.6.30.tar.bz2/from/this/mirror
RUN mv mirror php-5.6.30.tar.bz2
RUN tar -xvf php-5.6.30.tar.bz2
RUN cd php-5.6.30 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-5.6-zts && \
make && make install && cd ..
RUN cd php-5.6.30 && make clean && ./configure --prefix=/usr/local/php-5.6 && \
make && make install && cd ..
RUN wget http://am1.php.net/get/php-7.0.18.tar.bz2/from/this/mirror
RUN mv mirror php-7.0.18.tar.bz2
RUN tar -xvf php-7.0.18.tar.bz2
RUN cd php-7.0.18 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-7.0-zts && \
make && make install && cd ..
RUN cd php-7.0.18 && make clean && ./configure --prefix=/usr/local/php-7.0 && \
make && make install && cd ..
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN php composer-setup.php
RUN mv composer.phar /usr/bin/composer
@ -174,21 +157,21 @@ RUN cd /tmp && \
rm -rf protobuf && \
git clone https://github.com/google/protobuf.git && \
cd protobuf && \
git reset --hard 6b27c1f981a9a93918e4039f236ead27165a8e91 && \
git reset 46ae90dc5e145b12fffa7e053a908a9f3e066286 && \
cd php && \
ln -sfn /usr/local/php-5.5/bin/php /usr/bin/php && \
ln -sfn /usr/local/php-5.5/bin/php-config /usr/bin/php-config && \
ln -sfn /usr/local/php-5.5/bin/phpize /usr/bin/phpize && \
composer install && \
mv vendor /usr/local/vendor-5.5 && \
ln -sfn /usr/local/php-5.6/bin/php /usr/bin/php && \
ln -sfn /usr/local/php-5.6/bin/php-config /usr/bin/php-config && \
ln -sfn /usr/local/php-5.6/bin/phpize /usr/bin/phpize && \
ln -sfn /usr/bin/php5.6 /usr/bin/php && \
ln -sfn /usr/bin/php-config5.6 /usr/bin/php-config && \
ln -sfn /usr/bin/phpize5.6 /usr/bin/phpize && \
composer install && \
mv vendor /usr/local/vendor-5.6 && \
ln -sfn /usr/local/php-7.0/bin/php /usr/bin/php && \
ln -sfn /usr/local/php-7.0/bin/php-config /usr/bin/php-config && \
ln -sfn /usr/local/php-7.0/bin/phpize /usr/bin/phpize && \
ln -sfn /usr/bin/php7.0 /usr/bin/php && \
ln -sfn /usr/bin/php-config7.0 /usr/bin/php-config && \
ln -sfn /usr/bin/phpize7.0 /usr/bin/phpize && \
composer install && \
mv vendor /usr/local/vendor-7.0

View file

@ -64,7 +64,7 @@ RUN php -r "unlink('composer-setup.php');"
RUN cd /tmp && \
git clone https://github.com/google/protobuf.git && \
cd protobuf/php && \
git reset --hard 6b27c1f981a9a93918e4039f236ead27165a8e91 && \
git reset 6b27c1f981a9a93918e4039f236ead27165a8e91 && \
ln -sfn /usr/bin/php5.5 /usr/bin/php && \
ln -sfn /usr/bin/php-config5.5 /usr/bin/php-config && \
ln -sfn /usr/bin/phpize5.5 /usr/bin/phpize && \
@ -80,31 +80,14 @@ RUN cd /tmp && \
ln -sfn /usr/bin/phpize7.0 /usr/bin/phpize && \
composer install && \
mv vendor /usr/local/vendor-7.0
RUN wget http://am1.php.net/get/php-5.5.38.tar.bz2/from/this/mirror
RUN mv mirror php-5.5.38.tar.bz2
RUN tar -xvf php-5.5.38.tar.bz2
RUN cd php-5.5.38 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-5.5-zts && \
make && make install && make clean && cd ..
RUN cd php-5.5.38 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-5.5 && \
RUN cd php-5.5.38 && ./configure --enable-bcmath --prefix=/usr/local/php-5.5-bc && \
make && make install && make clean && cd ..
RUN wget http://am1.php.net/get/php-5.6.30.tar.bz2/from/this/mirror
RUN mv mirror php-5.6.30.tar.bz2
RUN tar -xvf php-5.6.30.tar.bz2
RUN cd php-5.6.30 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-5.6-zts && \
make && make install && cd ..
RUN cd php-5.6.30 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-5.6 && \
make && make install && cd ..
RUN wget http://am1.php.net/get/php-7.0.18.tar.bz2/from/this/mirror
RUN mv mirror php-7.0.18.tar.bz2
RUN tar -xvf php-7.0.18.tar.bz2
RUN cd php-7.0.18 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-7.0-zts && \
make && make install && cd ..
RUN cd php-7.0.18 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-7.0 && \
make && make install && cd ..
##################
# Python dependencies

View file

@ -1,6 +1,6 @@
{
"name": "google-protobuf",
"version": "3.3.0",
"version": "3.2.0",
"description": "Protocol Buffers for JavaScript",
"main": "google-protobuf.js",
"files": [

View file

@ -69,20 +69,19 @@ static zend_function_entry repeated_field_iter_methods[] = {
// 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, CACHED_VALUE **table,
static HashTable *repeated_field_get_gc(zval *object, zval ***table,
int *n TSRMLS_DC);
#if PHP_MAJOR_VERSION < 7
static zend_object_value repeated_field_create(zend_class_entry *ce TSRMLS_DC);
static zend_object_value repeated_field_iter_create(zend_class_entry *ce TSRMLS_DC);
#else
static zend_object *repeated_field_create(zend_class_entry *ce TSRMLS_DC);
static zend_object *repeated_field_iter_create(zend_class_entry *ce TSRMLS_DC);
#endif
static void repeated_field_iter_free(void *object TSRMLS_DC);
// -----------------------------------------------------------------------------
// RepeatedField creation/desctruction
@ -91,91 +90,76 @@ static zend_object *repeated_field_iter_create(zend_class_entry *ce TSRMLS_DC);
zend_class_entry* repeated_field_type;
zend_class_entry* repeated_field_iter_type;
zend_object_handlers* repeated_field_handlers;
zend_object_handlers* repeated_field_iter_handlers;
// Define object free method.
PHP_PROTO_OBJECT_FREE_START(RepeatedField, repeated_field)
#if PHP_MAJOR_VERSION < 7
php_proto_zval_ptr_dtor(intern->array);
#else
php_proto_zval_ptr_dtor(&intern->array);
#endif
PHP_PROTO_OBJECT_FREE_END
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);
PHP_PROTO_OBJECT_DTOR_START(RepeatedField, repeated_field)
PHP_PROTO_OBJECT_DTOR_END
repeated_field_type = zend_register_internal_class(&class_type TSRMLS_CC);
repeated_field_type->create_object = repeated_field_create;
// Define object create method.
PHP_PROTO_OBJECT_CREATE_START(RepeatedField, repeated_field)
#if PHP_MAJOR_VERSION < 7
intern->array = NULL;
#endif
intern->type = 0;
intern->msg_ce = NULL;
PHP_PROTO_OBJECT_CREATE_END(RepeatedField, repeated_field)
zend_class_implements(repeated_field_type TSRMLS_CC, 3, spl_ce_ArrayAccess,
zend_ce_aggregate, spl_ce_Countable);
// Init class entry.
PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\RepeatedField",
RepeatedField, repeated_field)
zend_class_implements(repeated_field_type TSRMLS_CC, 3, spl_ce_ArrayAccess,
zend_ce_aggregate, spl_ce_Countable);
repeated_field_handlers->write_dimension = repeated_field_write_dimension;
repeated_field_handlers->get_gc = repeated_field_get_gc;
PHP_PROTO_INIT_CLASS_END
// Define array element free function.
#if PHP_MAJOR_VERSION < 7
static inline void php_proto_array_string_release(void *value) {
zval_ptr_dtor(value);
repeated_field_handlers = PEMALLOC(zend_object_handlers);
memcpy(repeated_field_handlers, zend_get_std_object_handlers(),
sizeof(zend_object_handlers));
repeated_field_handlers->write_dimension = repeated_field_write_dimension;
repeated_field_handlers->get_gc = repeated_field_get_gc;
}
static inline void php_proto_array_object_release(void *value) {
zval_ptr_dtor(value);
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 inline void php_proto_array_default_release(void *value) {
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);
}
#else
static inline void php_proto_array_string_release(zval *value) {
void* ptr = Z_PTR_P(value);
zend_string* object = *(zend_string**)ptr;
zend_string_release(object);
efree(ptr);
}
static inline void php_proto_array_object_release(zval *value) {
void* ptr = Z_PTR_P(value);
zend_object* object = *(zend_object**)ptr;
if(--GC_REFCOUNT(object) == 0) {
zend_objects_store_del(object);
}
efree(ptr);
}
static void php_proto_array_default_release(zval* value) {
void* ptr = Z_PTR_P(value);
efree(ptr);
}
#endif
static int repeated_field_array_init(zval *array, upb_fieldtype_t type,
uint size ZEND_FILE_LINE_DC) {
PHP_PROTO_ALLOC_ARRAY(array);
ALLOC_HASHTABLE(Z_ARRVAL_P(array));
switch (type) {
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
zend_hash_init(Z_ARRVAL_P(array), size, NULL,
php_proto_array_string_release, 0);
break;
case UPB_TYPE_MESSAGE:
zend_hash_init(Z_ARRVAL_P(array), size, NULL,
php_proto_array_object_release, 0);
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
break;
default:
zend_hash_init(Z_ARRVAL_P(array), size, NULL,
php_proto_array_default_release, 0);
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
// -----------------------------------------------------------------------------
@ -184,25 +168,23 @@ static void repeated_field_write_dimension(zval *object, zval *offset,
zval *value TSRMLS_DC) {
uint64_t index;
RepeatedField *intern = UNBOX(RepeatedField, object);
HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
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_by_array(intern->type, intern->msg_ce, memory,
value TSRMLS_CC)) {
if (!native_slot_set(intern->type, intern->msg_ce, memory, value TSRMLS_CC)) {
return;
}
if (!offset || Z_TYPE_P(offset) == IS_NULL) {
index = zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array));
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 %llu doesn't exist.\n",
(long long unsigned int)index);
zend_error(E_USER_ERROR, "Element at %llu doesn't exist.\n", index);
return;
}
} else {
@ -210,19 +192,15 @@ static void repeated_field_write_dimension(zval *object, zval *offset,
}
}
php_proto_zend_hash_index_update(ht, index, memory, size, NULL);
zend_hash_index_update(ht, index, memory, size, NULL);
}
#if PHP_MAJOR_VERSION < 7
static HashTable *repeated_field_get_gc(zval *object, zval ***table,
int *n TSRMLS_DC) {
#else
static HashTable *repeated_field_get_gc(zval *object, zval **table, int *n) {
#endif
*table = NULL;
*n = 0;
RepeatedField *intern = UNBOX(RepeatedField, object);
return PHP_PROTO_HASH_OF(intern->array);
RepeatedField *intern = zend_object_store_get_object(object TSRMLS_CC);
return HASH_OF(intern->array);
}
// -----------------------------------------------------------------------------
@ -230,10 +208,10 @@ static HashTable *repeated_field_get_gc(zval *object, zval **table, int *n) {
// -----------------------------------------------------------------------------
void *repeated_field_index_native(RepeatedField *intern, int index TSRMLS_DC) {
HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
HashTable *ht = HASH_OF(intern->array);
void *value;
if (php_proto_zend_hash_index_find(ht, index, (void **)&value) == FAILURE) {
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;
}
@ -241,37 +219,35 @@ void *repeated_field_index_native(RepeatedField *intern, int index TSRMLS_DC) {
return value;
}
void repeated_field_push_native(RepeatedField *intern, void *value) {
HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
void repeated_field_push_native(RepeatedField *intern, void *value TSRMLS_DC) {
HashTable *ht = HASH_OF(intern->array);
int size = native_slot_size(intern->type);
php_proto_zend_hash_next_index_insert(ht, (void **)value, size, NULL);
zend_hash_next_index_insert(ht, (void **)value, size, NULL);
}
void repeated_field_create_with_field(
zend_class_entry *ce, const upb_fielddef *field,
CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC) {
void repeated_field_create_with_field(zend_class_entry *ce,
const upb_fielddef *field,
zval **repeated_field TSRMLS_DC) {
upb_fieldtype_t type = upb_fielddef_type(field);
const zend_class_entry *msg_ce = field_type_class(field PHP_PROTO_TSRMLS_CC);
repeated_field_create_with_type(ce, type, msg_ce,
repeated_field PHP_PROTO_TSRMLS_CC);
const zend_class_entry *msg_ce = field_type_class(field TSRMLS_CC);
repeated_field_create_with_type(ce, type, msg_ce, repeated_field TSRMLS_CC);
}
void repeated_field_create_with_type(
zend_class_entry *ce, upb_fieldtype_t type, const zend_class_entry *msg_ce,
CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC) {
CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(CACHED_PTR_TO_ZVAL_PTR(repeated_field),
repeated_field_type);
void repeated_field_create_with_type(zend_class_entry *ce,
upb_fieldtype_t type,
const zend_class_entry* msg_ce,
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 =
UNBOX(RepeatedField, CACHED_TO_ZVAL_PTR(*repeated_field));
zend_object_store_get_object(*repeated_field TSRMLS_CC);
intern->type = type;
intern->msg_ce = msg_ce;
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(intern->array);
repeated_field_array_init(intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
#else
repeated_field_array_init(&intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
#endif
// TODO(teboring): Link class entry for message and enum
}
@ -295,16 +271,12 @@ PHP_METHOD(RepeatedField, __construct) {
return;
}
RepeatedField *intern = UNBOX(RepeatedField, getThis());
RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
intern->type = to_fieldtype(type);
intern->msg_ce = klass;
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(intern->array);
repeated_field_array_init(intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
#else
repeated_field_array_init(&intern->array, intern->type, 0 ZEND_FILE_LINE_CC);
#endif
if (intern->type == UPB_TYPE_MESSAGE && klass == NULL) {
zend_error(E_USER_ERROR, "Message type must have concrete class.");
@ -341,10 +313,10 @@ PHP_METHOD(RepeatedField, offsetExists) {
return;
}
RepeatedField *intern = UNBOX(RepeatedField, getThis());
RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
RETURN_BOOL(index >= 0 &&
index < zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array)));
index < zend_hash_num_elements(HASH_OF(intern->array)));
}
/**
@ -364,16 +336,15 @@ PHP_METHOD(RepeatedField, offsetGet) {
return;
}
RepeatedField *intern = UNBOX(RepeatedField, getThis());
HashTable *table = PHP_PROTO_HASH_OF(intern->array);
RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
HashTable *table = HASH_OF(intern->array);
if (php_proto_zend_hash_index_find(table, index, (void **)&memory) == FAILURE) {
if (zend_hash_index_find(table, index, (void **)&memory) == FAILURE) {
zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
return;
}
native_slot_get_by_array(intern->type, memory,
ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
native_slot_get(intern->type, memory, return_value_ptr TSRMLS_CC);
}
/**
@ -408,16 +379,16 @@ PHP_METHOD(RepeatedField, offsetUnset) {
return;
}
RepeatedField *intern = UNBOX(RepeatedField, getThis());
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(PHP_PROTO_HASH_OF(intern->array)) - 1)) {
index != (zend_hash_num_elements(HASH_OF(intern->array)) - 1)) {
zend_error(E_USER_ERROR, "Cannot remove element at %ld.\n", index);
return;
}
zend_hash_index_del(PHP_PROTO_HASH_OF(intern->array), index);
zend_hash_index_del(HASH_OF(intern->array), index);
}
/**
@ -426,13 +397,13 @@ PHP_METHOD(RepeatedField, offsetUnset) {
* @return long The number of stored elements.
*/
PHP_METHOD(RepeatedField, count) {
RepeatedField *intern = UNBOX(RepeatedField, getThis());
RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
if (zend_parse_parameters_none() == FAILURE) {
return;
}
RETURN_LONG(zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array)));
RETURN_LONG(zend_hash_num_elements(HASH_OF(intern->array)));
}
/**
@ -441,77 +412,105 @@ PHP_METHOD(RepeatedField, count) {
* @return object Beginning iterator.
*/
PHP_METHOD(RepeatedField, getIterator) {
CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(return_value,
repeated_field_iter_type);
zval *iter_php = NULL;
MAKE_STD_ZVAL(iter_php);
Z_TYPE_P(iter_php) = IS_OBJECT;
Z_OBJVAL_P(iter_php) = repeated_field_iter_type->create_object(
repeated_field_iter_type TSRMLS_CC);
RepeatedField *intern = UNBOX(RepeatedField, getThis());
RepeatedFieldIter *iter = UNBOX(RepeatedFieldIter, return_value);
RepeatedField *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
RepeatedFieldIter *iter = zend_object_store_get_object(iter_php TSRMLS_CC);
iter->repeated_field = intern;
iter->position = 0;
RETURN_ZVAL(iter_php, 1, 1);
}
// -----------------------------------------------------------------------------
// RepeatedFieldIter creation/desctruction
// -----------------------------------------------------------------------------
// Define object free method.
PHP_PROTO_OBJECT_FREE_START(RepeatedFieldIter, repeated_field_iter)
PHP_PROTO_OBJECT_FREE_END
void repeated_field_iter_init(TSRMLS_D) {
zend_class_entry class_type;
const char* class_name = "Google\\Protobuf\\Internal\\RepeatedFieldIter";
INIT_CLASS_ENTRY_EX(class_type, class_name, strlen(class_name),
repeated_field_iter_methods);
PHP_PROTO_OBJECT_DTOR_START(RepeatedFieldIter, repeated_field_iter)
PHP_PROTO_OBJECT_DTOR_END
repeated_field_iter_type =
zend_register_internal_class(&class_type TSRMLS_CC);
repeated_field_iter_type->create_object = repeated_field_iter_create;
// Define object create method.
PHP_PROTO_OBJECT_CREATE_START(RepeatedFieldIter, repeated_field_iter)
intern->repeated_field = NULL;
intern->position = 0;
PHP_PROTO_OBJECT_CREATE_END(RepeatedFieldIter, repeated_field_iter)
zend_class_implements(repeated_field_iter_type TSRMLS_CC, 1,
zend_ce_iterator);
}
// Init class entry.
PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\RepeatedFieldIter",
RepeatedFieldIter, repeated_field_iter)
zend_class_implements(repeated_field_iter_type TSRMLS_CC, 1, zend_ce_iterator);
PHP_PROTO_INIT_CLASS_END
static zend_object_value repeated_field_iter_create(
zend_class_entry *ce TSRMLS_DC) {
zend_object_value retval = {0};
RepeatedFieldIter *intern;
intern = emalloc(sizeof(RepeatedFieldIter));
memset(intern, 0, sizeof(RepeatedFieldIter));
zend_object_std_init(&intern->std, ce TSRMLS_CC);
object_properties_init(&intern->std, ce);
intern->repeated_field = NULL;
intern->position = 0;
retval.handle = zend_objects_store_put(
intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
(zend_objects_free_object_storage_t)repeated_field_iter_free,
NULL TSRMLS_CC);
retval.handlers = zend_get_std_object_handlers();
return retval;
}
static void repeated_field_iter_free(void *object TSRMLS_DC) {
RepeatedFieldIter *intern = object;
zend_object_std_dtor(&intern->std TSRMLS_CC);
efree(object);
}
// -----------------------------------------------------------------------------
// PHP RepeatedFieldIter Methods
// -----------------------------------------------------------------------------
PHP_METHOD(RepeatedFieldIter, rewind) {
RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis());
RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
intern->position = 0;
}
PHP_METHOD(RepeatedFieldIter, current) {
RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis());
RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
RepeatedField *repeated_field = intern->repeated_field;
long index;
void *memory;
HashTable *table = PHP_PROTO_HASH_OF(repeated_field->array);
HashTable *table = HASH_OF(repeated_field->array);
if (php_proto_zend_hash_index_find(table, intern->position, (void **)&memory) ==
if (zend_hash_index_find(table, intern->position, (void **)&memory) ==
FAILURE) {
zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
return;
}
native_slot_get_by_array(repeated_field->type, memory,
ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
native_slot_get(repeated_field->type, memory, return_value_ptr TSRMLS_CC);
}
PHP_METHOD(RepeatedFieldIter, key) {
RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis());
RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
RETURN_LONG(intern->position);
}
PHP_METHOD(RepeatedFieldIter, next) {
RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis());
RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
++intern->position;
}
PHP_METHOD(RepeatedFieldIter, valid) {
RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis());
RETURN_BOOL(zend_hash_num_elements(PHP_PROTO_HASH_OF(
intern->repeated_field->array)) > intern->position);
RepeatedFieldIter *intern = zend_object_store_get_object(getThis() TSRMLS_CC);
RETURN_BOOL(zend_hash_num_elements(HASH_OF(intern->repeated_field->array)) >
intern->position);
}

View file

@ -30,17 +30,20 @@
#include "protobuf.h"
const char* const kReservedNames[] = {"Empty"};
const int kReservedNamesSize = 1;
// 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);
// -----------------------------------------------------------------------------
@ -101,31 +104,40 @@ static void append_map_entry_name(char *result, const char *field_name,
} while (0)
// Define PHP class
#define DEFINE_PROTOBUF_INIT_CLASS(CLASSNAME, CAMELNAME, LOWERNAME) \
PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWERNAME) \
PHP_PROTO_INIT_CLASS_END
#define DEFINE_PROTOBUF_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; \
}
#define DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME) \
PHP_PROTO_OBJECT_CREATE_START(NAME, LOWERNAME) \
LOWERNAME##_init_c_instance(intern TSRMLS_CC); \
PHP_PROTO_OBJECT_CREATE_END(NAME, LOWERNAME)
#define DEFINE_PROTOBUF_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(CAMELNAME, LOWERNAME) \
PHP_PROTO_OBJECT_FREE_START(CAMELNAME, LOWERNAME) \
LOWERNAME##_free_c(intern TSRMLS_CC); \
PHP_PROTO_OBJECT_FREE_END
#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_PROTOBUF_DTOR(CAMELNAME, LOWERNAME) \
PHP_PROTO_OBJECT_DTOR_START(CAMELNAME, LOWERNAME) \
PHP_PROTO_OBJECT_DTOR_END
#define DEFINE_CLASS(NAME, LOWERNAME, string_name) \
zend_class_entry *LOWERNAME##_type; \
zend_object_handlers *LOWERNAME##_handlers; \
DEFINE_PROTOBUF_FREE(NAME, LOWERNAME) \
DEFINE_PROTOBUF_DTOR(NAME, LOWERNAME) \
DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME) \
DEFINE_PROTOBUF_INIT_CLASS(string_name, NAME, LOWERNAME)
#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
@ -164,6 +176,228 @@ void gpb_type_init(TSRMLS_D) {
zend_declare_class_constant_long(gpb_type_type, STR("SINT64"), 18 TSRMLS_CC);
}
// -----------------------------------------------------------------------------
// DescriptorPool
// -----------------------------------------------------------------------------
static zend_function_entry descriptor_pool_methods[] = {
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\\Internal\\DescriptorPool");
zval* generated_pool_php; // wrapper of generated pool
DescriptorPool *generated_pool; // The actual generated pool
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(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(generated_pool_php) = zend_get_std_object_handlers();
}
}
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();
ALLOC_HASHTABLE(pool->pending_list);
zend_hash_init(pool->pending_list, 1, NULL, ZVAL_PTR_DTOR, 0);
}
static void descriptor_pool_free_c(DescriptorPool *pool TSRMLS_DC) {
upb_symtab_free(pool->symtab);
zend_hash_destroy(pool->pending_list);
FREE_HASHTABLE(pool->pending_list);
}
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'.");
}
}
static void validate_msgdef(const upb_msgdef* msgdef) {
// Verify that no required fields exist. proto3 does not support these.
upb_msg_field_iter it;
for (upb_msg_field_begin(&it, msgdef);
!upb_msg_field_done(&it);
upb_msg_field_next(&it)) {
const upb_fielddef* field = upb_msg_iter_field(&it);
if (upb_fielddef_label(field) == UPB_LABEL_REQUIRED) {
zend_error(E_ERROR, "Required fields are unsupported in proto3.");
}
}
}
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 *class_name,
const char* fullname,
const char* prefix,
const char* package_name) {
size_t i = 0, j;
bool first_char = true;
size_t pkg_name_len = package_name == NULL ? 0 : strlen(package_name);
size_t prefix_len = prefix == NULL ? 0 : strlen(prefix);
size_t message_name_start = package_name == NULL ? 0 : pkg_name_len + 1;
size_t message_len = (strlen(fullname) - message_name_start);
// In php, class name cannot be Empty.
if (strcmp("google.protobuf.Empty", fullname) == 0) {
strcpy(class_name, "\\Google\\Protobuf\\GPBEmpty");
return;
}
if (pkg_name_len != 0) {
class_name[i++] = '\\';
for (j = 0; j < pkg_name_len; j++) {
// php packages are divided by '\'.
if (package_name[j] == '.') {
class_name[i++] = '\\';
first_char = true;
} else if (first_char) {
// PHP package uses camel case.
if (package_name[j] < 'A' || package_name[j] > 'Z') {
class_name[i++] = package_name[j] + 'A' - 'a';
} else {
class_name[i++] = package_name[j];
}
first_char = false;
} else {
class_name[i++] = package_name[j];
}
}
class_name[i++] = '\\';
}
if (prefix_len > 0) {
strcpy(class_name + i, prefix);
i += prefix_len;
}
// Submessage is concatenated with its containing messages by '_'.
for (j = message_name_start; j < message_name_start + message_len; j++) {
if (fullname[j] == '.') {
class_name[i++] = '_';
} else {
class_name[i++] = fullname[j];
}
}
}
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;
}
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(upb_downcast_msgdef(def))) { \
break; \
} \
/* Prepend '.' to package name to make it absolute. In the 5 additional \
* bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if \
* given message is google.protobuf.Empty.*/ \
const char *fullname = upb_##def_type_lower##_fullname(def_type_lower); \
const char *prefix = upb_filedef_phpprefix(files[0]); \
size_t klass_name_len = strlen(fullname) + 5; \
if (prefix != NULL) { \
klass_name_len += strlen(prefix); \
} \
char *klass_name = ecalloc(sizeof(char), klass_name_len); \
convert_to_class_name_inplace(klass_name, fullname, prefix, \
upb_filedef_package(files[0])); \
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; \
}
CASE_TYPE(MSG, msgdef, Descriptor, descriptor)
CASE_TYPE(ENUM, enumdef, EnumDescriptor, enum_descriptor)
#undef CASE_TYPE
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);
}
}
upb_filedef_unref(files[0], &pool);
upb_gfree(files);
}
// -----------------------------------------------------------------------------
// Descriptor
// -----------------------------------------------------------------------------
@ -203,7 +437,7 @@ static void descriptor_free_c(Descriptor *self TSRMLS_DC) {
}
static void descriptor_init_c_instance(Descriptor *desc TSRMLS_DC) {
// zend_object_std_init(&desc->std, descriptor_type TSRMLS_CC);
zend_object_std_init(&desc->std, descriptor_type TSRMLS_CC);
desc->msgdef = NULL;
desc->layout = NULL;
desc->klass = NULL;
@ -230,7 +464,7 @@ static void enum_descriptor_free_c(EnumDescriptor *self TSRMLS_DC) {
}
static void enum_descriptor_init_c_instance(EnumDescriptor *self TSRMLS_DC) {
// zend_object_std_init(&self->std, enum_descriptor_type TSRMLS_CC);
zend_object_std_init(&self->std, enum_descriptor_type TSRMLS_CC);
self->enumdef = NULL;
self->klass = NULL;
}
@ -271,267 +505,3 @@ upb_fieldtype_t to_fieldtype(upb_descriptortype_t type) {
zend_error(E_ERROR, "Unknown field type.");
return 0;
}
// -----------------------------------------------------------------------------
// DescriptorPool
// -----------------------------------------------------------------------------
static zend_function_entry descriptor_pool_methods[] = {
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\\Internal\\DescriptorPool");
// wrapper of generated pool
#if PHP_MAJOR_VERSION < 7
zval* generated_pool_php;
#else
zend_object *generated_pool_php;
#endif
DescriptorPool *generated_pool; // The actual generated pool
static void init_generated_pool_once(TSRMLS_D) {
if (generated_pool_php == NULL) {
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(generated_pool_php);
ZVAL_OBJ(generated_pool_php, descriptor_pool_type->create_object(
descriptor_pool_type TSRMLS_CC));
generated_pool = UNBOX(DescriptorPool, generated_pool_php);
#else
generated_pool_php =
descriptor_pool_type->create_object(descriptor_pool_type TSRMLS_CC);
generated_pool = (DescriptorPool *)((char *)generated_pool_php -
XtOffsetOf(DescriptorPool, std));
#endif
}
}
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();
ALLOC_HASHTABLE(pool->pending_list);
zend_hash_init(pool->pending_list, 1, NULL, ZVAL_PTR_DTOR, 0);
}
static void descriptor_pool_free_c(DescriptorPool *pool TSRMLS_DC) {
upb_symtab_free(pool->symtab);
zend_hash_destroy(pool->pending_list);
FREE_HASHTABLE(pool->pending_list);
}
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'.");
}
}
static void validate_msgdef(const upb_msgdef* msgdef) {
// Verify that no required fields exist. proto3 does not support these.
upb_msg_field_iter it;
for (upb_msg_field_begin(&it, msgdef);
!upb_msg_field_done(&it);
upb_msg_field_next(&it)) {
const upb_fielddef* field = upb_msg_iter_field(&it);
if (upb_fielddef_label(field) == UPB_LABEL_REQUIRED) {
zend_error(E_ERROR, "Required fields are unsupported in proto3.");
}
}
}
PHP_METHOD(DescriptorPool, getGeneratedPool) {
init_generated_pool_once(TSRMLS_C);
#if PHP_MAJOR_VERSION < 7
RETURN_ZVAL(generated_pool_php, 1, 0);
#else
++GC_REFCOUNT(generated_pool_php);
RETURN_OBJ(generated_pool_php);
#endif
}
static void classname_no_prefix(const char *fullname, const char *package_name,
char *class_name) {
size_t i = 0, j;
bool first_char = true, is_reserved = false;
size_t pkg_name_len = package_name == NULL ? 0 : strlen(package_name);
size_t message_name_start = package_name == NULL ? 0 : pkg_name_len + 1;
size_t message_len = (strlen(fullname) - message_name_start);
// Submessage is concatenated with its containing messages by '_'.
for (j = message_name_start; j < message_name_start + message_len; j++) {
if (fullname[j] == '.') {
class_name[i++] = '_';
} else {
class_name[i++] = fullname[j];
}
}
}
static const char *classname_prefix(const char *classname,
const char *prefix_given,
const char *package_name) {
size_t i;
bool is_reserved = false;
if (prefix_given != NULL && strcmp(prefix_given, "") != 0) {
return prefix_given;
}
for (i = 0; i < kReservedNamesSize; i++) {
if (strcmp(kReservedNames[i], classname) == 0) {
is_reserved = true;
break;
}
}
if (is_reserved) {
if (package_name != NULL && strcmp("google.protobuf", package_name) == 0) {
return "GPB";
} else {
return "PB";
}
}
return "";
}
static void convert_to_class_name_inplace(const char *package,
const char *prefix, char *classname) {
size_t package_len = package == NULL ? 0 : strlen(package);
size_t prefix_len = prefix == NULL ? 0 : strlen(prefix);
size_t classname_len = strlen(classname);
int i = 0, j;
bool first_char = true;
int offset = package_len != 0 ? 2 : 0;
for (j = 0; j < classname_len; j++) {
classname[package_len + prefix_len + classname_len + offset - 1 - j] =
classname[classname_len - j - 1];
}
if (package_len != 0) {
classname[i++] = '\\';
for (j = 0; j < package_len; j++) {
// php packages are divided by '\'.
if (package[j] == '.') {
classname[i++] = '\\';
first_char = true;
} else if (first_char) {
// PHP package uses camel case.
if (package[j] < 'A' || package[j] > 'Z') {
classname[i++] = package[j] + 'A' - 'a';
} else {
classname[i++] = package[j];
}
first_char = false;
} else {
classname[i++] = package[j];
}
}
classname[i++] = '\\';
}
memcpy(classname + i, prefix, prefix_len);
}
PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {
char *data = NULL;
PHP_PROTO_SIZE data_len;
upb_filedef **files;
size_t i;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) ==
FAILURE) {
return;
}
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: { \
CREATE_HASHTABLE_VALUE(desc, desc_php, desc_type, desc_type_lower##_type); \
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(upb_downcast_msgdef(def))) { \
break; \
} \
/* Prepend '.' to package name to make it absolute. In the 5 additional \
* bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if \
* given message is google.protobuf.Empty.*/ \
const char *fullname = upb_##def_type_lower##_fullname(def_type_lower); \
const char *prefix_given = upb_filedef_phpprefix(files[0]); \
size_t classname_len = strlen(fullname) + 5; \
if (prefix_given != NULL) { \
classname_len += strlen(prefix_given); \
} \
char *classname = ecalloc(sizeof(char), classname_len); \
const char *package = upb_filedef_package(files[0]); \
classname_no_prefix(fullname, package, classname); \
const char *prefix = classname_prefix(classname, prefix_given, package); \
convert_to_class_name_inplace(package, prefix, classname); \
PHP_PROTO_CE_DECLARE pce; \
if (php_proto_zend_lookup_class(classname, strlen(classname), &pce) == \
FAILURE) { \
zend_error(E_ERROR, "Generated message class %s hasn't been defined", \
classname); \
return; \
} else { \
desc->klass = PHP_PROTO_CE_UNREF(pce); \
} \
add_ce_obj(desc->klass, desc_php); \
efree(classname); \
break; \
}
CASE_TYPE(MSG, msgdef, Descriptor, descriptor)
CASE_TYPE(ENUM, enumdef, EnumDescriptor, enum_descriptor)
#undef CASE_TYPE
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);
PHP_PROTO_HASHTABLE_VALUE desc_php = get_def_obj(msgdef);
build_class_from_descriptor(desc_php TSRMLS_CC);
}
}
upb_filedef_unref(files[0], &pool);
upb_gfree(files);
}

View file

@ -197,18 +197,19 @@ static const void *newoneofhandlerdata(upb_handlers *h,
static void *startseq_handler(void* closure, const void* hd) {
MessageHeader* msg = closure;
const size_t *ofs = hd;
return CACHED_PTR_TO_ZVAL_PTR(DEREF(message_data(msg), *ofs, CACHED_VALUE*));
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; \
TSRMLS_FETCH(); \
RepeatedField* intern = UNBOX(RepeatedField, array); \
repeated_field_push_native(intern, &val); \
return true; \
#define DEFINE_APPEND_HANDLER(type, ctype) \
static bool append##type##_handler(void* closure, const void* hd, \
ctype val) { \
zval* array = (zval*)closure; \
TSRMLS_FETCH(); \
RepeatedField* intern = \
(RepeatedField*)zend_object_store_get_object(array TSRMLS_CC); \
repeated_field_push_native(intern, &val TSRMLS_CC); \
return true; \
}
DEFINE_APPEND_HANDLER(bool, bool)
@ -225,19 +226,15 @@ static void* appendstr_handler(void *closure,
size_t size_hint) {
zval* array = (zval*)closure;
TSRMLS_FETCH();
RepeatedField* intern = UNBOX(RepeatedField, array);
RepeatedField* intern =
(RepeatedField*)zend_object_store_get_object(array TSRMLS_CC);
#if PHP_MAJOR_VERSION < 7
zval* str;
MAKE_STD_ZVAL(str);
PHP_PROTO_ZVAL_STRING(str, "", 1);
repeated_field_push_native(intern, &str);
ZVAL_STRING(str, "", 1);
repeated_field_push_native(intern, &str TSRMLS_CC);
return (void*)str;
#else
zend_string* str = zend_string_init("", 0, 1);
repeated_field_push_native(intern, &str);
return intern;
#endif
}
// Appends a 'bytes' string to a repeated field.
@ -246,51 +243,24 @@ static void* appendbytes_handler(void *closure,
size_t size_hint) {
zval* array = (zval*)closure;
TSRMLS_FETCH();
RepeatedField* intern = UNBOX(RepeatedField, array);
RepeatedField* intern =
(RepeatedField*)zend_object_store_get_object(array TSRMLS_CC);
#if PHP_MAJOR_VERSION < 7
zval* str;
MAKE_STD_ZVAL(str);
PHP_PROTO_ZVAL_STRING(str, "", 1);
repeated_field_push_native(intern, &str);
ZVAL_STRING(str, "", 1);
repeated_field_push_native(intern, &str TSRMLS_CC);
return (void*)str;
#else
zend_string* str = zend_string_init("", 0, 1);
repeated_field_push_native(intern, &str);
return intern;
#endif
}
// Handlers that append primitive values to a repeated field.
#define DEFINE_SINGULAR_HANDLER(type, ctype) \
static bool type##_handler(void* closure, const void* hd, \
ctype val) { \
MessageHeader* msg = (MessageHeader*)closure; \
const size_t *ofs = hd; \
DEREF(message_data(msg), *ofs, ctype) = val; \
return true; \
}
DEFINE_SINGULAR_HANDLER(bool, bool)
DEFINE_SINGULAR_HANDLER(int32, int32_t)
DEFINE_SINGULAR_HANDLER(uint32, uint32_t)
DEFINE_SINGULAR_HANDLER(float, float)
DEFINE_SINGULAR_HANDLER(int64, int64_t)
DEFINE_SINGULAR_HANDLER(uint64, uint64_t)
DEFINE_SINGULAR_HANDLER(double, double)
#undef DEFINE_SINGULAR_HANDLER
#if PHP_MAJOR_VERSION < 7
static void *empty_php_string(zval** value_ptr) {
SEPARATE_ZVAL_IF_NOT_REF(value_ptr);
return (void*)(*value_ptr);
zval* str = *value_ptr;
zval_dtor(str);
ZVAL_STRINGL(str, "", 0, 1);
return (void*)str;
}
#else
static void *empty_php_string(zval* value_ptr) {
return value_ptr;
}
#endif
// Sets a non-repeated string field in a message.
static void* str_handler(void *closure,
@ -298,7 +268,7 @@ static void* str_handler(void *closure,
size_t size_hint) {
MessageHeader* msg = closure;
const size_t *ofs = hd;
return empty_php_string(DEREF(message_data(msg), *ofs, CACHED_VALUE*));
return empty_php_string(DEREF(msg, *ofs, zval**));
}
// Sets a non-repeated 'bytes' field in a message.
@ -307,73 +277,52 @@ static void* bytes_handler(void *closure,
size_t size_hint) {
MessageHeader* msg = closure;
const size_t *ofs = hd;
return empty_php_string(DEREF(message_data(msg), *ofs, CACHED_VALUE*));
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;
#if PHP_MAJOR_VERSION < 7
// Oneof string/bytes fields may have NULL initial value, which doesn't need
// to be freed.
if (Z_TYPE_P(php_str) == IS_STRING && !IS_INTERNED(Z_STRVAL_P(php_str))) {
FREE(Z_STRVAL_P(php_str));
}
ZVAL_STRINGL(php_str, str, len, 1);
#else
if (Z_TYPE_P(php_str) == IS_STRING) {
zend_string_release(Z_STR_P(php_str));
}
ZVAL_NEW_STR(php_str, zend_string_init(str, len, 0));
#endif
return len;
}
#if PHP_MAJOR_VERSION >= 7
static size_t zendstringdata_handler(void* closure, const void* hd,
const char* str, size_t len,
const upb_bufhandle* handle) {
RepeatedField* intern = (RepeatedField*)closure;
char* old_str = Z_STRVAL_P(php_str);
size_t old_len = Z_STRLEN_P(php_str);
assert(old_str != NULL);
unsigned char memory[NATIVE_SLOT_MAX_SIZE];
memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
*(zend_string**)memory = zend_string_init(str, len, 0);
char* new_str = emalloc(old_len + len + 1);
HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
int index = zend_hash_num_elements(ht) - 1;
php_proto_zend_hash_index_update(
ht, index, memory, sizeof(zend_string*), NULL);
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;
}
#endif
// Appends a submessage to a repeated field.
static void *appendsubmsg_handler(void *closure, const void *hd) {
zval* array = (zval*)closure;
TSRMLS_FETCH();
RepeatedField* intern = UNBOX(RepeatedField, array);
RepeatedField* intern =
(RepeatedField*)zend_object_store_get_object(array TSRMLS_CC);
const submsg_handlerdata_t *submsgdata = hd;
Descriptor* subdesc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)submsgdata->md));
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;
#if PHP_MAJOR_VERSION < 7
zval* val = NULL;
MAKE_STD_ZVAL(val);
ZVAL_OBJ(val, subklass->create_object(subklass TSRMLS_CC));
repeated_field_push_native(intern, &val);
submsg = UNBOX(MessageHeader, val);
#else
zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
repeated_field_push_native(intern, &obj);
submsg = (MessageHeader*)((char*)obj - XtOffsetOf(MessageHeader, std));
#endif
custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
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;
}
@ -381,35 +330,26 @@ static void *appendsubmsg_handler(void *closure, const void *hd) {
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);
TSRMLS_FETCH();
Descriptor* subdesc =
UNBOX_HASHTABLE_VALUE(Descriptor, 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(CACHED_PTR_TO_ZVAL_PTR(DEREF(message_data(msg), submsgdata->ofs,
CACHED_VALUE*))) == IS_NULL) {
#if PHP_MAJOR_VERSION < 7
if (Z_TYPE_P(*DEREF(msg, submsgdata->ofs, zval**)) == IS_NULL) {
zval* val = NULL;
MAKE_STD_ZVAL(val);
ZVAL_OBJ(val, subklass->create_object(subklass TSRMLS_CC));
MessageHeader* intern = UNBOX(MessageHeader, val);
custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
php_proto_zval_ptr_dtor(*DEREF(message_data(msg), submsgdata->ofs, zval**));
*DEREF(message_data(msg), submsgdata->ofs, zval**) = val;
#else
zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
ZVAL_OBJ(DEREF(message_data(msg), submsgdata->ofs, zval*), obj);
MessageHeader* intern = UNBOX_HASHTABLE_VALUE(MessageHeader, obj);
custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
#endif
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 = CACHED_PTR_TO_ZVAL_PTR(
DEREF(message_data(msg), submsgdata->ofs, CACHED_VALUE*));
submsg_php = *DEREF(msg, submsgdata->ofs, zval**);
submsg = UNBOX(MessageHeader, submsg_php);
submsg = zend_object_store_get_object(submsg_php TSRMLS_CC);
return submsg;
}
@ -432,52 +372,32 @@ typedef struct {
// 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_data_t;
} map_parse_frame_t;
PHP_PROTO_WRAP_OBJECT_START(map_parse_frame_t)
map_parse_frame_data_t* data; // Place needs to be consistent with
// MessageHeader.
zval* map;
// In php7, we cannot allocate zval dynamically. So we need to add zval here
// to help decoding.
zval key_zval;
zval value_zval;
PHP_PROTO_WRAP_OBJECT_END
typedef struct map_parse_frame_t map_parse_frame_t;
static void map_slot_init(void* memory, upb_fieldtype_t type, zval* cache) {
static void map_slot_init(void* memory, upb_fieldtype_t type) {
switch (type) {
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES: {
#if PHP_MAJOR_VERSION < 7
// 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);
PHP_PROTO_ZVAL_STRINGL(tmp, "", 0, 1);
ZVAL_STRINGL(tmp, "", 0, 1);
*holder = tmp;
*(zval***)memory = holder;
#else
*(zval**)memory = cache;
PHP_PROTO_ZVAL_STRINGL(*(zval**)memory, "", 0, 1);
#endif
break;
}
case UPB_TYPE_MESSAGE: {
#if PHP_MAJOR_VERSION < 7
zval** holder = ALLOC(zval*);
zval* tmp;
MAKE_STD_ZVAL(tmp);
ZVAL_NULL(tmp);
*holder = tmp;
*(zval***)memory = holder;
#else
*(zval**)memory = cache;
ZVAL_NULL(*(zval**)memory);
#endif
break;
}
default:
@ -490,13 +410,9 @@ static void map_slot_uninit(void* memory, upb_fieldtype_t type) {
case UPB_TYPE_MESSAGE:
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES: {
#if PHP_MAJOR_VERSION < 7
zval** holder = *(zval***)memory;
php_proto_zval_ptr_dtor(*holder);
zval_ptr_dtor(holder);
FREE(holder);
#else
php_proto_zval_ptr_dtor(*(zval**)memory);
#endif
break;
}
default:
@ -508,11 +424,7 @@ static void map_slot_key(upb_fieldtype_t type, const void* from,
const char** keyval,
size_t* length) {
if (type == UPB_TYPE_STRING) {
#if PHP_MAJOR_VERSION < 7
zval* key_php = **(zval***)from;
#else
zval* key_php = *(zval**)from;
#endif
*keyval = Z_STRVAL_P(key_php);
*length = Z_STRLEN_P(key_php);
} else {
@ -532,7 +444,6 @@ static void map_slot_value(upb_fieldtype_t type, const void* from,
memset(to, 0, native_slot_size(type));
switch (type) {
#if PHP_MAJOR_VERSION < 7
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
case UPB_TYPE_MESSAGE: {
@ -540,17 +451,6 @@ static void map_slot_value(upb_fieldtype_t type, const void* from,
Z_ADDREF_PP((zval**)to);
break;
}
#else
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
*(zend_string**)to = Z_STR_P(*(zval**)from);
zend_string_addref(*(zend_string**)to);
break;
case UPB_TYPE_MESSAGE:
*(zend_object**)to = Z_OBJ_P(*(zval**)from);
++GC_REFCOUNT(*(zend_object**)to);
break;
#endif
default:
len = native_slot_size(type);
memcpy(to, from, len);
@ -562,17 +462,13 @@ static void map_slot_value(upb_fieldtype_t type, const void* from,
static void *startmapentry_handler(void *closure, const void *hd) {
MessageHeader* msg = closure;
const map_handlerdata_t* mapdata = hd;
zval* map = CACHED_PTR_TO_ZVAL_PTR(
DEREF(message_data(msg), mapdata->ofs, CACHED_VALUE*));
zval* map = *DEREF(msg, mapdata->ofs, zval**);
map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
frame->data = ALLOC(map_parse_frame_data_t);
frame->map = map;
map_slot_init(&frame->data->key_storage, mapdata->key_field_type,
&frame->key_zval);
map_slot_init(&frame->data->value_storage, mapdata->value_field_type,
&frame->value_zval);
map_slot_init(&frame->key_storage, mapdata->key_field_type);
map_slot_init(&frame->value_storage, mapdata->value_field_type);
return frame;
}
@ -584,20 +480,19 @@ static bool endmap_handler(void* closure, const void* hd, upb_status* s) {
const map_handlerdata_t* mapdata = hd;
TSRMLS_FETCH();
Map *map = UNBOX(Map, frame->map);
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->data->key_storage, &keyval, &length);
map_slot_value(map->value_type, &frame->data->value_storage, &v);
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->data->key_storage, mapdata->key_field_type);
map_slot_uninit(&frame->data->value_storage, mapdata->value_field_type);
FREE(frame->data);
map_slot_uninit(&frame->key_storage, mapdata->key_field_type);
map_slot_uninit(&frame->value_storage, mapdata->value_field_type);
FREE(frame);
return true;
@ -633,15 +528,14 @@ static map_handlerdata_t* new_map_handlerdata(
}
// 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; \
MessageHeader* msg = (MessageHeader*)closure; \
DEREF(message_data(closure), oneofdata->case_ofs, uint32_t) = \
oneofdata->oneof_case_num; \
DEREF(message_data(closure), oneofdata->ofs, ctype) = val; \
return true; \
#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)
@ -654,71 +548,74 @@ DEFINE_ONEOF_HANDLER(double, double)
#undef DEFINE_ONEOF_HANDLER
// Handlers for string/bytes in a oneof.
// 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(message_data(msg), oneofdata->case_ofs, uint32_t) =
DEREF(msg, oneofdata->case_ofs, uint32_t) =
oneofdata->oneof_case_num;
DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) =
DEREF(msg, oneofdata->ofs, zval**) =
&(msg->std.properties_table)[oneofdata->property_ofs];
return empty_php_string(DEREF(
message_data(msg), oneofdata->ofs, CACHED_VALUE*));
}
static void *oneofstr_handler(void *closure,
const void *hd,
size_t size_hint) {
// TODO(teboring): Add it back.
// rb_enc_associate(str, kRubyString8bitEncoding);
return oneofbytes_handler(closure, hd, size_hint);
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(message_data(msg), oneofdata->case_ofs, uint32_t);
uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t);
zval* subdesc_php = get_def_obj((void*)oneofdata->md);
TSRMLS_FETCH();
Descriptor* subdesc =
UNBOX_HASHTABLE_VALUE(Descriptor, 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) {
// Ideally, we should clean up the old data. However, we don't even know the
// type of the old data. So, we will defer the desctruction of the old data
// to the time that containing message's destroyed or the same oneof field
// is accessed again and find that the old data hasn't been cleaned.
DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) =
DEREF(msg, oneofdata->ofs, zval**) =
&(msg->std.properties_table)[oneofdata->property_ofs];
// Old data was't cleaned when the oneof was accessed from another field.
if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(DEREF(
message_data(msg), oneofdata->ofs, CACHED_VALUE*))) != IS_NULL) {
php_proto_zval_ptr_dtor(
CACHED_PTR_TO_ZVAL_PTR(
DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*)));
}
// Create new message.
ZVAL_OBJ(CACHED_PTR_TO_ZVAL_PTR(
DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*)),
subklass->create_object(subklass TSRMLS_CC));
}
DEREF(message_data(msg), oneofdata->case_ofs, uint32_t) =
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 = CACHED_PTR_TO_ZVAL_PTR(
DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
submsg = UNBOX(MessageHeader, submsg_php);
custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
submsg_php = *DEREF(msg, oneofdata->ofs, zval**);
submsg = zend_object_store_get_object(submsg_php TSRMLS_CC);
return submsg;
}
@ -755,11 +652,7 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
upb_handlers_setstartstr(h, f, is_bytes ?
appendbytes_handler : appendstr_handler,
NULL);
#if PHP_MAJOR_VERSION < 7
upb_handlers_setstring(h, f, stringdata_handler, NULL);
#else
upb_handlers_setstring(h, f, zendstringdata_handler, NULL);
#endif
break;
}
case UPB_TYPE_MESSAGE: {
@ -777,26 +670,16 @@ static void add_handlers_for_singular_field(upb_handlers *h,
const upb_fielddef *f,
size_t offset) {
switch (upb_fielddef_type(f)) {
#define SET_HANDLER(utype, ltype) \
case utype: { \
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; \
upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset)); \
upb_handlers_set##ltype(h, f, 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_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_msg_setscalarhandler(h, f, offset, -1);
break;
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES: {
bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
@ -847,11 +730,9 @@ static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h,
upb_handlers_setendmsg(h, endmap_handler, &attr);
add_handlers_for_singular_field(h, key_field,
offsetof(map_parse_frame_data_t,
key_storage));
offsetof(map_parse_frame_t, key_storage));
add_handlers_for_singular_field(h, value_field,
offsetof(map_parse_frame_data_t,
value_storage));
offsetof(map_parse_frame_t, value_storage));
}
// Set up handlers for a oneof field.
@ -906,8 +787,8 @@ static void add_handlers_for_message(const void* closure,
upb_handlers* h) {
const upb_msgdef* msgdef = upb_handlers_msgdef(h);
TSRMLS_FETCH();
Descriptor* desc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)msgdef));
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
@ -929,11 +810,13 @@ static void add_handlers_for_message(const void* closure,
!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;
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;
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,
@ -1000,8 +883,6 @@ static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) {
static void putmsg(zval* msg, const Descriptor* desc, upb_sink* sink,
int depth TSRMLS_DC);
static void putrawmsg(MessageHeader* msg, const Descriptor* desc,
upb_sink* sink, int depth TSRMLS_DC);
static void putstr(zval* str, const upb_fielddef* f, upb_sink* sink);
@ -1010,8 +891,6 @@ static void putrawstr(const char* str, int len, const upb_fielddef* f,
static void putsubmsg(zval* submsg, const upb_fielddef* f, upb_sink* sink,
int depth TSRMLS_DC);
static void putrawsubmsg(MessageHeader* submsg, const upb_fielddef* f,
upb_sink* sink, int depth TSRMLS_DC);
static void putarray(zval* array, const upb_fielddef* f, upb_sink* sink,
int depth TSRMLS_DC);
@ -1054,14 +933,8 @@ static void put_optional_value(const void* memory, int len, const upb_fielddef*
putrawstr(memory, len, f, sink);
break;
case UPB_TYPE_MESSAGE: {
#if PHP_MAJOR_VERSION < 7
MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
#else
MessageHeader *submsg =
(MessageHeader*)((char*)(*(zend_object**)memory) -
XtOffsetOf(MessageHeader, std));
#endif
putrawsubmsg(submsg, f, sink, depth TSRMLS_CC);
zval* submsg = *(zval**)memory;
putsubmsg(submsg, f, sink, depth TSRMLS_CC);
break;
}
default:
@ -1074,11 +947,7 @@ static const char* raw_value(void* memory, const upb_fielddef* f) {
switch (upb_fielddef_type(f)) {
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
#if PHP_MAJOR_VERSION < 7
return Z_STRVAL_PP((zval**)memory);
#else
return ZSTR_VAL(*(zend_string**)memory);
#endif
break;
default:
return memory;
@ -1089,11 +958,8 @@ 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:
#if PHP_MAJOR_VERSION < 7
return Z_STRLEN_PP((zval**)memory);
#else
return ZSTR_LEN(*(zend_string**)memory);
#endif
break;
default:
return len;
}
@ -1101,6 +967,7 @@ static int raw_value_len(void* memory, int len, const upb_fielddef* f) {
static void putmap(zval* map, const upb_fielddef* f, upb_sink* sink,
int depth TSRMLS_DC) {
Map* self;
upb_sink subsink;
const upb_fielddef* key_field;
const upb_fielddef* value_field;
@ -1108,7 +975,8 @@ static void putmap(zval* map, const upb_fielddef* f, upb_sink* sink,
int len, size;
assert(map != NULL);
Map* intern = UNBOX(Map, map);
Map* intern =
(Map*)zend_object_store_get_object(map TSRMLS_CC);
size = upb_strtable_count(&intern->table);
if (size == 0) return;
@ -1145,12 +1013,6 @@ static void putmap(zval* map, const upb_fielddef* f, upb_sink* sink,
static void putmsg(zval* msg_php, const Descriptor* desc, upb_sink* sink,
int depth TSRMLS_DC) {
MessageHeader* msg = UNBOX(MessageHeader, msg_php);
putrawmsg(msg, desc, sink, depth TSRMLS_CC);
}
static void putrawmsg(MessageHeader* msg, const Descriptor* desc,
upb_sink* sink, int depth TSRMLS_DC) {
upb_msg_field_iter i;
upb_status status;
@ -1163,18 +1025,21 @@ static void putrawmsg(MessageHeader* msg, const Descriptor* desc,
"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;
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;
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(message_data(msg), oneof_case_offset, uint32_t) !=
upb_fielddef_number(f)) {
if (DEREF(msg, oneof_case_offset, uint32_t) != upb_fielddef_number(f)) {
continue;
}
// Otherwise, fall through to the appropriate singular-field handler
@ -1182,36 +1047,31 @@ static void putrawmsg(MessageHeader* msg, const Descriptor* desc,
}
if (is_map_field(f)) {
zval* map = CACHED_PTR_TO_ZVAL_PTR(
DEREF(message_data(msg), offset, CACHED_VALUE*));
zval* map = *DEREF(msg, offset, zval**);
if (map != NULL) {
putmap(map, f, sink, depth TSRMLS_CC);
}
} else if (upb_fielddef_isseq(f)) {
zval* array = CACHED_PTR_TO_ZVAL_PTR(
DEREF(message_data(msg), offset, CACHED_VALUE*));
zval* array = *DEREF(msg, offset, zval**);
if (array != NULL) {
putarray(array, f, sink, depth TSRMLS_CC);
}
} else if (upb_fielddef_isstring(f)) {
zval* str = CACHED_PTR_TO_ZVAL_PTR(
DEREF(message_data(msg), offset, CACHED_VALUE*));
zval* str = *DEREF(msg, offset, zval**);
if (Z_STRLEN_P(str) > 0) {
putstr(str, f, sink);
}
} else if (upb_fielddef_issubmsg(f)) {
putsubmsg(CACHED_PTR_TO_ZVAL_PTR(
DEREF(message_data(msg), offset, CACHED_VALUE*)),
f, sink, depth TSRMLS_CC);
putsubmsg(*DEREF(msg, offset, zval**), f, sink, depth TSRMLS_CC);
} else {
upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
#define T(upbtypeconst, upbtype, ctype, default_value) \
case upbtypeconst: { \
ctype value = DEREF(message_data(msg), offset, ctype); \
if (value != default_value) { \
upb_sink_put##upbtype(sink, sel, value); \
} \
#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)) {
@ -1278,23 +1138,18 @@ static void putrawstr(const char* str, int len, const upb_fielddef* f,
upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
}
static void putsubmsg(zval* submsg_php, const upb_fielddef* f, upb_sink* sink,
static void putsubmsg(zval* submsg, const upb_fielddef* f, upb_sink* sink,
int depth TSRMLS_DC) {
if (Z_TYPE_P(submsg_php) == IS_NULL) return;
MessageHeader *submsg = UNBOX(MessageHeader, submsg_php);
putrawsubmsg(submsg, f, sink, depth TSRMLS_CC);
}
static void putrawsubmsg(MessageHeader* submsg, const upb_fielddef* f,
upb_sink* sink, int depth TSRMLS_DC) {
upb_sink subsink;
if (Z_TYPE_P(submsg) == IS_NULL) return;
zval* php_descriptor = get_def_obj(upb_fielddef_msgsubdef(f));
Descriptor* subdesc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(upb_fielddef_msgsubdef(f)));
(Descriptor*)zend_object_store_get_object(php_descriptor TSRMLS_CC);
upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
putrawmsg(submsg, subdesc, &subsink, depth + 1 TSRMLS_CC);
putmsg(submsg, subdesc, &subsink, depth + 1 TSRMLS_CC);
upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
}
@ -1306,10 +1161,9 @@ static void putarray(zval* array, const upb_fielddef* f, upb_sink* sink,
int size, i;
assert(array != NULL);
RepeatedField* intern = UNBOX(RepeatedField, array);
HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
size = zend_hash_num_elements(ht);
// size = zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array));
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);
@ -1336,28 +1190,12 @@ static void putarray(zval* array, const upb_fielddef* f, upb_sink* sink,
T(UPB_TYPE_UINT64, uint64, uint64_t)
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES: {
#if PHP_MAJOR_VERSION < 7
const char* rawstr = Z_STRVAL_P(*(zval**)memory);
int len = Z_STRLEN_P(*(zval**)memory);
#else
const char* rawstr = ZSTR_VAL(*(zend_string**)memory);
int len = ZSTR_LEN(*(zend_string**)memory);
#endif
putrawstr(rawstr, len, f, &subsink);
case UPB_TYPE_BYTES:
putstr(*((zval**)memory), f, &subsink);
break;
}
case UPB_TYPE_MESSAGE: {
#if PHP_MAJOR_VERSION < 7
MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
#else
MessageHeader *submsg =
(MessageHeader*)((char*)(*(zend_object**)memory) -
XtOffsetOf(MessageHeader, std));
#endif
putrawsubmsg(submsg, f, &subsink, depth TSRMLS_CC);
case UPB_TYPE_MESSAGE:
putsubmsg(*((zval**)memory), f, &subsink, depth TSRMLS_CC);
break;
}
#undef T
}
@ -1397,8 +1235,9 @@ static const upb_handlers* msgdef_json_serialize_handlers(
// -----------------------------------------------------------------------------
PHP_METHOD(Message, serializeToString) {
zval* php_descriptor = get_ce_obj(Z_OBJCE_P(getThis()));
Descriptor* desc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
(Descriptor*)zend_object_store_get_object(php_descriptor TSRMLS_CC);
stringsink sink;
stringsink_init(&sink);
@ -1414,7 +1253,7 @@ PHP_METHOD(Message, serializeToString) {
putmsg(getThis(), desc, upb_pb_encoder_input(encoder), 0 TSRMLS_CC);
PHP_PROTO_RETVAL_STRINGL(sink.ptr, sink.len, 1);
RETVAL_STRINGL(sink.ptr, sink.len, 1);
stackenv_uninit(&se);
stringsink_uninit(&sink);
@ -1422,13 +1261,13 @@ PHP_METHOD(Message, serializeToString) {
}
PHP_METHOD(Message, mergeFromString) {
zval* php_descriptor = get_ce_obj(Z_OBJCE_P(getThis()));
Descriptor* desc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
MessageHeader* msg = UNBOX(MessageHeader, getThis());
(Descriptor*)zend_object_store_get_object(php_descriptor TSRMLS_CC);
MessageHeader* msg = zend_object_store_get_object(getThis() TSRMLS_CC);
char *data = NULL;
PHP_PROTO_SIZE data_len;
int data_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) ==
FAILURE) {
return;
@ -1451,8 +1290,9 @@ PHP_METHOD(Message, mergeFromString) {
}
PHP_METHOD(Message, jsonEncode) {
zval* php_descriptor = get_ce_obj(Z_OBJCE_P(getThis()));
Descriptor* desc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
(Descriptor*)zend_object_store_get_object(php_descriptor TSRMLS_CC);
zend_bool preserve_proto_fieldnames = false;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b",
@ -1474,7 +1314,7 @@ PHP_METHOD(Message, jsonEncode) {
putmsg(getThis(), desc, upb_json_printer_input(printer), 0 TSRMLS_CC);
PHP_PROTO_RETVAL_STRINGL(sink.ptr, sink.len, 1);
RETVAL_STRINGL(sink.ptr, sink.len, 1);
stackenv_uninit(&se);
stringsink_uninit(&sink);
@ -1482,9 +1322,10 @@ PHP_METHOD(Message, jsonEncode) {
}
PHP_METHOD(Message, jsonDecode) {
zval* php_descriptor = get_ce_obj(Z_OBJCE_P(getThis()));
Descriptor* desc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
MessageHeader* msg = UNBOX(MessageHeader, getThis());
(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;

View file

@ -103,16 +103,16 @@ static bool table_key(Map* self, zval* 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_by_array(self->key_type, NULL, buf, key TSRMLS_CC); \
*out_key = buf; \
*out_length = native_slot_size(self->key_type); \
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 TSRMLS_CC); \
*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)
@ -148,7 +148,7 @@ static zend_function_entry map_field_methods[] = {
// Forward declare static functions.
static void map_field_write_dimension(zval *object, zval *key,
static bool map_field_write_dimension(zval *object, zval *key,
zval *value TSRMLS_DC);
// -----------------------------------------------------------------------------
@ -163,7 +163,8 @@ static void map_begin_internal(Map *map, MapIter *iter) {
upb_strtable_begin(&iter->it, &map->table);
}
static HashTable *map_field_get_gc(zval *object, CACHED_VALUE **table, int *n) {
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.
@ -172,101 +173,111 @@ static HashTable *map_field_get_gc(zval *object, CACHED_VALUE **table, int *n) {
return NULL;
}
// Define map value element free function.
#if PHP_MAJOR_VERSION < 7
static inline void php_proto_map_string_release(void *value) {
zval_ptr_dtor(value);
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->write_dimension = map_field_write_dimension;
map_field_handlers->get_gc = map_field_get_gc;
}
static inline void php_proto_map_object_release(void *value) {
zval_ptr_dtor(value);
}
#else
static inline void php_proto_map_string_release(void *value) {
zend_string* object = *(zend_string**)value;
zend_string_release(object);
}
static inline void php_proto_map_object_release(void *value) {
zend_object* object = *(zend_object**)value;
if(--GC_REFCOUNT(object) == 0) {
zend_objects_store_del(object);
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.");
}
}
#endif
// Define object free method.
PHP_PROTO_OBJECT_FREE_START(Map, map_field)
MapIter it;
int len;
for (map_begin_internal(intern, &it); !map_done(&it); map_next(&it)) {
upb_value value = map_iter_value(&it, &len);
void *mem = upb_value_memory(&value);
switch (intern->value_type) {
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:
php_proto_map_object_release(mem);
break;
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
php_proto_map_string_release(mem);
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);
}
upb_strtable_uninit(&intern->table);
PHP_PROTO_OBJECT_FREE_END
PHP_PROTO_OBJECT_DTOR_START(Map, map_field)
PHP_PROTO_OBJECT_DTOR_END
// Define object create method.
PHP_PROTO_OBJECT_CREATE_START(Map, map_field)
// 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.");
}
PHP_PROTO_OBJECT_CREATE_END(Map, map_field)
// Init class entry.
PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\MapField", Map,
map_field)
zend_class_implements(map_field_type TSRMLS_CC, 2, spl_ce_ArrayAccess,
spl_ce_Countable);
map_field_handlers->write_dimension = map_field_write_dimension;
map_field_handlers->get_gc = map_field_get_gc;
PHP_PROTO_INIT_CLASS_END
void map_field_create_with_field(const zend_class_entry *ce,
const upb_fielddef *field,
CACHED_VALUE *map_field PHP_PROTO_TSRMLS_DC) {
void map_field_create_with_field(zend_class_entry *ce, const upb_fielddef *field,
zval **map_field TSRMLS_DC) {
const upb_fielddef *key_field = map_field_key(field);
const upb_fielddef *value_field = map_field_value(field);
map_field_create_with_type(
ce, upb_fielddef_type(key_field), upb_fielddef_type(value_field),
field_type_class(value_field TSRMLS_CC), map_field PHP_PROTO_TSRMLS_CC);
field_type_class(value_field TSRMLS_CC), map_field TSRMLS_CC);
}
void map_field_create_with_type(const zend_class_entry *ce,
upb_fieldtype_t key_type,
void map_field_create_with_type(zend_class_entry *ce, upb_fieldtype_t key_type,
upb_fieldtype_t value_type,
const zend_class_entry *msg_ce,
CACHED_VALUE *map_field PHP_PROTO_TSRMLS_DC) {
CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(CACHED_PTR_TO_ZVAL_PTR(map_field),
map_field_type);
Map *intern = UNBOX(Map, CACHED_TO_ZVAL_PTR(*map_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);
intern->key_type = key_type;
intern->value_type = value_type;
intern->msg_ce = msg_ce;
}
static void map_field_free_element(void *object) {
}
// -----------------------------------------------------------------------------
// MapField Handlers
// -----------------------------------------------------------------------------
static bool map_field_read_dimension(zval *object, zval *key, int type,
CACHED_VALUE *retval TSRMLS_DC) {
Map *intern = UNBOX(Map, object);
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;
@ -281,7 +292,7 @@ static bool map_field_read_dimension(zval *object, zval *key, int type,
if (upb_strtable_lookup2(&intern->table, keyval, length, &v)) {
void* mem = upb_value_memory(&v);
native_slot_get_by_array(intern->value_type, mem, retval TSRMLS_CC);
native_slot_get(intern->value_type, mem, retval TSRMLS_CC);
return true;
} else {
zend_error(E_USER_ERROR, "Given key doesn't exist.");
@ -299,9 +310,9 @@ bool map_index_set(Map *intern, const char* keyval, int length, upb_value v) {
return true;
}
static void map_field_write_dimension(zval *object, zval *key,
static bool map_field_write_dimension(zval *object, zval *key,
zval *value TSRMLS_DC) {
Map *intern = UNBOX(Map, object);
Map *intern = (Map *)zend_object_store_get_object(object TSRMLS_CC);
char keybuf[TABLE_KEY_BUF_LENGTH];
const char* keyval = NULL;
@ -309,14 +320,14 @@ static void map_field_write_dimension(zval *object, zval *key,
upb_value v;
void* mem;
if (!table_key(intern, key, keybuf, &keyval, &length TSRMLS_CC)) {
return;
return false;
}
mem = upb_value_memory(&v);
memset(mem, 0, native_slot_size(intern->value_type));
if (!native_slot_set_by_array(intern->value_type, intern->msg_ce, mem,
value TSRMLS_CC)) {
return;
if (!native_slot_set(intern->value_type, intern->msg_ce, mem,
value TSRMLS_CC)) {
return false;
}
#ifndef NDEBUG
v.ctype = UPB_CTYPE_UINT64;
@ -326,12 +337,14 @@ static void map_field_write_dimension(zval *object, zval *key,
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;
return false;
}
return true;
}
static bool map_field_unset_dimension(zval *object, zval *key TSRMLS_DC) {
Map *intern = UNBOX(Map, object);
Map *intern = (Map *)zend_object_store_get_object(object TSRMLS_CC);
char keybuf[TABLE_KEY_BUF_LENGTH];
const char* keyval = NULL;
@ -362,7 +375,8 @@ PHP_METHOD(MapField, __construct) {
return;
}
Map *intern = UNBOX(Map, getThis());
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;
@ -390,7 +404,7 @@ PHP_METHOD(MapField, offsetExists) {
return;
}
Map *intern = UNBOX(Map, getThis());
Map *intern = (Map *)zend_object_store_get_object(getThis() TSRMLS_CC);
char keybuf[TABLE_KEY_BUF_LENGTH];
const char* keyval = NULL;
@ -413,7 +427,7 @@ PHP_METHOD(MapField, offsetGet) {
return;
}
map_field_read_dimension(getThis(), index, BP_VAR_R,
ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
return_value_ptr TSRMLS_CC);
}
PHP_METHOD(MapField, offsetSet) {
@ -435,7 +449,8 @@ PHP_METHOD(MapField, offsetUnset) {
}
PHP_METHOD(MapField, count) {
Map *intern = UNBOX(Map, getThis());
Map *intern =
(Map *)zend_object_store_get_object(getThis() TSRMLS_CC);
if (zend_parse_parameters_none() == FAILURE) {
return;

View file

@ -53,64 +53,40 @@ static zend_function_entry message_methods[] = {
// Forward declare static functions.
#if PHP_MAJOR_VERSION < 7
static void message_set_property(zval* object, zval* member, zval* value,
php_proto_zend_literal key TSRMLS_DC);
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,
php_proto_zend_literal key TSRMLS_DC);
static HashTable* message_get_gc(zval* object, zval*** table, int* n TSRMLS_DC);
#else
static void message_set_property(zval* object, zval* member, zval* value,
void** cache_slot);
static zval* message_get_property(zval* object, zval* member, int type,
void** cache_slot, zval* rv);
static zval* message_get_property_ptr_ptr(zval* object, zval* member, int type,
void** cache_slot);
static HashTable* message_get_gc(zval* object, zval** table, int* n);
#endif
const zend_literal* key TSRMLS_DC);
static HashTable* message_get_properties(zval* object TSRMLS_DC);
static HashTable* message_get_gc(zval* object, zval*** table, int* n TSRMLS_DC);
static zend_object_value message_create(zend_class_entry* ce TSRMLS_DC);
static void message_free(void* object TSRMLS_DC);
// -----------------------------------------------------------------------------
// PHP Message Handlers
// -----------------------------------------------------------------------------
// Define object free method.
PHP_PROTO_OBJECT_FREE_START(MessageHeader, message)
FREE(intern->data);
PHP_PROTO_OBJECT_FREE_END
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);
PHP_PROTO_OBJECT_DTOR_START(MessageHeader, message)
PHP_PROTO_OBJECT_DTOR_END
// Define object create method.
PHP_PROTO_OBJECT_CREATE_START(MessageHeader, message)
// Because php call this create func before calling the sub-message's
// constructor defined in PHP, it's possible that the decriptor of this class
// hasn't been added to descritpor pool (when the class is first
// instantiated). In that case, we will defer the initialization of the custom
// data to the parent Message's constructor, which will be called by
// sub-message's constructors after the descriptor has been added.
PHP_PROTO_OBJECT_CREATE_END(MessageHeader, message)
// Init class entry.
PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\Message",
MessageHeader, message)
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;
message_handlers->get_properties = message_get_properties;
message_handlers->get_gc = message_get_gc;
PHP_PROTO_INIT_CLASS_END
}
#if PHP_MAJOR_VERSION < 7
static void message_set_property(zval* object, zval* member, zval* value,
php_proto_zend_literal key TSRMLS_DC) {
#else
static void message_set_property(zval* object, zval* member, zval* value,
void** cache_slot) {
#endif
const zend_literal* key TSRMLS_DC) {
if (Z_TYPE_P(member) != IS_STRING) {
zend_error(E_USER_ERROR, "Unexpected type for field name");
return;
@ -124,7 +100,7 @@ static void message_set_property(zval* object, zval* member, zval* value,
const upb_fielddef* field;
MessageHeader* self = UNBOX(MessageHeader, object);
MessageHeader* self = zend_object_store_get_object(object TSRMLS_CC);
field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member));
if (field == NULL) {
@ -134,55 +110,46 @@ static void message_set_property(zval* object, zval* member, zval* value,
layout_set(self->descriptor->layout, self, field, value TSRMLS_CC);
}
#if PHP_MAJOR_VERSION < 7
static zval* message_get_property(zval* object, zval* member, int type,
const zend_literal* key TSRMLS_DC) {
#else
static zval* message_get_property(zval* object, zval* member, int type,
void** cache_slot, zval* rv) {
#endif
if (Z_TYPE_P(member) != IS_STRING) {
zend_error(E_USER_ERROR, "Property name has to be a string.");
return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL;
return EG(uninitialized_zval_ptr);
}
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 PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL;
return EG(uninitialized_zval_ptr);
}
MessageHeader* self = UNBOX(MessageHeader, object);
zend_property_info* property_info = NULL;
// 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);
const upb_fielddef* field;
field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member));
if (field == NULL) {
return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL;
return EG(uninitialized_zval_ptr);
}
zend_property_info* property_info;
#if PHP_MAJOR_VERSION < 7
property_info =
zend_get_property_info(Z_OBJCE_P(object), member, true TSRMLS_CC);
return layout_get(
self->descriptor->layout, message_data(self), field,
&Z_OBJ_P(object)->properties_table[property_info->offset] TSRMLS_CC);
#else
property_info =
zend_get_property_info(Z_OBJCE_P(object), Z_STR_P(member), true);
return layout_get(
self->descriptor->layout, message_data(self), field,
OBJ_PROP(Z_OBJ_P(object), property_info->offset) TSRMLS_CC);
#endif
}
#if PHP_MAJOR_VERSION < 7
static zval** message_get_property_ptr_ptr(zval* object, zval* member, int type,
php_proto_zend_literal key
TSRMLS_DC) {
#else
static zval* message_get_property_ptr_ptr(zval* object, zval* member, int type,
void** cache_slot) {
#endif
const zend_literal* key TSRMLS_DC) {
return NULL;
}
@ -190,37 +157,68 @@ static HashTable* message_get_properties(zval* object TSRMLS_DC) {
return NULL;
}
static HashTable* message_get_gc(zval* object, CACHED_VALUE** table,
int* n TSRMLS_DC) {
zend_object* zobj = Z_OBJ_P(object);
*table = zobj->properties_table;
*n = zobj->ce->default_properties_count;
return NULL;
static HashTable* message_get_gc(zval* object, zval*** table, int* n TSRMLS_DC) {
zend_object* zobj = Z_OBJ_P(object);
*table = zobj->properties_table;
*n = zobj->ce->default_properties_count;
return NULL;
}
// -----------------------------------------------------------------------------
// C Message Utilities
// -----------------------------------------------------------------------------
void* message_data(MessageHeader* msg) {
return msg->data;
void* message_data(void* msg) {
return ((uint8_t*)msg) + sizeof(MessageHeader);
}
void custom_data_init(const zend_class_entry* ce,
MessageHeader* intern PHP_PROTO_TSRMLS_DC) {
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(ce));
intern->data = ALLOC_N(uint8_t, desc->layout->size);
memset(message_data(intern), 0, desc->layout->size);
static void message_free(void* object TSRMLS_DC) {
MessageHeader* msg = (MessageHeader*)object;
int i;
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);
}
static zend_object_value message_create(zend_class_entry* ce TSRMLS_DC) {
zend_object_value return_value;
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().
intern->descriptor = desc;
layout_init(desc->layout, message_data(intern),
intern->std.properties_table PHP_PROTO_TSRMLS_CC);
msg->descriptor = desc;
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 TSRMLS_CC);
return_value.handle = zend_objects_store_put(
msg, (zend_objects_store_dtor_t)zend_objects_destroy_object, message_free,
NULL TSRMLS_CC);
return_value.handlers = message_handlers;
return return_value;
}
void build_class_from_descriptor(
PHP_PROTO_HASHTABLE_VALUE php_descriptor TSRMLS_DC) {
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, php_descriptor);
void message_create_with_type(zend_class_entry* ce, zval** message TSRMLS_DC) {
MAKE_STD_ZVAL(*message);
Z_TYPE_PP(message) = IS_OBJECT;
Z_OBJVAL_PP(message) = ce->create_object(ce TSRMLS_CC);
Z_DELREF_PP(message);
}
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)) {
@ -245,18 +243,26 @@ void build_class_from_descriptor(
// modified. As a result, the first created instance will be a normal zend
// object. Here, we manually modify it to our message in such a case.
PHP_METHOD(Message, __construct) {
zend_class_entry* ce = Z_OBJCE_P(getThis());
if (EXPECTED(class_added(ce))) {
MessageHeader* intern = UNBOX(MessageHeader, getThis());
custom_data_init(ce, intern PHP_PROTO_TSRMLS_CC);
if (Z_OBJVAL_P(getThis()).handlers != message_handlers) {
zend_class_entry* ce = Z_OBJCE_P(getThis());
zval_dtor(getThis());
Z_OBJVAL_P(getThis()) = message_create(ce TSRMLS_CC);
}
}
PHP_METHOD(Message, clear) {
MessageHeader* msg = UNBOX(MessageHeader, getThis());
MessageHeader* msg =
(MessageHeader*)zend_object_store_get_object(getThis() TSRMLS_CC);
Descriptor* desc = msg->descriptor;
zend_class_entry* ce = desc->klass;
int i;
for (i = 0; i < msg->std.ce->default_properties_count; i++) {
zval_ptr_dtor(&msg->std.properties_table[i]);
}
efree(msg->std.properties_table);
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 TSRMLS_CC);
@ -269,8 +275,10 @@ PHP_METHOD(Message, mergeFrom) {
return;
}
MessageHeader* from = UNBOX(MessageHeader, value);
MessageHeader* to = UNBOX(MessageHeader, getThis());
MessageHeader* from =
(MessageHeader*)zend_object_store_get_object(value TSRMLS_CC);
MessageHeader* to =
(MessageHeader*)zend_object_store_get_object(getThis() TSRMLS_CC);
if(from->descriptor != to->descriptor) {
zend_error(E_USER_ERROR, "Cannot merge messages with different class.");
@ -281,37 +289,36 @@ PHP_METHOD(Message, mergeFrom) {
}
PHP_METHOD(Message, readOneof) {
PHP_PROTO_LONG index;
long index;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
FAILURE) {
return;
}
MessageHeader* msg = UNBOX(MessageHeader, getThis());
MessageHeader* msg =
(MessageHeader*)zend_object_store_get_object(getThis() TSRMLS_CC);
const upb_fielddef* field = upb_msgdef_itof(msg->descriptor->msgdef, index);
int property_cache_index =
msg->descriptor->layout->fields[upb_fielddef_index(field)].cache_index;
zval* property_ptr = OBJ_PROP(Z_OBJ_P(getThis()), property_cache_index);
zval** cache_ptr = &(msg->std.properties_table)[property_cache_index];
// Unlike singular fields, oneof fields share cached property. So we cannot
// let lay_get modify the cached property. Instead, we pass in the return
// value directly.
layout_get(msg->descriptor->layout, message_data(msg), field,
ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
&return_value TSRMLS_CC);
}
PHP_METHOD(Message, writeOneof) {
PHP_PROTO_LONG index;
long index;
zval* value;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &index, &value) ==
FAILURE) {
return;
}
MessageHeader* msg = UNBOX(MessageHeader, getThis());
MessageHeader* msg =
(MessageHeader*)zend_object_store_get_object(getThis() TSRMLS_CC);
const upb_fielddef* field = upb_msgdef_itof(msg->descriptor->msgdef, index);
@ -320,18 +327,19 @@ PHP_METHOD(Message, writeOneof) {
PHP_METHOD(Message, whichOneof) {
char* oneof_name;
PHP_PROTO_SIZE length;
int length;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &oneof_name,
&length) == FAILURE) {
return;
}
MessageHeader* msg = UNBOX(MessageHeader, getThis());
MessageHeader* msg =
(MessageHeader*)zend_object_store_get_object(getThis() TSRMLS_CC);
const upb_oneofdef* oneof =
upb_msgdef_ntoo(msg->descriptor->msgdef, oneof_name, length);
const char* oneof_case_name = layout_get_oneof_case(
msg->descriptor->layout, message_data(msg), oneof TSRMLS_CC);
PHP_PROTO_RETURN_STRING(oneof_case_name, 1);
RETURN_STRING(oneof_case_name, 1);
}

View file

@ -13,16 +13,16 @@
<date>2017-01-13</date>
<time>16:06:07</time>
<version>
<release>3.3.0</release>
<api>3.3.0</api>
<release>3.2.0a1</release>
<api>3.2.0a1</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
<release>alpha</release>
<api>alpha</api>
</stability>
<license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
<notes>
GA release.
Second alpha release.
</notes>
<contents>
<dir baseinstalldir="/" name="/">
@ -87,21 +87,5 @@ First alpha release
Second alpha release.
</notes>
</release>
<release>
<version>
<release>3.3.0</release>
<api>3.3.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2017-04-28</date>
<time>16:06:07</time>
<license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
<notes>
GA release.
</notes>
</release>
</changelog>
</package>

View file

@ -55,60 +55,39 @@ static void add_to_table(HashTable* t, const void* def, void* value) {
uint nIndex = (ulong)def & t->nTableMask;
zval* pDest = NULL;
php_proto_zend_hash_index_update(t, (zend_ulong)def, &value, sizeof(zval*),
(void**)&pDest);
zend_hash_index_update(t, (zend_ulong)def, &value, sizeof(zval*), (void**)&pDest);
}
static void* get_from_table(const HashTable* t, const void* def) {
void** value;
if (php_proto_zend_hash_index_find(t, (zend_ulong)def, (void**)&value) ==
FAILURE) {
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 bool exist_in_table(const HashTable* t, const void* def) {
void** value;
return (php_proto_zend_hash_index_find(t, (zend_ulong)def, (void**)&value) ==
SUCCESS);
}
static void add_to_list(HashTable* t, void* value) {
zval* pDest = NULL;
php_proto_zend_hash_next_index_insert(t, &value, sizeof(void*),
(void**)&pDest);
zend_hash_next_index_insert(t, &value, sizeof(void*), (void**)&pDest);
}
void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value) {
#if PHP_MAJOR_VERSION < 7
void add_def_obj(const void* def, zval* value) {
Z_ADDREF_P(value);
#else
++GC_REFCOUNT(value);
#endif
add_to_table(upb_def_to_php_obj_map, def, value);
}
PHP_PROTO_HASHTABLE_VALUE get_def_obj(const void* def) {
return (PHP_PROTO_HASHTABLE_VALUE)get_from_table(upb_def_to_php_obj_map, def);
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, PHP_PROTO_HASHTABLE_VALUE value) {
#if PHP_MAJOR_VERSION < 7
void add_ce_obj(const void* ce, zval* value) {
Z_ADDREF_P(value);
#else
++GC_REFCOUNT(value);
#endif
add_to_table(ce_to_php_obj_map, ce, value);
}
PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce) {
return (PHP_PROTO_HASHTABLE_VALUE)get_from_table(ce_to_php_obj_map, ce);
}
bool class_added(const void* ce) {
return exist_in_table(ce_to_php_obj_map, ce);
zval* get_ce_obj(const void* ce) {
return (zval*)get_from_table(ce_to_php_obj_map, ce);
}
// -----------------------------------------------------------------------------
@ -146,23 +125,12 @@ static PHP_GINIT_FUNCTION(protobuf) {
static PHP_GSHUTDOWN_FUNCTION(protobuf) {
}
#if PHP_MAJOR_VERSION >= 7
static void php_proto_hashtable_descriptor_release(zval* value) {
void* ptr = Z_PTR_P(value);
zend_object* object = *(zend_object**)ptr;
if(--GC_REFCOUNT(object) == 0) {
zend_objects_store_del(object);
}
efree(ptr);
}
#endif
static PHP_RINIT_FUNCTION(protobuf) {
ALLOC_HASHTABLE(upb_def_to_php_obj_map);
zend_hash_init(upb_def_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0);
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, HASHTABLE_VALUE_DTOR, 0);
zend_hash_init(ce_to_php_obj_map, 16, NULL, ZVAL_PTR_DTOR, 0);
generated_pool = NULL;
generated_pool_php = NULL;
@ -177,12 +145,10 @@ static PHP_RSHUTDOWN_FUNCTION(protobuf) {
zend_hash_destroy(ce_to_php_obj_map);
FREE_HASHTABLE(ce_to_php_obj_map);
#if PHP_MAJOR_VERSION < 7
if (generated_pool_php != NULL) {
zval_dtor(generated_pool_php);
FREE_ZVAL(generated_pool_php);
}
#endif
return 0;
}
@ -204,7 +170,6 @@ static PHP_MINIT_FUNCTION(protobuf) {
static PHP_MSHUTDOWN_FUNCTION(protobuf) {
PEFREE(message_handlers);
PEFREE(repeated_field_handlers);
PEFREE(repeated_field_iter_handlers);
PEFREE(map_field_handlers);
return 0;

View file

@ -37,328 +37,11 @@
#include "upb.h"
#define PHP_PROTOBUF_EXTNAME "protobuf"
#define PHP_PROTOBUF_VERSION "3.3.0"
#define PHP_PROTOBUF_VERSION "3.2.0a1"
#define MAX_LENGTH_OF_INT64 20
#define SIZEOF_INT64 8
// -----------------------------------------------------------------------------
// PHP7 Wrappers
// ----------------------------------------------------------------------------
#if PHP_MAJOR_VERSION < 7
#define php_proto_zend_literal const zend_literal*
#define PHP_PROTO_CASE_IS_BOOL IS_BOOL
#define PHP_PROTO_SIZE int
#define PHP_PROTO_LONG long
#define PHP_PROTO_TSRMLS_DC TSRMLS_DC
#define PHP_PROTO_TSRMLS_CC TSRMLS_CC
// PHP String
#define PHP_PROTO_ZVAL_STRING(zval_ptr, s, copy) \
ZVAL_STRING(zval_ptr, s, copy)
#define PHP_PROTO_ZVAL_STRINGL(zval_ptr, s, len, copy) \
ZVAL_STRINGL(zval_ptr, s, len, copy)
#define PHP_PROTO_RETURN_STRING(s, copy) RETURN_STRING(s, copy)
#define PHP_PROTO_RETURN_STRINGL(s, len, copy) RETURN_STRINGL(s, len, copy)
#define PHP_PROTO_RETVAL_STRINGL(s, len, copy) RETVAL_STRINGL(s, len, copy)
#define php_proto_zend_make_printable_zval(from, to) \
{ \
int use_copy; \
zend_make_printable_zval(from, to, &use_copy); \
}
// PHP Array
#define PHP_PROTO_HASH_OF(array) Z_ARRVAL_P(array)
#define php_proto_zend_hash_index_update(ht, h, pData, nDataSize, pDest) \
zend_hash_index_update(ht, h, pData, nDataSize, pDest)
#define php_proto_zend_hash_index_find(ht, h, pDest) \
zend_hash_index_find(ht, h, pDest)
#define php_proto_zend_hash_next_index_insert(ht, pData, nDataSize, pDest) \
zend_hash_next_index_insert(ht, pData, nDataSize, pDest)
#define php_proto_zend_hash_get_current_data_ex(ht, pDest, pos) \
zend_hash_get_current_data_ex(ht, pDest, pos)
// PHP Object
#define PHP_PROTO_WRAP_OBJECT_START(name) \
struct name { \
zend_object std;
#define PHP_PROTO_WRAP_OBJECT_END \
};
#define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \
void LOWWERNAME##_init(TSRMLS_D) { \
zend_class_entry class_type; \
const char* class_name = CLASSNAME; \
INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \
LOWWERNAME##_methods); \
LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
LOWWERNAME##_type->create_object = LOWWERNAME##_create; \
LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers); \
memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(), \
sizeof(zend_object_handlers));
#define PHP_PROTO_INIT_CLASS_END \
}
#define PHP_PROTO_OBJECT_CREATE_START(NAME, LOWWERNAME) \
static zend_object_value LOWWERNAME##_create( \
zend_class_entry* ce TSRMLS_DC) { \
PHP_PROTO_ALLOC_CLASS_OBJECT(NAME, ce); \
zend_object_std_init(&intern->std, ce TSRMLS_CC); \
object_properties_init(&intern->std, ce);
#define PHP_PROTO_OBJECT_CREATE_END(NAME, LOWWERNAME) \
PHP_PROTO_FREE_CLASS_OBJECT(NAME, LOWWERNAME##_free, LOWWERNAME##_handlers); \
}
#define PHP_PROTO_OBJECT_FREE_START(classname, lowername) \
void lowername##_free(void* object TSRMLS_DC) { \
classname* intern = object;
#define PHP_PROTO_OBJECT_FREE_END \
zend_object_std_dtor(&intern->std TSRMLS_CC); \
efree(intern); \
}
#define PHP_PROTO_OBJECT_DTOR_START(classname, lowername)
#define PHP_PROTO_OBJECT_DTOR_END
#define CACHED_VALUE zval*
#define CACHED_TO_ZVAL_PTR(VALUE) (VALUE)
#define CACHED_PTR_TO_ZVAL_PTR(VALUE) (*VALUE)
#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (&VALUE)
#define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \
ZVAL_OBJ(zval_ptr, class_type->create_object(class_type TSRMLS_CC));
#define PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(value) \
SEPARATE_ZVAL_IF_NOT_REF(value)
#define PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL EG(uninitialized_zval_ptr)
#define OBJ_PROP(PROPERTIES, OFFSET) (PROPERTIES)->properties_table[OFFSET]
#define php_proto_zval_ptr_dtor(zval_ptr) \
zval_ptr_dtor(&(zval_ptr))
#define PHP_PROTO_ALLOC_CLASS_OBJECT(class_object, class_type) \
class_object* intern; \
intern = (class_object*)emalloc(sizeof(class_object)); \
memset(intern, 0, sizeof(class_object));
#define PHP_PROTO_FREE_CLASS_OBJECT(class_object, class_object_free, handler) \
zend_object_value retval = {0}; \
retval.handle = zend_objects_store_put( \
intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, \
class_object_free, NULL TSRMLS_CC); \
retval.handlers = handler; \
return retval;
#define PHP_PROTO_ALLOC_ARRAY(zval_ptr) \
ALLOC_HASHTABLE(Z_ARRVAL_P(zval_ptr)); \
Z_TYPE_P(zval_ptr) = IS_ARRAY;
#define ZVAL_OBJ(zval_ptr, call_create) \
Z_TYPE_P(zval_ptr) = IS_OBJECT; \
Z_OBJVAL_P(zval_ptr) = call_create;
#define UNBOX(class_name, val) \
(class_name*)zend_object_store_get_object(val TSRMLS_CC);
#define UNBOX_HASHTABLE_VALUE(class_name, val) UNBOX(class_name, val)
#define HASHTABLE_VALUE_DTOR ZVAL_PTR_DTOR
#define PHP_PROTO_HASHTABLE_VALUE zval*
#define CREATE_HASHTABLE_VALUE(OBJ, WRAPPED_OBJ, OBJ_TYPE, OBJ_CLASS_ENTRY) \
OBJ_TYPE* OBJ; \
PHP_PROTO_HASHTABLE_VALUE WRAPPED_OBJ; \
MAKE_STD_ZVAL(WRAPPED_OBJ); \
ZVAL_OBJ(WRAPPED_OBJ, \
OBJ_CLASS_ENTRY->create_object(OBJ_CLASS_ENTRY TSRMLS_CC)); \
OBJ = UNBOX_HASHTABLE_VALUE(OBJ_TYPE, WRAPPED_OBJ); \
Z_DELREF_P(desc_php);
#define PHP_PROTO_CE_DECLARE zend_class_entry**
#define PHP_PROTO_CE_UNREF(ce) (*ce)
#define php_proto_zend_lookup_class(name, name_length, ce) \
zend_lookup_class(name, name_length, ce TSRMLS_CC)
#else // PHP_MAJOR_VERSION >= 7
#define php_proto_zend_literal void**
#define PHP_PROTO_CASE_IS_BOOL IS_TRUE: case IS_FALSE
#define PHP_PROTO_SIZE size_t
#define PHP_PROTO_LONG zend_long
#define PHP_PROTO_TSRMLS_DC
#define PHP_PROTO_TSRMLS_CC
// PHP String
#define PHP_PROTO_ZVAL_STRING(zval_ptr, s, copy) \
ZVAL_STRING(zval_ptr, s)
#define PHP_PROTO_ZVAL_STRINGL(zval_ptr, s, len, copy) \
ZVAL_STRINGL(zval_ptr, s, len)
#define PHP_PROTO_RETURN_STRING(s, copy) RETURN_STRING(s)
#define PHP_PROTO_RETURN_STRINGL(s, len, copy) RETURN_STRINGL(s, len)
#define PHP_PROTO_RETVAL_STRINGL(s, len, copy) RETVAL_STRINGL(s, len)
#define php_proto_zend_make_printable_zval(from, to) \
zend_make_printable_zval(from, to)
// PHP Array
#define PHP_PROTO_HASH_OF(array) Z_ARRVAL_P(&array)
static inline int php_proto_zend_hash_index_update(HashTable* ht, ulong h,
void* pData, uint nDataSize,
void** pDest) {
void* result = NULL;
result = zend_hash_index_update_mem(ht, h, pData, nDataSize);
if (pDest != NULL) *pDest = result;
return result != NULL ? SUCCESS : FAILURE;
}
static inline int php_proto_zend_hash_index_find(const HashTable* ht, ulong h,
void** pDest) {
void* result = NULL;
result = zend_hash_index_find_ptr(ht, h);
if (pDest != NULL) *pDest = result;
return result != NULL ? SUCCESS : FAILURE;
}
static inline int php_proto_zend_hash_next_index_insert(HashTable* ht,
void* pData,
uint nDataSize,
void** pDest) {
void* result = NULL;
result = zend_hash_next_index_insert_mem(ht, pData, nDataSize);
if (pDest != NULL) *pDest = result;
return result != NULL ? SUCCESS : FAILURE;
}
static inline int php_proto_zend_hash_get_current_data_ex(HashTable* ht,
void** pDest,
HashPosition* pos) {
void* result = NULL;
result = zend_hash_get_current_data_ex(ht, pos);
if (pDest != NULL) *pDest = result;
return result != NULL ? SUCCESS : FAILURE;
}
// PHP Object
#define PHP_PROTO_WRAP_OBJECT_START(name) struct name {
#define PHP_PROTO_WRAP_OBJECT_END \
zend_object std; \
};
#define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \
void LOWWERNAME##_init(TSRMLS_D) { \
zend_class_entry class_type; \
const char* class_name = CLASSNAME; \
INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \
LOWWERNAME##_methods); \
LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
LOWWERNAME##_type->create_object = LOWWERNAME##_create; \
LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers); \
memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(), \
sizeof(zend_object_handlers)); \
LOWWERNAME##_handlers->free_obj = LOWWERNAME##_free; \
LOWWERNAME##_handlers->dtor_obj = LOWWERNAME##_dtor; \
LOWWERNAME##_handlers->offset = XtOffsetOf(CAMELNAME, std);
#define PHP_PROTO_INIT_CLASS_END \
}
#define PHP_PROTO_OBJECT_FREE_START(classname, lowername) \
void lowername##_free(zend_object* object) { \
classname* intern = \
(classname*)((char*)object - XtOffsetOf(classname, std));
#define PHP_PROTO_OBJECT_FREE_END \
}
#define PHP_PROTO_OBJECT_DTOR_START(classname, lowername) \
void lowername##_dtor(zend_object* object) { \
classname* intern = \
(classname*)((char*)object - XtOffsetOf(classname, std));
#define PHP_PROTO_OBJECT_DTOR_END \
zend_object_std_dtor(object TSRMLS_CC); \
}
#define PHP_PROTO_OBJECT_CREATE_START(NAME, LOWWERNAME) \
static zend_object* LOWWERNAME##_create(zend_class_entry* ce TSRMLS_DC) { \
PHP_PROTO_ALLOC_CLASS_OBJECT(NAME, ce); \
zend_object_std_init(&intern->std, ce TSRMLS_CC); \
object_properties_init(&intern->std, ce);
#define PHP_PROTO_OBJECT_CREATE_END(NAME, LOWWERNAME) \
PHP_PROTO_FREE_CLASS_OBJECT(NAME, LOWWERNAME##_free, LOWWERNAME##_handlers); \
}
#define CACHED_VALUE zval
#define CACHED_TO_ZVAL_PTR(VALUE) (&VALUE)
#define CACHED_PTR_TO_ZVAL_PTR(VALUE) (VALUE)
#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (VALUE)
#define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \
ZVAL_OBJ(zval_ptr, class_type->create_object(class_type));
#define PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(value) ;
#define PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL &EG(uninitialized_zval)
#define php_proto_zval_ptr_dtor(zval_ptr) \
zval_ptr_dtor(zval_ptr)
#define PHP_PROTO_ALLOC_CLASS_OBJECT(class_object, class_type) \
class_object* intern; \
int size = sizeof(class_object) + zend_object_properties_size(class_type); \
intern = ecalloc(1, size); \
memset(intern, 0, size);
#define PHP_PROTO_FREE_CLASS_OBJECT(class_object, class_object_free, handler) \
intern->std.handlers = handler; \
return &intern->std;
#define PHP_PROTO_ALLOC_ARRAY(zval_ptr) \
ZVAL_NEW_ARR(zval_ptr)
#define UNBOX(class_name, val) \
(class_name*)((char*)Z_OBJ_P(val) - XtOffsetOf(class_name, std));
#define UNBOX_HASHTABLE_VALUE(class_name, val) \
(class_name*)((char*)val - XtOffsetOf(class_name, std))
#define HASHTABLE_VALUE_DTOR php_proto_hashtable_descriptor_release
#define PHP_PROTO_HASHTABLE_VALUE zend_object*
#define CREATE_HASHTABLE_VALUE(OBJ, WRAPPED_OBJ, OBJ_TYPE, OBJ_CLASS_ENTRY) \
OBJ_TYPE* OBJ; \
PHP_PROTO_HASHTABLE_VALUE WRAPPED_OBJ; \
WRAPPED_OBJ = OBJ_CLASS_ENTRY->create_object(OBJ_CLASS_ENTRY); \
OBJ = UNBOX_HASHTABLE_VALUE(OBJ_TYPE, WRAPPED_OBJ); \
--GC_REFCOUNT(WRAPPED_OBJ);
#define PHP_PROTO_CE_DECLARE zend_class_entry*
#define PHP_PROTO_CE_UNREF(ce) (ce)
static inline int php_proto_zend_lookup_class(
const char* name, int name_length, zend_class_entry** ce TSRMLS_DC) {
zend_string *zstr_name = zend_string_init(name, name_length, 0);
*ce = zend_lookup_class(zstr_name);
zend_string_release(zstr_name);
return *ce != NULL ? SUCCESS : FAILURE;
}
#endif // PHP_MAJOR_VERSION >= 7
// -----------------------------------------------------------------------------
// Forward Declaration
// ----------------------------------------------------------------------------
@ -372,8 +55,7 @@ struct MessageHeader;
struct MessageLayout;
struct RepeatedField;
struct RepeatedFieldIter;
struct Map;
struct Oneof;
struct MapField;
typedef struct DescriptorPool DescriptorPool;
typedef struct Descriptor Descriptor;
@ -384,8 +66,7 @@ typedef struct MessageHeader MessageHeader;
typedef struct MessageLayout MessageLayout;
typedef struct RepeatedField RepeatedField;
typedef struct RepeatedFieldIter RepeatedFieldIter;
typedef struct Map Map;
typedef struct Oneof Oneof;
typedef struct MapField MapField;
// -----------------------------------------------------------------------------
// Globals.
@ -407,14 +88,13 @@ void message_init(TSRMLS_D);
// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
// instances.
void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value);
PHP_PROTO_HASHTABLE_VALUE get_def_obj(const void* def);
void add_def_obj(const void* def, zval* value);
zval* get_def_obj(const void* def);
// Global map from PHP class entries to wrapper Descriptor/EnumDescriptor
// instances.
void add_ce_obj(const void* ce, PHP_PROTO_HASHTABLE_VALUE value);
PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce);
bool class_added(const void* ce);
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;
@ -423,25 +103,20 @@ extern zend_class_entry* repeated_field_type;
// Descriptor.
// -----------------------------------------------------------------------------
PHP_PROTO_WRAP_OBJECT_START(DescriptorPool)
struct DescriptorPool {
zend_object std;
upb_symtab* symtab;
HashTable* pending_list;
PHP_PROTO_WRAP_OBJECT_END
};
PHP_METHOD(DescriptorPool, getGeneratedPool);
PHP_METHOD(DescriptorPool, internalAddGeneratedFile);
// wrapper of generated pool
#if PHP_MAJOR_VERSION < 7
extern zval* generated_pool_php;
void descriptor_pool_free(void* object TSRMLS_DC);
#else
extern zend_object *generated_pool_php;
void descriptor_pool_free(zend_object* object);
#endif
extern zval* generated_pool_php; // wrapper of generated pool
extern DescriptorPool* generated_pool; // The actual generated pool
PHP_PROTO_WRAP_OBJECT_START(Descriptor)
struct Descriptor {
zend_object std;
const upb_msgdef* msgdef;
MessageLayout* layout;
zend_class_entry* klass; // begins as NULL
@ -451,21 +126,23 @@ PHP_PROTO_WRAP_OBJECT_START(Descriptor)
const upb_handlers* pb_serialize_handlers;
const upb_handlers* json_serialize_handlers;
const upb_handlers* json_serialize_handlers_preserve;
PHP_PROTO_WRAP_OBJECT_END
};
extern zend_class_entry* descriptor_type;
void descriptor_name_set(Descriptor *desc, const char *name);
PHP_PROTO_WRAP_OBJECT_START(FieldDescriptor)
struct FieldDescriptor {
zend_object std;
const upb_fielddef* fielddef;
PHP_PROTO_WRAP_OBJECT_END
};
PHP_PROTO_WRAP_OBJECT_START(EnumDescriptor)
struct EnumDescriptor {
zend_object std;
const upb_enumdef* enumdef;
zend_class_entry* klass; // begins as NULL
// VALUE module; // begins as nil
PHP_PROTO_WRAP_OBJECT_END
};
extern zend_class_entry* enum_descriptor_type;
@ -473,15 +150,13 @@ extern zend_class_entry* enum_descriptor_type;
// Message class creation.
// -----------------------------------------------------------------------------
void* message_data(MessageHeader* msg);
void custom_data_init(const zend_class_entry* ce,
MessageHeader* msg PHP_PROTO_TSRMLS_DC);
void* message_data(void* msg);
void message_create_with_type(zend_class_entry* ce, zval** message TSRMLS_DC);
// 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(
PHP_PROTO_HASHTABLE_VALUE php_descriptor TSRMLS_DC);
void build_class_from_descriptor(zval* php_descriptor TSRMLS_DC);
extern zend_object_handlers* message_handlers;
@ -552,17 +227,18 @@ struct MessageLayout {
size_t size;
};
PHP_PROTO_WRAP_OBJECT_START(MessageHeader)
void* data; // Point to the real message data.
// Place needs to be consistent with map_parse_frame_data_t.
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.
PHP_PROTO_WRAP_OBJECT_END
// The real message data is appended after MessageHeader.
};
MessageLayout* create_layout(const upb_msgdef* msgdef);
void layout_init(MessageLayout* layout, void* storage,
CACHED_VALUE* properties_table PHP_PROTO_TSRMLS_DC);
zval** properties_table TSRMLS_DC);
zval* layout_get(MessageLayout* layout, const void* storage,
const upb_fielddef* field, CACHED_VALUE* cache TSRMLS_DC);
const upb_fielddef* field, zval** cache TSRMLS_DC);
void layout_set(MessageLayout* layout, MessageHeader* header,
const upb_fielddef* field, zval* val TSRMLS_DC);
void layout_merge(MessageLayout* layout, MessageHeader* from,
@ -632,12 +308,7 @@ PHP_METHOD(Util, checkRepeatedField);
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 TSRMLS_DC);
// String/Message is stored differently in array/map from normal message fields.
// So we need to make a special method to handle that.
bool native_slot_set_by_array(upb_fieldtype_t type,
const zend_class_entry* klass, void* memory,
zval* value TSRMLS_DC);
void native_slot_init(upb_fieldtype_t type, void* memory, void* cache);
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
@ -646,13 +317,8 @@ void native_slot_init(upb_fieldtype_t type, void* memory, void* cache);
// 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,
CACHED_VALUE* cache TSRMLS_DC);
// String/Message is stored differently in array/map from normal message fields.
// So we need to make a special method to handle that.
void native_slot_get_by_array(upb_fieldtype_t type, const void* memory,
CACHED_VALUE* cache TSRMLS_DC);
void native_slot_get_default(upb_fieldtype_t type,
CACHED_VALUE* cache TSRMLS_DC);
zval** cache TSRMLS_DC);
void native_slot_get_default(upb_fieldtype_t type, zval** cache TSRMLS_DC);
// -----------------------------------------------------------------------------
// Map Field.
@ -660,12 +326,13 @@ void native_slot_get_default(upb_fieldtype_t type,
extern zend_object_handlers* map_field_handlers;
PHP_PROTO_WRAP_OBJECT_START(Map)
typedef struct {
zend_object std;
upb_fieldtype_t key_type;
upb_fieldtype_t value_type;
const zend_class_entry* msg_ce; // class entry for value message
upb_strtable table;
PHP_PROTO_WRAP_OBJECT_END
} Map;
typedef struct {
Map* self;
@ -682,14 +349,14 @@ upb_value map_iter_value(MapIter* iter, int* len);
const upb_fielddef* map_entry_key(const upb_msgdef* msgdef);
const upb_fielddef* map_entry_value(const upb_msgdef* msgdef);
void map_field_create_with_field(const zend_class_entry* ce,
const upb_fielddef* field,
CACHED_VALUE* map_field PHP_PROTO_TSRMLS_DC);
void map_field_create_with_type(const zend_class_entry* ce,
upb_fieldtype_t key_type,
zend_object_value map_field_create(zend_class_entry *ce TSRMLS_DC);
void map_field_create_with_field(zend_class_entry *ce, const upb_fielddef *field,
zval **map_field TSRMLS_DC);
void map_field_create_with_type(zend_class_entry *ce, upb_fieldtype_t key_type,
upb_fieldtype_t value_type,
const zend_class_entry* msg_ce,
CACHED_VALUE* map_field PHP_PROTO_TSRMLS_DC);
const zend_class_entry *msg_ce,
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
@ -715,36 +382,33 @@ PHP_METHOD(MapField, count);
// -----------------------------------------------------------------------------
extern zend_object_handlers* repeated_field_handlers;
extern zend_object_handlers* repeated_field_iter_handlers;
PHP_PROTO_WRAP_OBJECT_START(RepeatedField)
#if PHP_MAJOR_VERSION < 7
struct RepeatedField {
zend_object std;
zval* array;
#else
zval array;
#endif
upb_fieldtype_t type;
const zend_class_entry* msg_ce; // class entry for containing message
// (for message field only).
PHP_PROTO_WRAP_OBJECT_END
};
PHP_PROTO_WRAP_OBJECT_START(RepeatedFieldIter)
struct RepeatedFieldIter {
zend_object std;
RepeatedField* repeated_field;
long position;
PHP_PROTO_WRAP_OBJECT_END
};
void repeated_field_create_with_field(
zend_class_entry* ce, const upb_fielddef* field,
CACHED_VALUE* repeated_field PHP_PROTO_TSRMLS_DC);
void repeated_field_create_with_type(
zend_class_entry* ce, upb_fieldtype_t type, const zend_class_entry* msg_ce,
CACHED_VALUE* repeated_field PHP_PROTO_TSRMLS_DC);
void repeated_field_create_with_field(zend_class_entry* ce,
const upb_fielddef* field,
zval** repeated_field TSRMLS_DC);
void repeated_field_create_with_type(zend_class_entry* ce, upb_fieldtype_t type,
const zend_class_entry* msg_ce,
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 TSRMLS_DC);
// 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);
void repeated_field_push_native(RepeatedField *intern, void *value TSRMLS_DC);
PHP_METHOD(RepeatedField, __construct);
PHP_METHOD(RepeatedField, append);
@ -765,11 +429,12 @@ PHP_METHOD(RepeatedFieldIter, valid);
// Oneof Field.
// -----------------------------------------------------------------------------
PHP_PROTO_WRAP_OBJECT_START(Oneof)
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];
PHP_PROTO_WRAP_OBJECT_END
} Oneof;
// 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
@ -781,13 +446,24 @@ PHP_PROTO_WRAP_OBJECT_END
// -----------------------------------------------------------------------------
upb_fieldtype_t to_fieldtype(upb_descriptortype_t type);
const zend_class_entry* field_type_class(
const upb_fielddef* field PHP_PROTO_TSRMLS_DC);
const zend_class_entry *field_type_class(const upb_fielddef *field TSRMLS_DC);
// -----------------------------------------------------------------------------
// Utilities.
// -----------------------------------------------------------------------------
// PHP <-> C conversion.
#define UNBOX(class_name, val) \
(class_name*)zend_object_store_get_object(val TSRMLS_CC);
#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)
@ -795,15 +471,19 @@ const zend_class_entry* field_type_class(
#define FREE(object) efree(object)
#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
#if PHP_MAJOR_VERSION < 7
#define Z_OBJ_P(zval_p) \
((zend_object*)(EG(objects_store) \
.object_buckets[Z_OBJ_HANDLE_P(zval_p)] \
.bucket.obj.object))
#endif
#endif // __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__

View file

@ -57,7 +57,7 @@ size_t native_slot_size(upb_fieldtype_t type) {
}
}
static bool native_slot_is_default(upb_fieldtype_t type, const void* memory) {
static bool native_slot_is_default(upb_fieldtype_t type, void* memory) {
switch (type) {
#define CASE_TYPE(upb_type, c_type) \
case UPB_TYPE_##upb_type: { \
@ -75,17 +75,15 @@ static bool native_slot_is_default(upb_fieldtype_t type, const void* memory) {
#undef CASE_TYPE
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
return Z_STRLEN_P(CACHED_PTR_TO_ZVAL_PTR(DEREF(memory, CACHED_VALUE*))) ==
0;
return Z_STRLEN_PP(DEREF(memory, zval**)) == 0;
case UPB_TYPE_MESSAGE:
return Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(DEREF(memory, CACHED_VALUE*))) ==
IS_NULL;
return Z_TYPE_PP(DEREF(memory, zval**)) == IS_NULL;
default: return false;
}
}
bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
void* memory, zval* value PHP_PROTO_TSRMLS_DC) {
void* memory, zval* value TSRMLS_DC) {
switch (type) {
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES: {
@ -97,14 +95,14 @@ bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
return false;
}
zval* cached_zval = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
if (EXPECTED(cached_zval != NULL)) {
#if PHP_MAJOR_VERSION < 7
if (*(zval**)memory != NULL) {
REPLACE_ZVAL_VALUE((zval**)memory, value, 1);
#else
zend_assign_to_variable(cached_zval, value, IS_CV);
#endif
} 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;
}
@ -117,18 +115,13 @@ bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
zend_error(E_USER_ERROR, "Given message does not have correct class.");
return false;
}
zval* property_ptr = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
if (EXPECTED(property_ptr != value)) {
php_proto_zval_ptr_dtor(property_ptr);
if (EXPECTED(DEREF(memory, zval*) != value)) {
if (DEREF(memory, zval*) != NULL) {
zval_ptr_dtor((zval**)memory);
}
DEREF(memory, zval*) = value;
Z_ADDREF_P(value);
}
#if PHP_MAJOR_VERSION < 7
DEREF(memory, zval*) = value;
Z_ADDREF_P(value);
#else
ZVAL_ZVAL(property_ptr, value, 1, 0);
#endif
break;
}
@ -158,59 +151,7 @@ bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
return true;
}
bool native_slot_set_by_array(upb_fieldtype_t type,
const zend_class_entry* klass, void* memory,
zval* value TSRMLS_DC) {
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;
}
// Handles repeated/map string field. Memory provided by
// RepeatedField/Map is not initialized.
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(DEREF(memory, zval*));
PHP_PROTO_ZVAL_STRINGL(DEREF(memory, zval*), Z_STRVAL_P(value),
Z_STRLEN_P(value), 1);
#else
*(zend_string**)memory = zend_string_dup(Z_STR_P(value), 0);
#endif
break;
}
case UPB_TYPE_MESSAGE: {
if (Z_TYPE_P(value) != IS_OBJECT) {
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 PHP_MAJOR_VERSION < 7
if (EXPECTED(DEREF(memory, zval*) != value)) {
DEREF(memory, zval*) = value;
Z_ADDREF_P(value);
}
#else
DEREF(memory, zend_object*) = Z_OBJ_P(value);
++GC_REFCOUNT(Z_OBJ_P(value));
#endif
break;
}
default:
return native_slot_set(type, klass, memory, value TSRMLS_CC);
}
return true;
}
void native_slot_init(upb_fieldtype_t type, void* memory, void* cache) {
void native_slot_init(upb_fieldtype_t type, void* memory, zval** cache) {
zval* tmp = NULL;
switch (type) {
case UPB_TYPE_FLOAT:
@ -225,7 +166,7 @@ void native_slot_init(upb_fieldtype_t type, void* memory, void* cache) {
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
case UPB_TYPE_MESSAGE:
DEREF(memory, CACHED_VALUE*) = cache;
DEREF(memory, zval**) = cache;
break;
case UPB_TYPE_ENUM:
case UPB_TYPE_INT32:
@ -246,38 +187,38 @@ void native_slot_init(upb_fieldtype_t type, void* memory, void* cache) {
}
void native_slot_get(upb_fieldtype_t type, const void* memory,
CACHED_VALUE* cache TSRMLS_DC) {
zval** cache TSRMLS_DC) {
switch (type) {
#define CASE(upb_type, php_type, c_type) \
case UPB_TYPE_##upb_type: \
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); \
ZVAL_##php_type(CACHED_PTR_TO_ZVAL_PTR(cache), DEREF(memory, c_type)); \
return;
#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(ENUM, LONG, uint32_t)
CASE(FLOAT, DOUBLE, float)
CASE(DOUBLE, DOUBLE, double)
CASE(BOOL, BOOL, int8_t)
CASE(INT32, LONG, int32_t)
CASE(ENUM, LONG, uint32_t)
#undef CASE
#if SIZEOF_LONG == 4
#define CASE(upb_type, c_type) \
case UPB_TYPE_##upb_type: { \
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); \
char buffer[MAX_LENGTH_OF_INT64]; \
sprintf(buffer, "%lld", DEREF(memory, c_type)); \
PHP_PROTO_ZVAL_STRING(CACHED_PTR_TO_ZVAL_PTR(cache), buffer, 1); \
return; \
}
#define CASE(upb_type, c_type) \
case UPB_TYPE_##upb_type: { \
SEPARATE_ZVAL_IF_NOT_REF(cache); \
char buffer[MAX_LENGTH_OF_INT64]; \
sprintf(buffer, "%lld", DEREF(memory, c_type)); \
ZVAL_STRING(*cache, buffer, 1); \
return; \
}
#else
#define CASE(upb_type, c_type) \
case UPB_TYPE_##upb_type: { \
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); \
ZVAL_LONG(CACHED_PTR_TO_ZVAL_PTR(cache), DEREF(memory, c_type)); \
return; \
}
#define CASE(upb_type, c_type) \
case UPB_TYPE_##upb_type: { \
SEPARATE_ZVAL_IF_NOT_REF(cache); \
ZVAL_LONG(*cache, DEREF(memory, c_type)); \
return; \
}
#endif
CASE(UINT64, uint64_t)
CASE(INT64, int64_t)
@ -286,34 +227,32 @@ CASE(INT64, int64_t)
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.
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);
SEPARATE_ZVAL_IF_NOT_REF(cache);
int value = DEREF(memory, int32_t);
if (sizeof(int) == 8) {
value |= (-((value >> 31) & 0x1) & 0xFFFFFFFF00000000);
}
ZVAL_LONG(CACHED_PTR_TO_ZVAL_PTR(cache), value);
ZVAL_LONG(*cache, value);
return;
}
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES: {
// For optional string/bytes/message fields, the cache is owned by the
// containing message and should have been updated during
// setting/decoding. However, oneof accessor call this function by
// providing the return value directly, which is not the same as the cache
// value.
zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
if (CACHED_PTR_TO_ZVAL_PTR(cache) != value) {
PHP_PROTO_ZVAL_STRINGL(CACHED_PTR_TO_ZVAL_PTR(cache), Z_STRVAL_P(value),
Z_STRLEN_P(value), 1);
// 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: {
// Same as above for string/bytes fields.
zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
if (CACHED_PTR_TO_ZVAL_PTR(cache) != value) {
ZVAL_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cache), value, 1, 0);
zval* value = DEREF(memory, zval*);
if (*cache != value) {
ZVAL_ZVAL(*cache, value, 1, 0);
}
return;
}
@ -322,46 +261,12 @@ CASE(INT64, int64_t)
}
}
void native_slot_get_by_array(upb_fieldtype_t type, const void* memory,
CACHED_VALUE* cache TSRMLS_DC) {
void native_slot_get_default(upb_fieldtype_t type, zval** cache TSRMLS_DC) {
switch (type) {
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES: {
#if PHP_MAJOR_VERSION < 7
zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
if (EXPECTED(CACHED_PTR_TO_ZVAL_PTR(cache) != value)) {
PHP_PROTO_ZVAL_STRINGL(CACHED_PTR_TO_ZVAL_PTR(cache),
Z_STRVAL_P(value), Z_STRLEN_P(value), 1);
}
#else
ZVAL_NEW_STR(cache, zend_string_dup(*(zend_string**)memory, 0));
#endif
return;
}
case UPB_TYPE_MESSAGE: {
#if PHP_MAJOR_VERSION < 7
zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
if (EXPECTED(CACHED_PTR_TO_ZVAL_PTR(cache) != value)) {
ZVAL_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cache), value, 1, 0);
}
#else
++GC_REFCOUNT(*(zend_object**)memory);
ZVAL_OBJ(cache, *(zend_object**)memory);
#endif
return;
}
default:
native_slot_get(type, memory, cache TSRMLS_CC);
}
}
void native_slot_get_default(upb_fieldtype_t type,
CACHED_VALUE* cache TSRMLS_DC) {
switch (type) {
#define CASE(upb_type, php_type) \
case UPB_TYPE_##upb_type: \
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); \
ZVAL_##php_type(CACHED_PTR_TO_ZVAL_PTR(cache), 0); \
#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)
@ -374,19 +279,19 @@ void native_slot_get_default(upb_fieldtype_t type,
#undef CASE
#if SIZEOF_LONG == 4
#define CASE(upb_type) \
case UPB_TYPE_##upb_type: { \
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); \
PHP_PROTO_ZVAL_STRING(CACHED_PTR_TO_ZVAL_PTR(cache), "0", 1); \
return; \
}
#define CASE(upb_type) \
case UPB_TYPE_##upb_type: { \
SEPARATE_ZVAL_IF_NOT_REF(cache); \
ZVAL_STRING(*cache, "0", 1); \
return; \
}
#else
#define CASE(upb_type) \
case UPB_TYPE_##upb_type: { \
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache); \
ZVAL_LONG(CACHED_PTR_TO_ZVAL_PTR(cache), 0); \
return; \
}
#define CASE(upb_type) \
case UPB_TYPE_##upb_type: { \
SEPARATE_ZVAL_IF_NOT_REF(cache); \
ZVAL_LONG(*cache, 0); \
return; \
}
#endif
CASE(UINT64)
CASE(INT64)
@ -394,13 +299,13 @@ CASE(INT64)
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES: {
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);
PHP_PROTO_ZVAL_STRINGL(CACHED_PTR_TO_ZVAL_PTR(cache), "", 0, 1);
SEPARATE_ZVAL_IF_NOT_REF(cache);
ZVAL_STRINGL(*cache, "", 0, 1);
break;
}
case UPB_TYPE_MESSAGE: {
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);
ZVAL_NULL(CACHED_PTR_TO_ZVAL_PTR(cache));
SEPARATE_ZVAL_IF_NOT_REF(cache);
ZVAL_NULL(*cache);
return;
}
default:
@ -454,15 +359,14 @@ const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
return value_field;
}
const zend_class_entry* field_type_class(
const upb_fielddef* field PHP_PROTO_TSRMLS_DC) {
const zend_class_entry* field_type_class(const upb_fielddef* field TSRMLS_DC) {
if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
Descriptor* desc = UNBOX_HASHTABLE_VALUE(
Descriptor, get_def_obj(upb_fielddef_subdef(field)));
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) {
EnumDescriptor* desc = UNBOX_HASHTABLE_VALUE(
EnumDescriptor, get_def_obj(upb_fielddef_subdef(field)));
zval* desc_php = get_def_obj(upb_fielddef_subdef(field));
EnumDescriptor* desc = zend_object_store_get_object(desc_php TSRMLS_CC);
return desc->klass;
}
return NULL;
@ -597,7 +501,7 @@ void free_layout(MessageLayout* layout) {
}
void layout_init(MessageLayout* layout, void* storage,
CACHED_VALUE* properties_table PHP_PROTO_TSRMLS_DC) {
zval** properties_table TSRMLS_DC) {
int i;
upb_msg_field_iter it;
for (upb_msg_field_begin(&it, layout->msgdef), i = 0; !upb_msg_field_done(&it);
@ -606,27 +510,20 @@ void layout_init(MessageLayout* layout, void* storage,
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);
CACHED_VALUE* property_ptr = &properties_table[cache_index];
zval** property_ptr = &properties_table[cache_index];
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);
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(*property_ptr);
#endif
map_field_create_with_field(map_field_type, field,
property_ptr PHP_PROTO_TSRMLS_CC);
DEREF(memory, CACHED_VALUE*) = property_ptr;
map_field_create_with_field(map_field_type, field, property_ptr TSRMLS_CC);
DEREF(memory, zval**) = property_ptr;
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
zval_ptr_dtor(property_ptr);
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(*property_ptr);
#endif
repeated_field_create_with_field(repeated_field_type, field,
property_ptr PHP_PROTO_TSRMLS_CC);
DEREF(memory, CACHED_VALUE*) = property_ptr;
property_ptr TSRMLS_CC);
DEREF(memory, zval**) = property_ptr;
} else {
native_slot_init(upb_fielddef_type(field), memory, property_ptr);
}
@ -640,7 +537,7 @@ static void* value_memory(const upb_fielddef* field, void* memory) {
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
case UPB_TYPE_MESSAGE:
memory = DEREF(memory, CACHED_VALUE*);
memory = DEREF(memory, zval**);
break;
default:
// No operation
@ -650,7 +547,7 @@ static void* value_memory(const upb_fielddef* field, void* memory) {
}
zval* layout_get(MessageLayout* layout, const void* storage,
const upb_fielddef* field, CACHED_VALUE* cache TSRMLS_DC) {
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);
@ -661,13 +558,13 @@ zval* layout_get(MessageLayout* layout, const void* storage,
native_slot_get(upb_fielddef_type(field), value_memory(field, memory),
cache TSRMLS_CC);
}
return CACHED_PTR_TO_ZVAL_PTR(cache);
return *cache;
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
return CACHED_PTR_TO_ZVAL_PTR(cache);
return *cache;
} else {
native_slot_get(upb_fielddef_type(field), value_memory(field, memory),
cache TSRMLS_CC);
return CACHED_PTR_TO_ZVAL_PTR(cache);
return *cache;
}
}
@ -686,7 +583,8 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
switch (type) {
case UPB_TYPE_MESSAGE: {
const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg));
zval* desc_php = get_def_obj(msg);
Descriptor* desc = zend_object_store_get_object(desc_php TSRMLS_CC);
ce = desc->klass;
// Intentionally fall through.
}
@ -695,9 +593,9 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
int property_cache_index =
header->descriptor->layout->fields[upb_fielddef_index(field)]
.cache_index;
DEREF(memory, CACHED_VALUE*) =
DEREF(memory, zval**) =
&(header->std.properties_table)[property_cache_index];
memory = DEREF(memory, CACHED_VALUE*);
memory = DEREF(memory, zval**);
break;
}
default:
@ -708,130 +606,27 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
*oneof_case = upb_fielddef_number(field);
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
// Works for both repeated and map fields
memory = DEREF(memory, void**);
zval* property_ptr = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
if (EXPECTED(property_ptr != val)) {
#if PHP_MAJOR_VERSION < 7
REPLACE_ZVAL_VALUE((zval**)memory, val, 1);
#else
php_proto_zval_ptr_dtor(property_ptr);
ZVAL_ZVAL(property_ptr, val, 1, 0);
#endif
memory = DEREF(memory, zval**);
if (EXPECTED(DEREF(memory, zval*) != val)) {
zval_ptr_dtor(memory);
DEREF(memory, zval*) = val;
Z_ADDREF_P(val);
}
} else {
upb_fieldtype_t type = upb_fielddef_type(field);
zend_class_entry *ce = NULL;
if (type == UPB_TYPE_MESSAGE) {
const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg));
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 TSRMLS_CC);
}
}
static native_slot_merge(const upb_fielddef* field, const void* from_memory,
void* to_memory PHP_PROTO_TSRMLS_DC) {
upb_fieldtype_t type = upb_fielddef_type(field);
zend_class_entry* ce = NULL;
if (!native_slot_is_default(type, from_memory)) {
switch (type) {
#define CASE_TYPE(upb_type, c_type) \
case UPB_TYPE_##upb_type: { \
DEREF(to_memory, c_type) = DEREF(from_memory, c_type); \
break; \
}
CASE_TYPE(INT32, int32_t)
CASE_TYPE(UINT32, uint32_t)
CASE_TYPE(ENUM, int32_t)
CASE_TYPE(INT64, int64_t)
CASE_TYPE(UINT64, uint64_t)
CASE_TYPE(FLOAT, float)
CASE_TYPE(DOUBLE, double)
CASE_TYPE(BOOL, int8_t)
#undef CASE_TYPE
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
native_slot_set(type, NULL, value_memory(field, to_memory),
CACHED_PTR_TO_ZVAL_PTR(DEREF(
from_memory, CACHED_VALUE*)) PHP_PROTO_TSRMLS_CC);
break;
case UPB_TYPE_MESSAGE: {
const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg));
ce = desc->klass;
if (native_slot_is_default(type, to_memory)) {
#if PHP_MAJOR_VERSION < 7
SEPARATE_ZVAL_IF_NOT_REF((zval**)value_memory(field, to_memory));
#endif
CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(
CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*)), ce);
MessageHeader* submsg =
UNBOX(MessageHeader,
CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*)));
custom_data_init(ce, submsg PHP_PROTO_TSRMLS_CC);
}
MessageHeader* sub_from =
UNBOX(MessageHeader,
CACHED_PTR_TO_ZVAL_PTR(DEREF(from_memory, CACHED_VALUE*)));
MessageHeader* sub_to =
UNBOX(MessageHeader,
CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*)));
layout_merge(desc->layout, sub_from, sub_to PHP_PROTO_TSRMLS_CC);
break;
}
}
}
}
static native_slot_merge_by_array(const upb_fielddef* field, const void* from_memory,
void* to_memory PHP_PROTO_TSRMLS_DC) {
upb_fieldtype_t type = upb_fielddef_type(field);
switch (type) {
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES: {
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(DEREF(to_memory, zval*));
PHP_PROTO_ZVAL_STRINGL(DEREF(to_memory, zval*),
Z_STRVAL_P(*(zval**)from_memory),
Z_STRLEN_P(*(zval**)from_memory), 1);
#else
DEREF(to_memory, zend_string*) =
zend_string_dup(*(zend_string**)from_memory, 0);
#endif
break;
}
case UPB_TYPE_MESSAGE: {
const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg));
zend_class_entry* ce = desc->klass;
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(DEREF(to_memory, zval*));
CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(DEREF(to_memory, zval*), ce);
#else
DEREF(to_memory, zend_object*) = ce->create_object(ce TSRMLS_CC);
#endif
MessageHeader* sub_from = UNBOX_HASHTABLE_VALUE(
MessageHeader, DEREF(from_memory, PHP_PROTO_HASHTABLE_VALUE));
MessageHeader* sub_to = UNBOX_HASHTABLE_VALUE(
MessageHeader, DEREF(to_memory, PHP_PROTO_HASHTABLE_VALUE));
custom_data_init(ce, sub_to PHP_PROTO_TSRMLS_CC);
layout_merge(desc->layout, sub_from, sub_to PHP_PROTO_TSRMLS_CC);
break;
}
default:
native_slot_merge(field, from_memory, to_memory PHP_PROTO_TSRMLS_CC);
break;
}
}
void layout_merge(MessageLayout* layout, MessageHeader* from,
MessageHeader* to PHP_PROTO_TSRMLS_DC) {
MessageHeader* to TSRMLS_DC) {
int i, j;
upb_msg_field_iter it;
@ -844,10 +639,11 @@ void layout_merge(MessageLayout* layout, MessageHeader* from,
if (upb_fielddef_containingoneof(field)) {
uint32_t oneof_case_offset =
layout->fields[upb_fielddef_index(field)].case_offset;
layout->fields[upb_fielddef_index(field)].case_offset +
sizeof(MessageHeader);
// For a oneof, check that this field is actually present -- skip all the
// below if not.
if (DEREF((message_data(from) + oneof_case_offset), uint32_t) !=
if (DEREF(((uint8_t*)from + oneof_case_offset), uint32_t) !=
upb_fielddef_number(field)) {
continue;
}
@ -862,7 +658,7 @@ void layout_merge(MessageLayout* layout, MessageHeader* from,
case UPB_TYPE_BYTES: {
int property_cache_index =
layout->fields[upb_fielddef_index(field)].cache_index;
DEREF(to_memory, CACHED_VALUE*) =
DEREF(to_memory, zval**) =
&(to->std.properties_table)[property_cache_index];
break;
}
@ -880,57 +676,141 @@ void layout_merge(MessageLayout* layout, MessageHeader* from,
int size, key_length, value_length;
MapIter map_it;
zval* to_map_php =
CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*));
zval* from_map_php =
CACHED_PTR_TO_ZVAL_PTR(DEREF(from_memory, CACHED_VALUE*));
Map* to_map = UNBOX(Map, to_map_php);
Map* from_map = UNBOX(Map, from_map_php);
zval* to_map_php = *DEREF(to_memory, zval**);
zval* from_map_php = *DEREF(from_memory, zval**);
Map* to_map = zend_object_store_get_object(to_map_php TSRMLS_CC);
Map* from_map = zend_object_store_get_object(from_map_php TSRMLS_CC);
size = upb_strtable_count(&from_map->table);
if (size == 0) continue;
const upb_msgdef *mapentry_def = upb_fielddef_msgsubdef(field);
const upb_fielddef *value_field = upb_msgdef_itof(mapentry_def, 2);
for (map_begin(from_map_php, &map_it TSRMLS_CC); !map_done(&map_it);
map_next(&map_it)) {
const char* key = map_iter_key(&map_it, &key_length);
upb_value from_value = map_iter_value(&map_it, &value_length);
upb_value to_value;
void* from_mem = upb_value_memory(&from_value);
void* to_mem = upb_value_memory(&to_value);
memset(to_mem, 0, native_slot_size(to_map->value_type));
upb_value value = map_iter_value(&map_it, &value_length);
void* mem = upb_value_memory(&value);
switch (to_map->value_type) {
case UPB_TYPE_MESSAGE: {
zval* new_message;
message_create_with_type(to_map->msg_ce, &new_message TSRMLS_CC);
Z_ADDREF_P(new_message);
native_slot_merge_by_array(value_field, from_mem,
to_mem PHP_PROTO_TSRMLS_CC);
map_index_set(to_map, key, key_length, to_value);
zval* subdesc_php = get_ce_obj(to_map->msg_ce);
Descriptor* subdesc =
zend_object_store_get_object(subdesc_php TSRMLS_CC);
MessageHeader* sub_from =
(MessageHeader*)zend_object_store_get_object(DEREF(mem, zval*)
TSRMLS_CC);
MessageHeader* sub_to =
(MessageHeader*)zend_object_store_get_object(
new_message TSRMLS_CC);
layout_merge(subdesc->layout, sub_from, sub_to TSRMLS_CC);
DEREF(mem, zval*) = new_message;
break;
}
case UPB_TYPE_BYTES:
case UPB_TYPE_STRING:
Z_ADDREF_PP((zval**)mem);
break;
default:
break;
}
map_index_set(to_map, key, key_length, value);
}
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
zval* to_array_php = CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*));
zval* from_array_php = CACHED_PTR_TO_ZVAL_PTR(DEREF(from_memory, CACHED_VALUE*));
RepeatedField* to_array = UNBOX(RepeatedField, to_array_php);
RepeatedField* from_array = UNBOX(RepeatedField, from_array_php);
zval* to_array_php = *DEREF(to_memory, zval**);
zval* from_array_php = *DEREF(from_memory, zval**);
RepeatedField* to_array =
zend_object_store_get_object(to_array_php TSRMLS_CC);
RepeatedField* from_array =
zend_object_store_get_object(from_array_php TSRMLS_CC);
int size = zend_hash_num_elements(PHP_PROTO_HASH_OF(from_array->array));
int size = zend_hash_num_elements(HASH_OF(from_array->array));
if (size > 0) {
for (j = 0; j < size; j++) {
void* from_memory = NULL;
void* to_memory =
ALLOC_N(char, native_slot_size(upb_fielddef_type(field)));
memset(to_memory, 0, native_slot_size(upb_fielddef_type(field)));
php_proto_zend_hash_index_find(PHP_PROTO_HASH_OF(from_array->array),
j, (void**)&from_memory);
native_slot_merge_by_array(field, from_memory,
to_memory PHP_PROTO_TSRMLS_CC);
repeated_field_push_native(to_array, to_memory);
FREE(to_memory);
void* memory = NULL;
zend_hash_index_find(HASH_OF(from_array->array), j, (void**)&memory);
switch (to_array->type) {
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES: {
zval* str;
MAKE_STD_ZVAL(str);
ZVAL_STRINGL(str, Z_STRVAL_PP((zval**)memory),
Z_STRLEN_PP((zval**)memory), 1);
memory = &str;
break;
}
case UPB_TYPE_MESSAGE: {
zval* new_message;
message_create_with_type(from_array->msg_ce, &new_message TSRMLS_CC);
Z_ADDREF_P(new_message);
zval* subdesc_php = get_ce_obj(from_array->msg_ce);
Descriptor* subdesc =
zend_object_store_get_object(subdesc_php TSRMLS_CC);
MessageHeader* sub_from =
(MessageHeader*)zend_object_store_get_object(
DEREF(memory, zval*) TSRMLS_CC);
MessageHeader* sub_to =
(MessageHeader*)zend_object_store_get_object(
new_message TSRMLS_CC);
layout_merge(subdesc->layout, sub_from, sub_to TSRMLS_CC);
memory = &new_message;
}
default:
break;
}
repeated_field_push_native(to_array, memory TSRMLS_CC);
}
}
} else {
native_slot_merge(field, from_memory, to_memory PHP_PROTO_TSRMLS_CC);
upb_fieldtype_t type = upb_fielddef_type(field);
zend_class_entry *ce = NULL;
if (!native_slot_is_default(type, from_memory)) {
switch (type) {
#define CASE_TYPE(upb_type, c_type) \
case UPB_TYPE_##upb_type: { \
DEREF(to_memory, c_type) = DEREF(from_memory, c_type); \
break; \
}
CASE_TYPE(INT32, int32_t)
CASE_TYPE(UINT32, uint32_t)
CASE_TYPE(ENUM, int32_t)
CASE_TYPE(INT64, int64_t)
CASE_TYPE(UINT64, uint64_t)
CASE_TYPE(FLOAT, float)
CASE_TYPE(DOUBLE, double)
CASE_TYPE(BOOL, int8_t)
#undef CASE_TYPE
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
native_slot_set(type, NULL, value_memory(field, to_memory),
*DEREF(from_memory, zval**) TSRMLS_CC);
break;
case UPB_TYPE_MESSAGE: {
const 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;
if (native_slot_is_default(type, to_memory)) {
zval* new_message = NULL;
message_create_with_type(ce, &new_message TSRMLS_CC);
native_slot_set(type, ce, value_memory(field, to_memory),
new_message TSRMLS_CC);
}
MessageHeader* sub_from =
(MessageHeader*)zend_object_store_get_object(
*DEREF(from_memory, zval**) TSRMLS_CC);
MessageHeader* sub_to =
(MessageHeader*)zend_object_store_get_object(
*DEREF(to_memory, zval**) TSRMLS_CC);
layout_merge(desc->layout, sub_from, sub_to TSRMLS_CC);
}
}
}
}
}
}

View file

@ -325,18 +325,9 @@ CONVERT_TO_FLOAT(double);
bool protobuf_convert_to_bool(zval* from, int8_t* to) {
switch (Z_TYPE_P(from)) {
#if PHP_MAJOR_VERSION < 7
case IS_BOOL:
*to = (int8_t)Z_BVAL_P(from);
break;
#else
case IS_TRUE:
*to = 1;
break;
case IS_FALSE:
*to = 0;
break;
#endif
case IS_LONG:
*to = (int8_t)(Z_LVAL_P(from) != 0);
break;
@ -366,16 +357,12 @@ bool protobuf_convert_to_string(zval* from) {
case IS_STRING: {
return true;
}
#if PHP_MAJOR_VERSION < 7
case IS_BOOL:
#else
case IS_TRUE:
case IS_FALSE:
#endif
case IS_LONG:
case IS_DOUBLE: {
int use_copy;
zval tmp;
php_proto_zend_make_printable_zval(from, &tmp);
zend_make_printable_zval(from, &tmp, &use_copy);
ZVAL_COPY_VALUE(from, &tmp);
return true;
}
@ -430,45 +417,34 @@ PHP_METHOD(Util, checkMessage) {
PHP_METHOD(Util, checkRepeatedField) {
zval* val;
PHP_PROTO_LONG type;
long type;
const zend_class_entry* klass = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl|C", &val, &type,
&klass) == FAILURE) {
return;
}
#if PHP_MAJOR_VERSION >= 7
if (Z_ISREF_P(val)) {
ZVAL_DEREF(val);
}
#endif
if (Z_TYPE_P(val) == IS_ARRAY) {
HashTable* table = HASH_OF(val);
HashTable* table = Z_ARRVAL_P(val);
HashPosition pointer;
void* memory;
#if PHP_MAJOR_VERSION < 7
zval* repeated_field;
MAKE_STD_ZVAL(repeated_field);
#else
zval repeated_field;
#endif
repeated_field_create_with_type(repeated_field_type, to_fieldtype(type),
klass, &repeated_field TSRMLS_CC);
RepeatedField* intern =
(RepeatedField*)zend_object_store_get_object(repeated_field TSRMLS_CC);
for (zend_hash_internal_pointer_reset_ex(table, &pointer);
php_proto_zend_hash_get_current_data_ex(table, (void**)&memory,
&pointer) == SUCCESS;
zend_hash_get_current_data_ex(table, (void**)&memory, &pointer) ==
SUCCESS;
zend_hash_move_forward_ex(table, &pointer)) {
repeated_field_handlers->write_dimension(
CACHED_TO_ZVAL_PTR(repeated_field), NULL,
CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory) TSRMLS_CC);
repeated_field_handlers->write_dimension(repeated_field, NULL,
*(zval**)memory TSRMLS_CC);
}
Z_DELREF_P(CACHED_TO_ZVAL_PTR(repeated_field));
RETURN_ZVAL(CACHED_TO_ZVAL_PTR(repeated_field), 1, 0);
Z_DELREF_P(repeated_field);
RETURN_ZVAL(repeated_field, 1, 0);
} else if (Z_TYPE_P(val) == IS_OBJECT) {
if (!instanceof_function(Z_OBJCE_P(val), repeated_field_type TSRMLS_CC)) {
@ -476,7 +452,8 @@ PHP_METHOD(Util, checkRepeatedField) {
repeated_field_type->name);
return;
}
RepeatedField* intern = UNBOX(RepeatedField, val);
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;
@ -497,55 +474,43 @@ PHP_METHOD(Util, checkRepeatedField) {
PHP_METHOD(Util, checkMapField) {
zval* val;
PHP_PROTO_LONG key_type, value_type;
long key_type, value_type;
const zend_class_entry* klass = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zll|C", &val, &key_type,
&value_type, &klass) == FAILURE) {
return;
}
#if PHP_MAJOR_VERSION >= 7
if (Z_ISREF_P(val)) {
ZVAL_DEREF(val);
}
#endif
if (Z_TYPE_P(val) == IS_ARRAY) {
HashTable* table = Z_ARRVAL_P(val);
HashPosition pointer;
zval key;
zval key, *map_field;
void* value;
#if PHP_MAJOR_VERSION < 7
zval* map_field;
MAKE_STD_ZVAL(map_field);
#else
zval map_field;
#endif
map_field_create_with_type(map_field_type, to_fieldtype(key_type),
to_fieldtype(value_type), klass,
&map_field TSRMLS_CC);
Map* intern =
(Map*)zend_object_store_get_object(map_field TSRMLS_CC);
for (zend_hash_internal_pointer_reset_ex(table, &pointer);
php_proto_zend_hash_get_current_data_ex(table, (void**)&value,
&pointer) == SUCCESS;
zend_hash_get_current_data_ex(table, (void**)&value, &pointer) ==
SUCCESS;
zend_hash_move_forward_ex(table, &pointer)) {
zend_hash_get_current_key_zval_ex(table, &key, &pointer);
map_field_handlers->write_dimension(
CACHED_TO_ZVAL_PTR(map_field), &key,
CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value) TSRMLS_CC);
map_field_handlers->write_dimension(map_field, &key,
*(zval**)value TSRMLS_CC);
}
Z_DELREF_P(CACHED_TO_ZVAL_PTR(map_field));
RETURN_ZVAL(CACHED_TO_ZVAL_PTR(map_field), 1, 0);
Z_DELREF_P(map_field);
RETURN_ZVAL(map_field, 1, 0);
} else if (Z_TYPE_P(val) == IS_OBJECT) {
if (!instanceof_function(Z_OBJCE_P(val), map_field_type TSRMLS_CC)) {
zend_error(E_USER_ERROR, "Given value is not an instance of %s.",
map_field_type->name);
return;
}
Map* intern = UNBOX(Map, val);
Map* intern = (Map*)zend_object_store_get_object(val TSRMLS_CC);
if (to_fieldtype(key_type) != intern->key_type) {
zend_error(E_USER_ERROR, "Incorrect map field key type.");
return;

View file

@ -95,9 +95,6 @@ class DescriptorPool
foreach ($descriptor->getNestedType() as $nested_type) {
$this->addDescriptor($nested_type);
}
foreach ($descriptor->getEnumType() as $enum_type) {
$this->addEnumDescriptor($enum_type);
}
}
public function addEnumDescriptor($descriptor)

View file

@ -1,47 +0,0 @@
<?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 GPBDecodeException extends \Exception
{
public function __construct(
$message,
$code = 0,
\Exception $previous = null)
{
parent::__construct(
"Error occurred during parsing: " . $message,
$code,
$previous);
}
}

View file

@ -330,7 +330,6 @@ class InputStream
* passed unchanged to the corresponding call to popLimit().
*
* @param integer $byte_limit
* @throws Exception Fail to push limit.
*/
public function pushLimit($byte_limit)
{
@ -340,15 +339,19 @@ class InputStream
// security: byte_limit is possibly evil, so check for negative values
// and overflow.
if ($byte_limit >= 0 &&
$byte_limit <= PHP_INT_MAX - $current_position &&
$byte_limit <= $this->current_limit - $current_position) {
if ($byte_limit >= 0 && $byte_limit <= PHP_INT_MAX - $current_position) {
$this->current_limit = $current_position + $byte_limit;
$this->recomputeBufferLimits();
} else {
throw new GPBDecodeException("Fail to push limit.");
// 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;
}
@ -367,7 +370,7 @@ class InputStream
}
public function incrementRecursionDepthAndPushLimit(
$byte_limit, &$old_limit, &$recursion_budget)
$byte_limit, &$old_limit, &$recursion_budget)
{
$old_limit = $this->pushLimit($byte_limit);
$recursion_limit = --$this->recursion_limit;

View file

@ -155,6 +155,7 @@ function checkKey($key_type, &$key)
GPBUtil::checkString($key, true);
break;
default:
var_dump($key_type);
trigger_error(
"Given type cannot be map key.",
E_USER_ERROR);
@ -283,9 +284,6 @@ class MapField implements \ArrayAccess, \IteratorAggregate, \Countable
GPBUtil::checkString($value, true);
break;
case GPBType::MESSAGE:
if (is_null($value)) {
trigger_error("Map element cannot be null.", E_USER_ERROR);
}
GPBUtil::checkMessage($value, $this->klass);
break;
default:

View file

@ -224,57 +224,48 @@ class Message
switch ($field->getType()) {
case GPBType::DOUBLE:
if (!GPBWire::readDouble($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside double field.");
return false;
}
break;
case GPBType::FLOAT:
if (!GPBWire::readFloat($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside float field.");
return false;
}
break;
case GPBType::INT64:
if (!GPBWire::readInt64($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside int64 field.");
return false;
}
break;
case GPBType::UINT64:
if (!GPBWire::readUint64($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside uint64 field.");
return false;
}
break;
case GPBType::INT32:
if (!GPBWire::readInt32($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside int32 field.");
return false;
}
break;
case GPBType::FIXED64:
if (!GPBWire::readFixed64($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside fixed64 field.");
return false;
}
break;
case GPBType::FIXED32:
if (!GPBWire::readFixed32($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside fixed32 field.");
return false;
}
break;
case GPBType::BOOL:
if (!GPBWire::readBool($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside bool field.");
return false;
}
break;
case GPBType::STRING:
// TODO(teboring): Add utf-8 check.
if (!GPBWire::readString($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside string field.");
return false;
}
break;
case GPBType::GROUP:
@ -289,51 +280,43 @@ class Message
$value = new $klass;
}
if (!GPBWire::readMessage($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside message.");
return false;
}
break;
case GPBType::BYTES:
if (!GPBWire::readString($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside bytes field.");
return false;
}
break;
case GPBType::UINT32:
if (!GPBWire::readUint32($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside uint32 field.");
return false;
}
break;
case GPBType::ENUM:
// TODO(teboring): Check unknown enum value.
if (!GPBWire::readInt32($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside enum field.");
return false;
}
break;
case GPBType::SFIXED32:
if (!GPBWire::readSfixed32($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside sfixed32 field.");
return false;
}
break;
case GPBType::SFIXED64:
if (!GPBWire::readSfixed64($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside sfixed64 field.");
return false;
}
break;
case GPBType::SINT32:
if (!GPBWire::readSint32($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside sint32 field.");
return false;
}
break;
case GPBType::SINT64:
if (!GPBWire::readSint64($input, $value)) {
throw new GPBDecodeException(
"Unexpected EOF inside sint64 field.");
return false;
}
break;
default:
@ -362,21 +345,24 @@ class Message
}
if ($value_format === GPBWire::NORMAL_FORMAT) {
self::parseFieldFromStreamNoTag($input, $field, $value);
if (!self::parseFieldFromStreamNoTag($input, $field, $value)) {
return false;
}
} elseif ($value_format === GPBWire::PACKED_FORMAT) {
$length = 0;
if (!GPBWire::readInt32($input, $length)) {
throw new GPBDecodeException(
"Unexpected EOF inside packed length.");
return false;
}
$limit = $input->pushLimit($length);
$getter = $field->getGetter();
while ($input->bytesUntilLimit() > 0) {
self::parseFieldFromStreamNoTag($input, $field, $value);
if (!self::parseFieldFromStreamNoTag($input, $field, $value)) {
return false;
}
$this->$getter()[] = $value;
}
$input->popLimit($limit);
return;
return true;
} else {
return false;
}
@ -391,6 +377,8 @@ class Message
$setter = $field->getSetter();
$this->$setter($value);
}
return true;
}
/**
@ -579,8 +567,7 @@ class Message
* specified message.
*
* @param string $data Binary protobuf data.
* @return null.
* @throws Exception Invalid data.
* @return bool Return true on success.
*/
public function mergeFromString($data)
{
@ -608,7 +595,9 @@ class Message
continue;
}
$this->parseFieldFromStream($tag, $input, $field);
if (!$this->parseFieldFromStream($tag, $input, $field)) {
return false;
}
}
}

View file

@ -225,10 +225,6 @@ class RepeatedField implements \ArrayAccess, \IteratorAggregate, \Countable
GPBUtil::checkString($value, true);
break;
case GPBType::MESSAGE:
if (is_null($value)) {
trigger_error("RepeatedField element cannot be null.",
E_USER_ERROR);
}
GPBUtil::checkMessage($value, $this->klass);
break;
default:

View file

@ -210,12 +210,6 @@ class Descriptor
$nested_proto, $file_proto, $message_name_without_package));
}
// Handle nested enum.
foreach ($proto->getEnumType() as $enum_proto) {
$desc->addEnumType(EnumDescriptor::buildFromProto(
$enum_proto, $file_proto, $message_name_without_package));
}
// Handle oneof fields.
foreach ($proto->getOneofDecl() as $oneof_proto) {
$desc->addOneofDecl(
@ -226,36 +220,20 @@ class Descriptor
}
}
function getClassNamePrefix(
$classname,
$file_proto)
{
$option = $file_proto->getOptions();
$prefix = is_null($option) ? "" : $option->getPhpClassPrefix();
if ($prefix !== "") {
return $prefix;
}
$reserved_words = array("Empty");
foreach ($reserved_words as $reserved_word) {
if ($classname === $reserved_word) {
if ($file_proto->getPackage() === "google.protobuf") {
return "GPB";
} else {
return "PB";
}
}
}
return "";
}
function getClassNameWithoutPackage(
$name,
$file_proto)
{
$classname = implode('_', array_map('ucwords', explode('.', $name)));
return getClassNamePrefix($classname, $file_proto) . $classname;
if ($name === "Empty" && $file_proto->getPackage() === "google.protobuf") {
return "GPBEmpty";
} else {
$option = $file_proto->getOptions();
$prefix = is_null($option) ? "" : $option->getPhpClassPrefix();
// Nested message class names are seperated by '_', and package names
// are seperated by '\'.
return $prefix . implode('_', array_map('ucwords',
explode('.', $name)));
}
}
function getFullClassName(

View file

@ -751,13 +751,23 @@ class RepeatedFieldTest extends PHPUnit_Framework_TestCase
$arr []= $sub_m;
$this->assertSame(1, $arr[0]->getA());
$this->assertEquals(1, count($arr));
$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.
$sub_m = new TestMessage_Sub();
$sub_m->setA(2);
$arr [0]= $sub_m;
$this->assertSame(2, $arr[0]->getA());
$this->assertSame(1, $arr[0]->getA());
$arr [1]= $null;
$this->assertNull($arr[1]);
}
/**
@ -807,27 +817,6 @@ class RepeatedFieldTest extends PHPUnit_Framework_TestCase
$arr []= new TestMessage;
}
/**
* @expectedException PHPUnit_Framework_Error
*/
public function testMessageAppendNullFail()
{
$arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
$null = null;
$arr []= $null;
}
/**
* @expectedException PHPUnit_Framework_Error
*/
public function testMessageSetNullFail()
{
$arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
$arr []= new TestMessage_Sub();
$null = null;
$arr[0] = $null;
}
#########################################################
# Test offset type
#########################################################

View file

@ -211,204 +211,6 @@ class EncodeDecodeTest extends TestBase
$this->assertEquals(-1, $m->getOptionalInt32());
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidInt32()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('08'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidSubMessage()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('9A010108'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidInt64()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('10'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidUInt32()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('18'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidUInt64()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('20'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidSInt32()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('28'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidSInt64()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('30'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidFixed32()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('3D'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidFixed64()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('41'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidSFixed32()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('4D'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidSFixed64()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('51'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidFloat()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('5D'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidDouble()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('61'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidBool()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('68'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidStringLengthMiss()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('72'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidStringDataMiss()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('7201'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidBytesLengthMiss()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('7A'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidBytesDataMiss()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('7A01'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidEnum()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('8001'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidMessageLengthMiss()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('8A01'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidMessageDataMiss()
{
$m = new TestMessage();
$m->mergeFromString(hex2bin('8A0101'));
}
/**
* @expectedException Exception
*/
public function testDecodeInvalidPackedMessageLength()
{
$m = new TestPackedMessage();
$m->mergeFromString(hex2bin('D205'));
}
# TODO(teboring): Add test back when php implementation is ready for json
# encode/decode.
# public function testJsonEncode()

View file

@ -3,8 +3,10 @@
# gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which
# phpunit` --bootstrap autoload.php tmp_test.php
#
gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php well_known_test.php
gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php array_test.php
#
# gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
# # gdb --args 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
# # USE_ZEND_ALLOC=0 valgrind --leak-check=yes php
# -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php

View file

@ -1,7 +1,7 @@
<?php
require_once('generated/NoNamespaceEnum.php');
require_once('generated/NoNamespaceMessage.php');
require_once('generated/NoNameSpaceEnum.php');
require_once('generated/NoNameSpaceMessage.php');
require_once('test_base.php');
require_once('test_util.php');
@ -295,12 +295,6 @@ class GeneratedClassTest extends TestBase
$this->assertEquals(TestEnum::ONE, $m->getOptionalEnum());
}
public function testNestedEnum()
{
$m = new TestMessage();
$m->setOptionalNestedEnum(\Foo\TestMessage_NestedEnum::ZERO);
}
#########################################################
# Test float field.
#########################################################
@ -838,20 +832,12 @@ class GeneratedClassTest extends TestBase
public function testMessageWithoutNamespace()
{
$m = new TestMessage();
$sub = new NoNameSpaceMessage();
$m->setOptionalNoNamespaceMessage($sub);
$m->getRepeatedNoNamespaceMessage()[] = new NoNameSpaceMessage();
$n = new NoNamespaceMessage();
$n->setB(NoNamespaceMessage_NestedEnum::ZERO);
$m = new NoNameSpaceMessage();
}
public function testEnumWithoutNamespace()
{
$m = new TestMessage();
$m->setOptionalNoNamespaceEnum(NoNameSpaceEnum::VALUE_A);
$m->getRepeatedNoNamespaceEnum()[] = NoNameSpaceEnum::VALUE_A;
$m = new NoNameSpaceEnum();
}
#########################################################
@ -866,15 +852,4 @@ class GeneratedClassTest extends TestBase
$m->setPrefixMessage($n);
$this->assertSame(1, $m->getPrefixMessage()->getA());
}
#########################################################
# Test prefix for reserved words.
#########################################################
public function testPrefixForReservedWords()
{
$m = new \Foo\TestMessage_Empty();
$m = new \Foo\PBEmpty();
$m = new \PrefixEmpty();
}
}

View file

@ -616,7 +616,11 @@ class MapFieldTest extends PHPUnit_Framework_TestCase {
$arr[0] = $sub_m;
$this->assertSame(1, $arr[0]->getA());
$this->assertEquals(1, count($arr));
$null = NULL;
$arr[1] = $null;
$this->assertNull($arr[1]);
$this->assertEquals(2, count($arr));
}
/**
@ -649,17 +653,6 @@ class MapFieldTest extends PHPUnit_Framework_TestCase {
$arr[0] = new TestMessage_Sub();
}
/**
* @expectedException PHPUnit_Framework_Error
*/
public function testMessageSetNullFail()
{
$arr =
new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
$null = NULL;
$arr[0] = $null;
}
#########################################################
# Test memory leak
#########################################################

View file

@ -2,25 +2,17 @@
# phpunit has memory leak by itself. Thus, it cannot be used to test memory leak.
require_once('generated/NoNamespaceEnum.php');
require_once('generated/NoNamespaceMessage.php');
require_once('generated/NoNamespaceMessage_NestedEnum.php');
require_once('generated/PrefixEmpty.php');
require_once('generated/PrefixTestPrefix.php');
require_once('generated/Bar/TestInclude.php');
require_once('generated/Foo/PBEmpty.php');
require_once('generated/Foo/TestEnum.php');
require_once('generated/Foo/TestIncludePrefixMessage.php');
require_once('generated/Foo/TestMessage.php');
require_once('generated/Foo/TestMessage_Empty.php');
require_once('generated/Foo/TestMessage_NestedEnum.php');
require_once('generated/Foo/TestMessage_Sub.php');
require_once('generated/Foo/TestPackedMessage.php');
require_once('generated/Foo/TestPhpDoc.php');
require_once('generated/Foo/TestUnpackedMessage.php');
require_once('generated/GPBMetadata/Proto/Test.php');
require_once('generated/GPBMetadata/Proto/TestInclude.php');
require_once('generated/GPBMetadata/Proto/TestNoNamespace.php');
require_once('generated/GPBMetadata/Proto/TestPrefix.php');
require_once('test_util.php');
@ -91,8 +83,7 @@ $n = new TestMessage();
$n->mergeFromString($data);
assert(1 === $n->getOneofMessage()->getA());
# $from = new TestMessage();
# $to = new TestMessage();
# TestUtil::setTestMessage($from);
# $to->mergeFrom($from);
# TestUtil::assertTestMessage($to);
$from = new TestMessage();
$to = new TestMessage();
TestUtil::setTestMessage($from);
$to->mergeFrom($from);

View file

@ -1,7 +1,6 @@
syntax = "proto3";
import 'proto/test_include.proto';
import 'proto/test_no_namespace.proto';
import 'proto/test_prefix.proto';
package foo;
@ -97,34 +96,12 @@ message TestMessage {
// Reserved for non-existing field test.
// int32 non_exist = 89;
NoNamespaceMessage optional_no_namespace_message = 91;
NoNamespaceEnum optional_no_namespace_enum = 92;
repeated NoNamespaceMessage repeated_no_namespace_message = 93;
repeated NoNamespaceEnum repeated_no_namespace_enum = 94;
enum NestedEnum {
ZERO = 0;
}
NestedEnum optional_nested_enum = 101;
// Test prefix for reserved words.
message Empty {
int32 a = 1;
}
}
enum TestEnum {
ZERO = 0;
ONE = 1;
TWO = 2;
ECHO = 3; // Test reserved name.
}
// Test prefix for reserved words.
message Empty {
int32 a = 1;
}
message TestPackedMessage {

View file

@ -1,14 +0,0 @@
syntax = "proto3";
import "google/protobuf/descriptor.proto";
message TestImportDescriptorProto {
extend google.protobuf.MethodOptions {
int32 a = 72295727;
}
}
extend google.protobuf.MethodOptions {
int32 a = 72295728;
}

View file

@ -1,16 +1,10 @@
syntax = "proto3";
message NoNamespaceMessage {
message NoNameSpaceMessage {
int32 a = 1;
enum NestedEnum {
ZERO = 0;
}
NestedEnum b = 2;
repeated NestedEnum c = 3;
}
enum NoNamespaceEnum {
enum NoNameSpaceEnum {
VALUE_A = 0;
VALUE_B = 1;
}

View file

@ -5,8 +5,3 @@ option php_class_prefix = "Prefix";
message TestPrefix {
int32 a = 1;
}
// Test prefix for reserved words.
message Empty {
int32 a = 1;
}

View file

@ -51,6 +51,8 @@ class TestUtil
public static function setTestMessage(TestMessage $m)
{
$sub = new TestMessage_Sub();
$m->setOptionalInt32(-42);
$m->setOptionalInt64(-43);
$m->setOptionalUint32(42);
@ -67,7 +69,6 @@ class TestUtil
$m->setOptionalString('a');
$m->setOptionalBytes('b');
$m->setOptionalEnum(TestEnum::ONE);
$sub = new TestMessage_Sub();
$m->setOptionalMessage($sub);
$m->getOptionalMessage()->SetA(33);

View file

@ -4,14 +4,8 @@ use Google\Protobuf\GPBEmpty;
class WellKnownTest extends PHPUnit_Framework_TestCase {
public function testNone()
{
$msg = new GPBEmpty();
}
public function testImportDescriptorProto()
{
$msg = new TestImportDescriptorProto();
public function testNone() {
$msg = new GPBEmpty();
}
}

View file

@ -10,7 +10,7 @@
</parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protoc</artifactId>
<version>3.3.0</version>
<version>3.2.0</version>
<packaging>pom</packaging>
<name>Protobuf Compiler</name>
<description>

View file

@ -30,7 +30,7 @@
# Copyright 2007 Google Inc. All Rights Reserved.
__version__ = '3.3.0'
__version__ = '3.2.0'
if __name__ != '__main__':
try:

View file

@ -127,9 +127,6 @@ class DescriptorPool(object):
self._service_descriptors = {}
self._file_descriptors = {}
self._toplevel_extensions = {}
# TODO(jieluo): Remove _file_desc_by_toplevel_extension when
# FieldDescriptor.file is added in code gen.
self._file_desc_by_toplevel_extension = {}
# We store extensions in two two-level mappings: The first key is the
# descriptor of the message being extended, the second key is the extension
# full name or its tag number.
@ -173,7 +170,7 @@ class DescriptorPool(object):
raise TypeError('Expected instance of descriptor.Descriptor.')
self._descriptors[desc.full_name] = desc
self._AddFileDescriptor(desc.file)
self.AddFileDescriptor(desc.file)
def AddEnumDescriptor(self, enum_desc):
"""Adds an EnumDescriptor to the pool.
@ -188,7 +185,7 @@ class DescriptorPool(object):
raise TypeError('Expected instance of descriptor.EnumDescriptor.')
self._enum_descriptors[enum_desc.full_name] = enum_desc
self._AddFileDescriptor(enum_desc.file)
self.AddFileDescriptor(enum_desc.file)
def AddServiceDescriptor(self, service_desc):
"""Adds a ServiceDescriptor to the pool.
@ -254,23 +251,6 @@ class DescriptorPool(object):
file_desc: A FileDescriptor.
"""
self._AddFileDescriptor(file_desc)
# TODO(jieluo): This is a temporary solution for FieldDescriptor.file.
# Remove it when FieldDescriptor.file is added in code gen.
for extension in file_desc.extensions_by_name.values():
self._file_desc_by_toplevel_extension[
extension.full_name] = file_desc
def _AddFileDescriptor(self, file_desc):
"""Adds a FileDescriptor to the pool, non-recursively.
If the FileDescriptor contains messages or enums, the caller must explicitly
register them.
Args:
file_desc: A FileDescriptor.
"""
if not isinstance(file_desc, descriptor.FileDescriptor):
raise TypeError('Expected instance of descriptor.FileDescriptor.')
self._file_descriptors[file_desc.name] = file_desc
@ -333,18 +313,12 @@ class DescriptorPool(object):
except KeyError:
pass
try:
return self._file_desc_by_toplevel_extension[symbol]
except KeyError:
pass
# Try nested extensions inside a message.
message_name, _, extension_name = symbol.rpartition('.')
try:
message = self.FindMessageTypeByName(message_name)
assert message.extensions_by_name[extension_name]
return message.file
scope = self.FindMessageTypeByName(message_name)
assert scope.extensions_by_name[extension_name]
return scope.file
except KeyError:
raise KeyError('Cannot find a file containing %s' % symbol)

View file

@ -63,9 +63,6 @@ from google.protobuf import symbol_database
class DescriptorPoolTest(unittest.TestCase):
def setUp(self):
# TODO(jieluo): Should make the pool which is created by
# serialized_pb same with generated pool.
# TODO(jieluo): More test coverage for the generated pool.
self.pool = descriptor_pool.DescriptorPool()
self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString(
factory_test1_pb2.DESCRIPTOR.serialized_pb)
@ -131,12 +128,6 @@ class DescriptorPoolTest(unittest.TestCase):
self.assertEqual('google/protobuf/internal/factory_test2.proto',
file_desc4.name)
# Tests the generated pool.
assert descriptor_pool.Default().FindFileContainingSymbol(
'google.protobuf.python.internal.Factory2Message.one_more_field')
assert descriptor_pool.Default().FindFileContainingSymbol(
'google.protobuf.python.internal.another_field')
def testFindFileContainingSymbolFailure(self):
with self.assertRaises(KeyError):
self.pool.FindFileContainingSymbol('Does not exist')

View file

@ -779,7 +779,7 @@ PyObject* CheckString(PyObject* arg, const FieldDescriptor* descriptor) {
encoded_string = arg; // Already encoded.
Py_INCREF(encoded_string);
} else {
encoded_string = PyUnicode_AsEncodedString(arg, "utf-8", NULL);
encoded_string = PyUnicode_AsEncodedObject(arg, "utf-8", NULL);
}
} else {
// In this case field type is "bytes".

View file

@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = "google-protobuf"
s.version = "3.3.0"
s.version = "3.2.0.1"
s.licenses = ["BSD-3-Clause"]
s.summary = "Protocol Buffers"
s.description = "Protocol Buffers are Google's data interchange format."

View file

@ -116,7 +116,6 @@ nobase_include_HEADERS = \
google/protobuf/generated_enum_reflection.h \
google/protobuf/generated_enum_util.h \
google/protobuf/generated_message_reflection.h \
google/protobuf/generated_message_table_driven.h \
google/protobuf/generated_message_util.h \
google/protobuf/has_bits.h \
google/protobuf/map_entry.h \
@ -129,7 +128,6 @@ nobase_include_HEADERS = \
google/protobuf/message.h \
google/protobuf/message_lite.h \
google/protobuf/metadata.h \
google/protobuf/metadata_lite.h \
google/protobuf/reflection.h \
google/protobuf/reflection_ops.h \
google/protobuf/repeated_field.h \
@ -184,7 +182,7 @@ nobase_include_HEADERS = \
lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la
libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS)
libprotobuf_lite_la_LDFLAGS = -version-info 13:0:0 -export-dynamic -no-undefined
libprotobuf_lite_la_LDFLAGS = -version-info 12:0:0 -export-dynamic -no-undefined
if HAVE_LD_VERSION_SCRIPT
libprotobuf_lite_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libprotobuf-lite.map
EXTRA_libprotobuf_lite_la_DEPENDENCIES = libprotobuf-lite.map
@ -229,7 +227,7 @@ libprotobuf_lite_la_SOURCES = \
google/protobuf/io/zero_copy_stream_impl_lite.cc
libprotobuf_la_LIBADD = $(PTHREAD_LIBS)
libprotobuf_la_LDFLAGS = -version-info 13:0:0 -export-dynamic -no-undefined
libprotobuf_la_LDFLAGS = -version-info 12:0:0 -export-dynamic -no-undefined
if HAVE_LD_VERSION_SCRIPT
libprotobuf_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libprotobuf.map
EXTRA_libprotobuf_la_DEPENDENCIES = libprotobuf.map
@ -318,7 +316,7 @@ libprotobuf_la_SOURCES = \
nodist_libprotobuf_la_SOURCES = $(nodist_libprotobuf_lite_la_SOURCES)
libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la
libprotoc_la_LDFLAGS = -version-info 13:0:0 -export-dynamic -no-undefined
libprotoc_la_LDFLAGS = -version-info 12:0:0 -export-dynamic -no-undefined
if HAVE_LD_VERSION_SCRIPT
libprotoc_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libprotoc.map
EXTRA_libprotoc_la_DEPENDENCIES = libprotoc.map

View file

@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3003000
#if GOOGLE_PROTOBUF_VERSION < 3002000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#if 3002000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.

View file

@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3003000
#if GOOGLE_PROTOBUF_VERSION < 3002000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#if 3002000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.

View file

@ -751,15 +751,6 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
message_generators_[i]->GenerateShutdownCode(printer);
}
if (HasDescriptorMethods(file_, options_)) {
for (int i = 0; i < message_generators_.size(); i++) {
if (!IsMapEntryMessage(message_generators_[i]->descriptor_)) continue;
printer->Print(
"delete file_level_metadata[$index$].reflection;\n",
"index", SimpleItoa(i));
}
}
printer->Outdent();
printer->Print(
"}\n\n");

View file

@ -49,8 +49,6 @@ const std::string kDescriptorMetadataFile =
"GPBMetadata/Google/Protobuf/Internal/Descriptor.php";
const std::string kDescriptorDirName = "Google/Protobuf/Internal";
const std::string kDescriptorPackageName = "Google\\Protobuf\\Internal";
const char* const kReservedNames[] = {"Empty", "ECHO"};
const int kReservedNamesSize = 2;
namespace google {
namespace protobuf {
@ -86,6 +84,33 @@ std::string RenameEmpty(const std::string& name) {
}
}
std::string MessagePrefix(const Descriptor* message) {
// Empty cannot be php class name.
if (message->name() == "Empty" &&
message->file()->package() == "google.protobuf") {
return "GPB";
} else {
return (message->file()->options()).php_class_prefix();
}
}
std::string MessageName(const Descriptor* message, bool is_descriptor) {
string message_name = message->name();
const Descriptor* descriptor = message->containing_type();
while (descriptor != NULL) {
message_name = descriptor->name() + '_' + message_name;
descriptor = descriptor->containing_type();
}
message_name = MessagePrefix(message) + message_name;
if (message->file()->package() == "") {
return message_name;
} else {
return PhpName(message->file()->package(), is_descriptor) + '\\' +
message_name;
}
}
std::string MessageFullName(const Descriptor* message, bool is_descriptor) {
if (is_descriptor) {
return StringReplace(message->full_name(),
@ -106,51 +131,19 @@ std::string EnumFullName(const EnumDescriptor* envm, bool is_descriptor) {
}
}
template <typename DescriptorType>
std::string ClassNamePrefix(const string& classname,
const DescriptorType* desc) {
const string& prefix = (desc->file()->options()).php_class_prefix();
if (prefix != "") {
return prefix;
std::string EnumClassName(const EnumDescriptor* envm) {
string enum_class_name = envm->name();
const Descriptor* descriptor = envm->containing_type();
while (descriptor != NULL) {
enum_class_name = descriptor->name() + '_' + enum_class_name;
descriptor = descriptor->containing_type();
}
bool is_reserved = false;
for (int i = 0; i < kReservedNamesSize; i++) {
if (classname == kReservedNames[i]) {
is_reserved = true;
break;
}
}
if (is_reserved) {
if (desc->file()->package() == "google.protobuf") {
return "GPB";
} else {
return "PB";
}
}
return "";
return enum_class_name;
}
template <typename DescriptorType>
std::string FullClassName(const DescriptorType* desc, bool is_descriptor) {
string classname = desc->name();
const Descriptor* containing = desc->containing_type();
while (containing != NULL) {
classname = containing->name() + '_' + classname;
containing = containing->containing_type();
}
classname = ClassNamePrefix(classname, desc) + classname;
if (desc->file()->package() == "") {
return classname;
} else {
return PhpName(desc->file()->package(), is_descriptor) + '\\' +
classname;
}
std::string EnumName(const 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) {
@ -238,7 +231,7 @@ std::string GeneratedMetadataFileName(const std::string& proto_file,
std::string GeneratedMessageFileName(const Descriptor* message,
bool is_descriptor) {
std::string result = FullClassName(message, is_descriptor);
std::string result = MessageName(message, is_descriptor);
for (int i = 0; i < result.size(); i++) {
if (result[i] == '\\') {
result[i] = '/';
@ -249,7 +242,7 @@ std::string GeneratedMessageFileName(const Descriptor* message,
std::string GeneratedEnumFileName(const EnumDescriptor* en,
bool is_descriptor) {
std::string result = FullClassName(en, is_descriptor);
std::string result = EnumName(en, is_descriptor);
for (int i = 0; i < result.size(); i++) {
if (result[i] == '\\') {
result[i] = '/';
@ -463,12 +456,12 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
printer->Print(
", \\^class_name^);\n",
"class_name",
FullClassName(value->message_type(), is_descriptor) + "::class");
MessageName(value->message_type(), is_descriptor) + "::class");
} else if (value->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
printer->Print(
", \\^class_name^);\n",
", ^class_name^);\n",
"class_name",
FullClassName(value->enum_type(), is_descriptor) + "::class");
EnumName(value->enum_type(), is_descriptor) + "::class");
} else {
printer->Print(");\n");
}
@ -481,23 +474,23 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
printer->Print(
", \\^class_name^);\n",
"class_name",
FullClassName(field->message_type(), is_descriptor) + "::class");
MessageName(field->message_type(), is_descriptor) + "::class");
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
printer->Print(
", \\^class_name^);\n",
", ^class_name^);\n",
"class_name",
FullClassName(field->enum_type(), is_descriptor) + "::class");
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", FullClassName(field->message_type(), is_descriptor));
"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", FullClassName(field->enum_type(), is_descriptor));
"class_name", EnumName(field->enum_type(), is_descriptor));
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
printer->Print(
"GPBUtil::checkString($var, ^utf8^);\n",
@ -559,7 +552,7 @@ void GenerateEnumToPool(const EnumDescriptor* en, io::Printer* printer) {
const EnumValueDescriptor* value = en->value(i);
printer->Print(
"->value(\"^name^\", ^number^)\n",
"name", ClassNamePrefix(value->name(), en) + value->name(),
"name", value->name(),
"number", IntToString(value->number()));
}
printer->Print("->finalizeToPool();\n\n");
@ -674,12 +667,6 @@ void GenerateAddFileToPool(const FileDescriptor* file, bool is_descriptor,
} else {
for (int i = 0; i < file->dependency_count(); i++) {
const std::string& name = file->dependency(i)->name();
// Currently, descriptor.proto is not ready for external usage. Skip to
// import it for now, so that its dependencies can still work as long as
// they don't use protos defined in descriptor.proto.
if (name == kDescriptorFile) {
continue;
}
std::string dependency_filename =
GeneratedMetadataFileName(name, is_descriptor);
printer->Print(
@ -691,26 +678,6 @@ void GenerateAddFileToPool(const FileDescriptor* file, bool is_descriptor,
FileDescriptorSet files;
FileDescriptorProto* file_proto = files.add_file();
file->CopyTo(file_proto);
// Filter out descriptor.proto as it cannot be depended on for now.
RepeatedPtrField<string>* dependency = file_proto->mutable_dependency();
for (RepeatedPtrField<string>::iterator it = dependency->begin();
it != dependency->end(); ++it) {
if (*it != kDescriptorFile) {
dependency->erase(it);
break;
}
}
// Filter out all extensions, since we do not support extension yet.
file_proto->clear_extension();
RepeatedPtrField<DescriptorProto>* message_type =
file_proto->mutable_message_type();
for (RepeatedPtrField<DescriptorProto>::iterator it = message_type->begin();
it != message_type->end(); ++it) {
it->clear_extension();
}
string files_data;
files.SerializeToString(&files_data);
@ -845,7 +812,7 @@ void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
const EnumValueDescriptor* value = en->value(i);
GenerateEnumValueDocComment(&printer, value);
printer.Print("const ^name^ = ^number^;\n",
"name", ClassNamePrefix(value->name(), en) + value->name(),
"name", value->name(),
"number", IntToString(value->number()));
}

View file

@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3003000
#if GOOGLE_PROTOBUF_VERSION < 3002000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#if 3002000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.

View file

@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3003000
#if GOOGLE_PROTOBUF_VERSION < 3002000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#if 3002000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.

View file

@ -445,6 +445,8 @@ void Generator::PrintFileDescriptor() const {
printer_->Outdent();
printer_->Print(")\n");
printer_->Print("_sym_db.RegisterFileDescriptor($name$)\n", "name",
kDescriptorKey);
printer_->Print("\n");
}
@ -997,10 +999,6 @@ void Generator::FixForeignFieldsInDescriptors() const {
for (int i = 0; i < file_->extension_count(); ++i) {
AddExtensionToFileDescriptor(*file_->extension(i));
}
// TODO(jieluo): Move this register to PrintFileDescriptor() when
// FieldDescriptor.file is added in generated file.
printer_->Print("_sym_db.RegisterFileDescriptor($name$)\n", "name",
kDescriptorKey);
printer_->Print("\n");
}

View file

@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3003000
#if GOOGLE_PROTOBUF_VERSION < 3002000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#if 3002000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.

View file

@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3003000
#if GOOGLE_PROTOBUF_VERSION < 3002000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#if 3002000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.

View file

@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3003000
#if GOOGLE_PROTOBUF_VERSION < 3002000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#if 3002000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.

View file

@ -438,7 +438,9 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// SpaceUsed()).
size_t SpaceUsedExcludingSelfLong() const;
int SpaceUsedExcludingSelf() const;
int SpaceUsedExcludingSelf() const {
return internal::FromIntSize(SpaceUsedExcludingSelfLong());
}
private:

View file

@ -340,10 +340,6 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
}
}
int ExtensionSet::SpaceUsedExcludingSelf() const {
return internal::FromIntSize(SpaceUsedExcludingSelfLong());
}
size_t ExtensionSet::SpaceUsedExcludingSelfLong() const {
size_t total_size =
extensions_.size() * sizeof(ExtensionMap::value_type);

View file

@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3003000
#if GOOGLE_PROTOBUF_VERSION < 3002000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#if 3002000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.

View file

@ -255,7 +255,7 @@ struct MigrationSchema {
// of whatever type the individual field would be. Strings and
// Messages use RepeatedPtrFields while everything else uses
// RepeatedFields.
class LIBPROTOBUF_EXPORT GeneratedMessageReflection PROTOBUF_FINAL : public Reflection {
class GeneratedMessageReflection PROTOBUF_FINAL : public Reflection {
public:
// Constructs a GeneratedMessageReflection.
// Parameters:

View file

@ -39,7 +39,6 @@
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
#include <assert.h>
#include <climits>
#include <string>
#include <google/protobuf/stubs/logging.h>
@ -178,7 +177,7 @@ LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyString() {
return GetEmptyStringAlreadyInited();
}
LIBPROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const string& str);
size_t StringSpaceUsedExcludingSelfLong(const string& str);
// True if IsInitialized() is true for all elements of t. Type is expected

View file

@ -83,7 +83,7 @@ namespace internal {
template <typename Derived, typename Key, typename Value,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
class MapEntry
class LIBPROTOBUF_EXPORT MapEntry
: public MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
kValueFieldType, default_enum_value> {
public:

View file

@ -92,7 +92,7 @@ struct MoveHelper<false, false, true, T> { // strings and similar
template <typename Derived, typename Base, typename Key, typename Value,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
class MapEntryImpl : public Base {
class LIBPROTOBUF_EXPORT MapEntryImpl : public Base {
protected:
// Provide utilities to parse/serialize key/value. Provide utilities to
// manipulate internal stored type.
@ -537,7 +537,7 @@ class MapEntryImpl : public Base {
template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
class MapEntryLite
class LIBPROTOBUF_EXPORT MapEntryLite
: public MapEntryImpl<MapEntryLite<Key, Value, kKeyFieldType,
kValueFieldType, default_enum_value>,
MessageLite, Key, Value, kKeyFieldType,

View file

@ -67,13 +67,6 @@ size_t MapFieldBase::SpaceUsedExcludingSelfNoLock() const {
}
}
bool MapFieldBase::IsMapValid() const {
// "Acquire" insures the operation after SyncRepeatedFieldWithMap won't get
// executed before state_ is checked.
Atomic32 state = google::protobuf::internal::Acquire_Load(&state_);
return state != STATE_MODIFIED_REPEATED;
}
void MapFieldBase::SetMapDirty() { state_ = STATE_MODIFIED_MAP; }
void MapFieldBase::SetRepeatedDirty() { state_ = STATE_MODIFIED_REPEATED; }
@ -366,13 +359,6 @@ void DynamicMapField::SyncMapWithRepeatedFieldNoLock() const {
GOOGLE_LOG(FATAL) << "Can't get here.";
break;
}
// Remove existing map value with same key.
Map<MapKey, MapValueRef>::iterator iter = map->find(map_key);
if (iter != map->end()) {
iter->second.DeleteData();
}
MapValueRef& map_val = (*map)[map_key];
map_val.SetType(val_des->cpp_type());
switch (val_des->cpp_type()) {

View file

@ -86,8 +86,6 @@ class LIBPROTOBUF_EXPORT MapFieldBase {
virtual bool ContainsMapKey(const MapKey& map_key) const = 0;
virtual bool InsertOrLookupMapValue(
const MapKey& map_key, MapValueRef* val) = 0;
// Insures operations after won't get executed before calling this.
bool IsMapValid() const;
virtual bool DeleteMapValue(const MapKey& map_key) = 0;
virtual bool EqualIterator(const MapIterator& a,
const MapIterator& b) const = 0;

View file

@ -975,11 +975,6 @@ static int Int(const string& value) {
class MapFieldReflectionTest : public testing::Test {
protected:
typedef FieldDescriptor FD;
int MapSize(const Reflection* reflection, const FieldDescriptor* field,
const Message& message) {
return reflection->MapSize(message, field);
}
};
TEST_F(MapFieldReflectionTest, RegularFields) {
@ -1787,50 +1782,6 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefMergeFromAndSwap) {
// TODO(teboring): add test for duplicated key
}
TEST_F(MapFieldReflectionTest, MapSizeWithDuplicatedKey) {
// Dynamic Message
{
DynamicMessageFactory factory;
google::protobuf::scoped_ptr<Message> message(
factory.GetPrototype(unittest::TestMap::descriptor())->New());
const Reflection* reflection = message->GetReflection();
const FieldDescriptor* field =
unittest::TestMap::descriptor()->FindFieldByName("map_int32_int32");
Message* entry1 = reflection->AddMessage(message.get(), field);
Message* entry2 = reflection->AddMessage(message.get(), field);
const Reflection* entry_reflection = entry1->GetReflection();
const FieldDescriptor* key_field =
entry1->GetDescriptor()->FindFieldByName("key");
entry_reflection->SetInt32(entry1, key_field, 1);
entry_reflection->SetInt32(entry2, key_field, 1);
EXPECT_EQ(2, reflection->FieldSize(*message, field));
EXPECT_EQ(1, MapSize(reflection, field, *message));
}
// Generated Message
{
unittest::TestMap message;
const Reflection* reflection = message.GetReflection();
const FieldDescriptor* field =
message.GetDescriptor()->FindFieldByName("map_int32_int32");
Message* entry1 = reflection->AddMessage(&message, field);
Message* entry2 = reflection->AddMessage(&message, field);
const Reflection* entry_reflection = entry1->GetReflection();
const FieldDescriptor* key_field =
entry1->GetDescriptor()->FindFieldByName("key");
entry_reflection->SetInt32(entry1, key_field, 1);
entry_reflection->SetInt32(entry2, key_field, 1);
EXPECT_EQ(2, reflection->FieldSize(message, field));
EXPECT_EQ(1, MapSize(reflection, field, message));
}
}
// Generated Message Test ===========================================
TEST(GeneratedMapFieldTest, Accessors) {
@ -2738,69 +2689,6 @@ TEST_F(MapFieldInDynamicMessageTest, RecursiveMap) {
ASSERT_TRUE(to->ParseFromString(data));
}
TEST_F(MapFieldInDynamicMessageTest, MapValueReferernceValidAfterSerialize) {
google::protobuf::scoped_ptr<Message> message(map_prototype_->New());
MapReflectionTester reflection_tester(map_descriptor_);
reflection_tester.SetMapFieldsViaMapReflection(message.get());
// Get value reference before serialization, so that we know the value is from
// map.
MapKey map_key;
MapValueRef map_val;
map_key.SetInt32Value(0);
reflection_tester.GetMapValueViaMapReflection(
message.get(), "map_int32_foreign_message", map_key, &map_val);
Message* submsg = map_val.MutableMessageValue();
// In previous implementation, calling SerializeToString will cause syncing
// from map to repeated field, which will invalidate the submsg we previously
// got.
string data;
message->SerializeToString(&data);
const Reflection* submsg_reflection = submsg->GetReflection();
const Descriptor* submsg_desc = submsg->GetDescriptor();
const FieldDescriptor* submsg_field = submsg_desc->FindFieldByName("c");
submsg_reflection->SetInt32(submsg, submsg_field, 128);
message->SerializeToString(&data);
TestMap to;
to.ParseFromString(data);
EXPECT_EQ(128, to.map_int32_foreign_message().at(0).c());
}
TEST_F(MapFieldInDynamicMessageTest, MapEntryReferernceValidAfterSerialize) {
google::protobuf::scoped_ptr<Message> message(map_prototype_->New());
MapReflectionTester reflection_tester(map_descriptor_);
reflection_tester.SetMapFieldsViaReflection(message.get());
// Get map entry before serialization, so that we know the it is from
// repeated field.
Message* map_entry = reflection_tester.GetMapEntryViaReflection(
message.get(), "map_int32_foreign_message", 0);
const Reflection* map_entry_reflection = map_entry->GetReflection();
const Descriptor* map_entry_desc = map_entry->GetDescriptor();
const FieldDescriptor* value_field = map_entry_desc->FindFieldByName("value");
Message* submsg =
map_entry_reflection->MutableMessage(map_entry, value_field);
// In previous implementation, calling SerializeToString will cause syncing
// from repeated field to map, which will invalidate the map_entry we
// previously got.
string data;
message->SerializeToString(&data);
const Reflection* submsg_reflection = submsg->GetReflection();
const Descriptor* submsg_desc = submsg->GetDescriptor();
const FieldDescriptor* submsg_field = submsg_desc->FindFieldByName("c");
submsg_reflection->SetInt32(submsg, submsg_field, 128);
message->SerializeToString(&data);
TestMap to;
to.ParseFromString(data);
EXPECT_EQ(128, to.map_int32_foreign_message().at(0).c());
}
// ReflectionOps Test ===============================================
TEST(ReflectionOpsForMapFieldTest, MapSanityCheck) {
@ -2863,20 +2751,6 @@ TEST(ReflectionOpsForMapFieldTest, MapDiscardUnknownFields) {
GetUnknownFields(message).field_count());
}
TEST(ReflectionOpsForMapFieldTest, IsInitialized) {
unittest::TestRequiredMessageMap map_message;
// Add an uninitialized message.
(*map_message.mutable_map_field())[0];
EXPECT_FALSE(ReflectionOps::IsInitialized(map_message));
// Initialize uninitialized message
(*map_message.mutable_map_field())[0].set_a(0);
(*map_message.mutable_map_field())[0].set_b(0);
(*map_message.mutable_map_field())[0].set_c(0);
EXPECT_TRUE(ReflectionOps::IsInitialized(map_message));
}
// Wire Format Test =================================================
TEST(WireFormatForMapFieldTest, ParseMap) {
@ -2937,33 +2811,6 @@ TEST(WireFormatForMapFieldTest, SerializeMap) {
EXPECT_TRUE(dynamic_data == generated_data);
}
TEST(WireFormatForMapFieldTest, SerializeMapDynamicMessage) {
DynamicMessageFactory factory;
google::protobuf::scoped_ptr<Message> dynamic_message;
dynamic_message.reset(
factory.GetPrototype(unittest::TestMap::descriptor())->New());
MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
reflection_tester.SetMapFieldsViaReflection(dynamic_message.get());
reflection_tester.ExpectMapFieldsSetViaReflection(*dynamic_message);
unittest::TestMap generated_message;
MapTestUtil::SetMapFields(&generated_message);
MapTestUtil::ExpectMapFieldsSet(generated_message);
string generated_data;
string dynamic_data;
// Serialize.
generated_message.SerializeToString(&generated_data);
dynamic_message->SerializeToString(&dynamic_data);
// Because map serialization doesn't guarantee order, we just compare
// serialized size here. This is enough to tell dynamic message doesn't miss
// anything in serialization.
EXPECT_TRUE(dynamic_data.size() == generated_data.size());
}
TEST(WireFormatForMapFieldTest, MapParseHelpers) {
string data;
@ -3215,7 +3062,7 @@ TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) {
}
// Use text format parsing and serializing to test reflection api.
TEST(ArenaTest, ReflectionInTextFormat) {
TEST(ArenaTest, RelfectionInTextFormat) {
Arena arena;
string data;

View file

@ -744,22 +744,6 @@ void MapReflectionTester::SetMapFieldsViaMapReflection(
sub_foreign_message, foreign_c_, 1);
}
void MapReflectionTester::GetMapValueViaMapReflection(Message* message,
const string& field_name,
const MapKey& map_key,
MapValueRef* map_val) {
const Reflection* reflection = message->GetReflection();
EXPECT_FALSE(reflection->InsertOrLookupMapValue(message, F(field_name),
map_key, map_val));
}
Message* MapReflectionTester::GetMapEntryViaReflection(Message* message,
const string& field_name,
int index) {
const Reflection* reflection = message->GetReflection();
return reflection->MutableRepeatedMessage(message, F(field_name), index);
}
void MapReflectionTester::ClearMapFieldsViaReflection(
Message* message) {
const Reflection* reflection = message->GetReflection();

View file

@ -106,11 +106,6 @@ class MapReflectionTester {
void ExpectClearViaReflection(const Message& message);
void ExpectClearViaReflectionIterator(Message* message);
void ExpectMapEntryClearViaReflection(Message* message);
void GetMapValueViaMapReflection(Message* message,
const string& field_name,
const MapKey& map_key, MapValueRef* map_val);
Message* GetMapEntryViaReflection(Message* message, const string& field_name,
int index);
private:
const FieldDescriptor* F(const string& name);

View file

@ -154,13 +154,6 @@ class MapReflectionFriend; // scalar_map_container.h
}
namespace internal {
class ReflectionOps; // reflection_ops.h
class MapKeySorter; // wire_format.cc
class WireFormat; // wire_format.h
class MapFieldReflectionTest; // map_test.cc
}
template<typename T>
class RepeatedField; // repeated_field.h
@ -943,10 +936,6 @@ class LIBPROTOBUF_EXPORT Reflection {
template<typename T, typename Enable>
friend class MutableRepeatedFieldRef;
friend class ::google::protobuf::python::MapReflectionFriend;
friend class internal::MapFieldReflectionTest;
friend class internal::MapKeySorter;
friend class internal::WireFormat;
friend class internal::ReflectionOps;
// Special version for specialized implementations of string. We can't call
// MutableRawRepeatedField directly here because we don't have access to

View file

@ -38,7 +38,6 @@
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/map_field.h>
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/stubs/strutil.h>
@ -159,27 +158,6 @@ bool ReflectionOps::IsInitialized(const Message& message) {
const FieldDescriptor* field = fields[i];
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (field->is_map()) {
const FieldDescriptor* value_field = field->message_type()->field(1);
if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
MapFieldBase* map_field =
reflection->MapData(const_cast<Message*>(&message), field);
if (map_field->IsMapValid()) {
MapIterator iter(const_cast<Message*>(&message), field);
MapIterator end(const_cast<Message*>(&message), field);
for (map_field->MapBegin(&iter), map_field->MapEnd(&end);
iter != end; ++iter) {
if (!iter.GetValueRef().GetMessageValue().IsInitialized()) {
return false;
}
}
continue;
}
} else {
continue;
}
}
if (field->is_repeated()) {
int size = reflection->FieldSize(message, field);

View file

@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3003000
#if GOOGLE_PROTOBUF_VERSION < 3002000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#if 3002000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.

View file

@ -133,7 +133,6 @@ void TableStruct::Shutdown() {
delete file_level_metadata[2].reflection;
_ListValue_default_instance_.Shutdown();
delete file_level_metadata[3].reflection;
delete file_level_metadata[0].reflection;
}
void TableStruct::InitDefaultsImpl() {

View file

@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3003000
#if GOOGLE_PROTOBUF_VERSION < 3002000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#if 3002000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.

View file

@ -96,27 +96,27 @@ namespace internal {
// The current version, represented as a single integer to make comparison
// easier: major * 10^6 + minor * 10^3 + micro
#define GOOGLE_PROTOBUF_VERSION 3003000
#define GOOGLE_PROTOBUF_VERSION 3002000
// A suffix string for alpha, beta or rc releases. Empty for stable releases.
#define GOOGLE_PROTOBUF_VERSION_SUFFIX ""
// The minimum library version which works with the current version of the
// headers.
#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3003000
#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3002000
// The minimum header version which works with the current version of
// the library. This constant should only be used by protoc's C++ code
// generator.
static const int kMinHeaderVersionForLibrary = 3003000;
static const int kMinHeaderVersionForLibrary = 3002000;
// The minimum protoc version which works with the current version of the
// headers.
#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3003000
#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3002000
// The minimum header version which works with the current version of
// protoc. This constant should only be used in VerifyVersion().
static const int kMinHeaderVersionForProtoc = 3003000;
static const int kMinHeaderVersionForProtoc = 3002000;
// Verifies that the headers and libraries are compatible. Use the macro
// below to call this.

View file

@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3003000
#if GOOGLE_PROTOBUF_VERSION < 3002000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#if 3002000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.

View file

@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3003000
#if GOOGLE_PROTOBUF_VERSION < 3002000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#if 3002000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.

View file

@ -54,17 +54,9 @@
namespace google {
const size_t kMapEntryTagByteSize = 2;
namespace protobuf {
namespace internal {
// Forward declare static functions
static size_t MapKeyDataOnlyByteSize(const FieldDescriptor* field,
const MapKey& value);
static size_t MapValueRefDataOnlyByteSize(const FieldDescriptor* field,
const MapValueRef& value);
// ===================================================================
bool UnknownFieldSetFieldSkipper::SkipField(
@ -805,16 +797,7 @@ void WireFormat::SerializeWithCachedSizes(
int expected_endpoint = output->ByteCount() + size;
std::vector<const FieldDescriptor*> fields;
// Fields of map entry should always be serialized.
if (descriptor->options().map_entry()) {
for (int i = 0; i < descriptor->field_count(); i++) {
fields.push_back(descriptor->field(i));
}
} else {
message_reflection->ListFields(message, &fields);
}
message_reflection->ListFields(message, &fields);
for (int i = 0; i < fields.size(); i++) {
SerializeFieldWithCachedSizes(fields[i], message, output);
}
@ -833,129 +816,6 @@ void WireFormat::SerializeWithCachedSizes(
"during serialization?";
}
static void SerializeMapKeyWithCachedSizes(const FieldDescriptor* field,
const MapKey& value,
io::CodedOutputStream* output) {
switch (field->type()) {
case FieldDescriptor::TYPE_DOUBLE:
case FieldDescriptor::TYPE_FLOAT:
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_BYTES:
case FieldDescriptor::TYPE_ENUM:
GOOGLE_LOG(FATAL) << "Unsupported";
break;
#define CASE_TYPE(FieldType, CamelFieldType, CamelCppType) \
case FieldDescriptor::TYPE_##FieldType: \
WireFormatLite::Write##CamelFieldType(1, value.Get##CamelCppType##Value(), \
output); \
break;
CASE_TYPE(INT64, Int64, Int64)
CASE_TYPE(UINT64, UInt64, UInt64)
CASE_TYPE(INT32, Int32, Int32)
CASE_TYPE(FIXED64, Fixed64, UInt64)
CASE_TYPE(FIXED32, Fixed32, UInt32)
CASE_TYPE(BOOL, Bool, Bool)
CASE_TYPE(UINT32, UInt32, UInt32)
CASE_TYPE(SFIXED32, SFixed32, Int32)
CASE_TYPE(SFIXED64, SFixed64, Int64)
CASE_TYPE(SINT32, SInt32, Int32)
CASE_TYPE(SINT64, SInt64, Int64)
CASE_TYPE(STRING, String, String)
#undef CASE_TYPE
}
}
static void SerializeMapValueRefWithCachedSizes(const FieldDescriptor* field,
const MapValueRef& value,
io::CodedOutputStream* output) {
switch (field->type()) {
#define CASE_TYPE(FieldType, CamelFieldType, CamelCppType) \
case FieldDescriptor::TYPE_##FieldType: \
WireFormatLite::Write##CamelFieldType(2, value.Get##CamelCppType##Value(), \
output); \
break;
CASE_TYPE(INT64, Int64, Int64)
CASE_TYPE(UINT64, UInt64, UInt64)
CASE_TYPE(INT32, Int32, Int32)
CASE_TYPE(FIXED64, Fixed64, UInt64)
CASE_TYPE(FIXED32, Fixed32, UInt32)
CASE_TYPE(BOOL, Bool, Bool)
CASE_TYPE(UINT32, UInt32, UInt32)
CASE_TYPE(SFIXED32, SFixed32, Int32)
CASE_TYPE(SFIXED64, SFixed64, Int64)
CASE_TYPE(SINT32, SInt32, Int32)
CASE_TYPE(SINT64, SInt64, Int64)
CASE_TYPE(ENUM, Enum, Enum)
CASE_TYPE(DOUBLE, Double, Double)
CASE_TYPE(FLOAT, Float, Float)
CASE_TYPE(STRING, String, String)
CASE_TYPE(BYTES, Bytes, String)
CASE_TYPE(MESSAGE, Message, Message)
CASE_TYPE(GROUP, Group, Message)
#undef CASE_TYPE
}
}
class MapKeySorter {
public:
static std::vector<MapKey> SortKey(const Message& message,
const Reflection* reflection,
const FieldDescriptor* field) {
std::vector<MapKey> sorted_key_list;
for (MapIterator it =
reflection->MapBegin(const_cast<Message*>(&message), field);
it != reflection->MapEnd(const_cast<Message*>(&message), field);
++it) {
sorted_key_list.push_back(it.GetKey());
}
MapKeyComparator comparator;
std::sort(sorted_key_list.begin(), sorted_key_list.end(), comparator);
return sorted_key_list;
}
private:
class MapKeyComparator {
public:
bool operator()(const MapKey& a, const MapKey& b) const {
GOOGLE_DCHECK(a.type() == b.type());
switch (a.type()) {
#define CASE_TYPE(CppType, CamelCppType) \
case FieldDescriptor::CPPTYPE_##CppType: { \
return a.Get##CamelCppType##Value() < b.Get##CamelCppType##Value(); \
}
CASE_TYPE(STRING, String)
CASE_TYPE(INT64, Int64)
CASE_TYPE(INT32, Int32)
CASE_TYPE(UINT64, UInt64)
CASE_TYPE(UINT32, UInt32)
CASE_TYPE(BOOL, Bool)
#undef CASE_TYPE
default:
GOOGLE_LOG(DFATAL) << "Invalid key for map field.";
return true;
}
}
};
};
static void SerializeMapEntry(const FieldDescriptor* field, const MapKey& key,
const MapValueRef& value,
io::CodedOutputStream* output) {
const FieldDescriptor* key_field = field->message_type()->field(0);
const FieldDescriptor* value_field = field->message_type()->field(1);
WireFormatLite::WriteTag(field->number(),
WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
size_t size = kMapEntryTagByteSize;
size += MapKeyDataOnlyByteSize(key_field, key);
size += MapValueRefDataOnlyByteSize(value_field, value);
output->WriteVarint32(size);
SerializeMapKeyWithCachedSizes(key_field, key, output);
SerializeMapValueRefWithCachedSizes(value_field, value, output);
}
void WireFormat::SerializeFieldWithCachedSizes(
const FieldDescriptor* field,
const Message& message,
@ -970,55 +830,10 @@ void WireFormat::SerializeFieldWithCachedSizes(
return;
}
// For map fields, we can use either repeated field reflection or map
// reflection. Our choice has some subtle effects. If we use repeated field
// reflection here, then the repeated field representation becomes
// authoritative for this field: any existing references that came from map
// reflection remain valid for reading, but mutations to them are lost and
// will be overwritten next time we call map reflection!
//
// So far this mainly affects Python, which keeps long-term references to map
// values around, and always uses map reflection. See: b/35918691
//
// Here we choose to use map reflection API as long as the internal
// map is valid. In this way, the serialization doesn't change map field's
// internal state and existing references that came from map reflection remain
// valid for both reading and writing.
if (field->is_map()) {
MapFieldBase* map_field =
message_reflection->MapData(const_cast<Message*>(&message), field);
if (map_field->IsMapValid()) {
if (output->IsSerializationDeterministic()) {
std::vector<MapKey> sorted_key_list =
MapKeySorter::SortKey(message, message_reflection, field);
for (std::vector<MapKey>::iterator it = sorted_key_list.begin();
it != sorted_key_list.end(); ++it) {
MapValueRef map_value;
message_reflection->InsertOrLookupMapValue(
const_cast<Message*>(&message), field, *it, &map_value);
SerializeMapEntry(field, *it, map_value, output);
}
} else {
for (MapIterator it = message_reflection->MapBegin(
const_cast<Message*>(&message), field);
it !=
message_reflection->MapEnd(const_cast<Message*>(&message), field);
++it) {
SerializeMapEntry(field, it.GetKey(), it.GetValueRef(), output);
}
}
return;
}
}
int count = 0;
if (field->is_repeated()) {
count = message_reflection->FieldSize(message, field);
} else if (field->containing_type()->options().map_entry()) {
// Map entry fields always need to be serialized.
count = 1;
} else if (message_reflection->HasField(message, field)) {
count = 1;
}
@ -1169,16 +984,7 @@ size_t WireFormat::ByteSize(const Message& message) {
size_t our_size = 0;
std::vector<const FieldDescriptor*> fields;
// Fields of map entry should always be serialized.
if (descriptor->options().map_entry()) {
for (int i = 0; i < descriptor->field_count(); i++) {
fields.push_back(descriptor->field(i));
}
} else {
message_reflection->ListFields(message, &fields);
}
message_reflection->ListFields(message, &fields);
for (int i = 0; i < fields.size(); i++) {
our_size += FieldByteSize(fields[i], message);
}
@ -1209,9 +1015,6 @@ size_t WireFormat::FieldByteSize(
size_t count = 0;
if (field->is_repeated()) {
count = FromIntSize(message_reflection->FieldSize(message, field));
} else if (field->containing_type()->options().map_entry()) {
// Map entry fields always need to be serialized.
count = 1;
} else if (message_reflection->HasField(message, field)) {
count = 1;
}
@ -1232,124 +1035,20 @@ size_t WireFormat::FieldByteSize(
return our_size;
}
static size_t MapKeyDataOnlyByteSize(const FieldDescriptor* field,
const MapKey& value) {
GOOGLE_DCHECK_EQ(FieldDescriptor::TypeToCppType(field->type()), value.type());
switch (field->type()) {
case FieldDescriptor::TYPE_DOUBLE:
case FieldDescriptor::TYPE_FLOAT:
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_BYTES:
case FieldDescriptor::TYPE_ENUM:
GOOGLE_LOG(FATAL) << "Unsupported";
return 0;
#define CASE_TYPE(FieldType, CamelFieldType, CamelCppType) \
case FieldDescriptor::TYPE_##FieldType: \
return WireFormatLite::CamelFieldType##Size( \
value.Get##CamelCppType##Value());
#define FIXED_CASE_TYPE(FieldType, CamelFieldType) \
case FieldDescriptor::TYPE_##FieldType: \
return WireFormatLite::k##CamelFieldType##Size;
CASE_TYPE(INT32, Int32, Int32);
CASE_TYPE(INT64, Int64, Int64);
CASE_TYPE(UINT32, UInt32, UInt32);
CASE_TYPE(UINT64, UInt64, UInt64);
CASE_TYPE(SINT32, SInt32, Int32);
CASE_TYPE(SINT64, SInt64, Int64);
CASE_TYPE(STRING, String, String);
FIXED_CASE_TYPE(FIXED32, Fixed32);
FIXED_CASE_TYPE(FIXED64, Fixed64);
FIXED_CASE_TYPE(SFIXED32, SFixed32);
FIXED_CASE_TYPE(SFIXED64, SFixed64);
FIXED_CASE_TYPE(BOOL, Bool);
#undef CASE_TYPE
#undef FIXED_CASE_TYPE
}
GOOGLE_LOG(FATAL) << "Cannot get here";
return 0;
}
static size_t MapValueRefDataOnlyByteSize(const FieldDescriptor* field,
const MapValueRef& value) {
switch (field->type()) {
case FieldDescriptor::TYPE_GROUP:
GOOGLE_LOG(FATAL) << "Unsupported";
return 0;
#define CASE_TYPE(FieldType, CamelFieldType, CamelCppType) \
case FieldDescriptor::TYPE_##FieldType: \
return WireFormatLite::CamelFieldType##Size( \
value.Get##CamelCppType##Value());
#define FIXED_CASE_TYPE(FieldType, CamelFieldType) \
case FieldDescriptor::TYPE_##FieldType: \
return WireFormatLite::k##CamelFieldType##Size;
CASE_TYPE(INT32, Int32, Int32);
CASE_TYPE(INT64, Int64, Int64);
CASE_TYPE(UINT32, UInt32, UInt32);
CASE_TYPE(UINT64, UInt64, UInt64);
CASE_TYPE(SINT32, SInt32, Int32);
CASE_TYPE(SINT64, SInt64, Int64);
CASE_TYPE(STRING, String, String);
CASE_TYPE(BYTES, Bytes, String);
CASE_TYPE(ENUM, Enum, Enum);
CASE_TYPE(MESSAGE, Message, Message);
FIXED_CASE_TYPE(FIXED32, Fixed32);
FIXED_CASE_TYPE(FIXED64, Fixed64);
FIXED_CASE_TYPE(SFIXED32, SFixed32);
FIXED_CASE_TYPE(SFIXED64, SFixed64);
FIXED_CASE_TYPE(DOUBLE, Double);
FIXED_CASE_TYPE(FLOAT, Float);
FIXED_CASE_TYPE(BOOL, Bool);
#undef CASE_TYPE
#undef FIXED_CASE_TYPE
}
GOOGLE_LOG(FATAL) << "Cannot get here";
return 0;
}
size_t WireFormat::FieldDataOnlyByteSize(
const FieldDescriptor* field,
const Message& message) {
const Reflection* message_reflection = message.GetReflection();
size_t data_size = 0;
if (field->is_map()) {
MapFieldBase* map_field =
message_reflection->MapData(const_cast<Message*>(&message), field);
if (map_field->IsMapValid()) {
MapIterator iter(const_cast<Message*>(&message), field);
MapIterator end(const_cast<Message*>(&message), field);
const FieldDescriptor* key_field = field->message_type()->field(0);
const FieldDescriptor* value_field = field->message_type()->field(1);
for (map_field->MapBegin(&iter), map_field->MapEnd(&end); iter != end;
++iter) {
size_t size = kMapEntryTagByteSize;
size += MapKeyDataOnlyByteSize(key_field, iter.GetKey());
size += MapValueRefDataOnlyByteSize(value_field, iter.GetValueRef());
data_size += WireFormatLite::LengthDelimitedSize(size);
}
return data_size;
}
}
size_t count = 0;
if (field->is_repeated()) {
count =
internal::FromIntSize(message_reflection->FieldSize(message, field));
} else if (field->containing_type()->options().map_entry()) {
// Map entry fields always need to be serialized.
count = 1;
} else if (message_reflection->HasField(message, field)) {
count = 1;
}
size_t data_size = 0;
switch (field->type()) {
#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: \

View file

@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3003000
#if GOOGLE_PROTOBUF_VERSION < 3002000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#if 3002000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.

126
tests.sh
View file

@ -362,7 +362,6 @@ generate_php_test_proto() {
../../src/protoc --php_out=generated proto/test.proto proto/test_include.proto proto/test_no_namespace.proto proto/test_prefix.proto
pushd ../../src
./protoc --php_out=../php/tests/generated google/protobuf/empty.proto
./protoc --php_out=../php/tests/generated -I../php/tests -I. ../php/tests/proto/test_import_descriptor_proto.proto
popd
popd
}
@ -372,9 +371,12 @@ use_php() {
PHP=`which php`
PHP_CONFIG=`which php-config`
PHPIZE=`which phpize`
ln -sfn "/usr/local/php-${VERSION}/bin/php" $PHP
ln -sfn "/usr/local/php-${VERSION}/bin/php-config" $PHP_CONFIG
ln -sfn "/usr/local/php-${VERSION}/bin/phpize" $PHPIZE
rm $PHP
rm $PHP_CONFIG
rm $PHPIZE
cp "/usr/bin/php$VERSION" $PHP
cp "/usr/bin/php-config$VERSION" $PHP_CONFIG
cp "/usr/bin/phpize$VERSION" $PHPIZE
generate_php_test_proto
}
@ -401,13 +403,18 @@ use_php_bc() {
}
build_php5.5() {
use_php 5.5
PHP=`which php`
PHP_CONFIG=`which php-config`
PHPIZE=`which phpize`
ln -sfn "/usr/local/php-5.5/bin/php" $PHP
ln -sfn "/usr/local/php-5.5/bin/php-config" $PHP_CONFIG
ln -sfn "/usr/local/php-5.5/bin/phpize" $PHPIZE
generate_php_test_proto
pushd php
rm -rf vendor
cp -r /usr/local/vendor-5.5 vendor
wget https://phar.phpunit.de/phpunit-4.8.0.phar -O /usr/bin/phpunit
phpunit
./vendor/bin/phpunit
popd
pushd conformance
# TODO(teboring): Add it back
@ -416,30 +423,59 @@ build_php5.5() {
}
build_php5.5_c() {
use_php 5.5
wget https://phar.phpunit.de/phpunit-4.8.0.phar -O /usr/bin/phpunit
PHP=`which php`
PHP_CONFIG=`which php-config`
PHPIZE=`which phpize`
ln -sfn "/usr/local/php-5.5/bin/php" $PHP
ln -sfn "/usr/local/php-5.5/bin/php-config" $PHP_CONFIG
ln -sfn "/usr/local/php-5.5/bin/phpize" $PHPIZE
generate_php_test_proto
wget https://phar.phpunit.de/phpunit-old.phar -O /usr/bin/phpunit
cd php/tests && /bin/bash ./test.sh && cd ../..
pushd conformance
# make test_php_c
make test_php_c
popd
}
build_php5.5_zts_c() {
use_php_zts 5.5
wget https://phar.phpunit.de/phpunit-4.8.0.phar -O /usr/bin/phpunit
wget https://phar.phpunit.de/phpunit-old.phar -O /usr/bin/phpunit
cd php/tests && /bin/bash ./test.sh && cd ../..
pushd conformance
# make test_php_c
make test_php_c
popd
}
build_php5.5_32() {
use_php_bc 5.5
pushd php
rm -rf vendor
cp -r /usr/local/vendor-5.5 vendor
./vendor/bin/phpunit
popd
# TODO(teboring): Add conformance test.
# pushd conformance
# make test_php
# popd
}
build_php5.5_c_32() {
use_php_bc 5.5
wget https://phar.phpunit.de/phpunit-old.phar -O /usr/bin/phpunit
cd php/tests && /bin/bash ./test.sh && cd ../..
# TODO(teboring): Add conformance test.
# pushd conformance
# make test_php_c
# popd
}
build_php5.6() {
use_php 5.6
pushd php
rm -rf vendor
cp -r /usr/local/vendor-5.6 vendor
wget https://phar.phpunit.de/phpunit-5.7.0.phar -O /usr/bin/phpunit
phpunit
./vendor/bin/phpunit
popd
pushd conformance
# TODO(teboring): Add it back
@ -449,19 +485,9 @@ build_php5.6() {
build_php5.6_c() {
use_php 5.6
wget https://phar.phpunit.de/phpunit-5.7.0.phar -O /usr/bin/phpunit
cd php/tests && /bin/bash ./test.sh && cd ../..
pushd conformance
# make test_php_c
popd
}
build_php5.6_zts_c() {
use_php_zts 5.6
wget https://phar.phpunit.de/phpunit-5.7.0.phar -O /usr/bin/phpunit
cd php/tests && /bin/bash ./test.sh && cd ../..
pushd conformance
# make test_php_c
make test_php_c
popd
}
@ -485,7 +511,7 @@ build_php5.6_mac() {
# Test
cd php/tests && /bin/bash ./test.sh && cd ../..
pushd conformance
# make test_php_c
make test_php_c
popd
}
@ -494,8 +520,7 @@ build_php7.0() {
pushd php
rm -rf vendor
cp -r /usr/local/vendor-7.0 vendor
wget https://phar.phpunit.de/phpunit-5.6.0.phar -O /usr/bin/phpunit
phpunit
./vendor/bin/phpunit
popd
pushd conformance
# TODO(teboring): Add it back
@ -505,43 +530,9 @@ build_php7.0() {
build_php7.0_c() {
use_php 7.0
wget https://phar.phpunit.de/phpunit-5.6.0.phar -O /usr/bin/phpunit
cd php/tests && /bin/bash ./test.sh && cd ../..
pushd conformance
# make test_php_c
popd
}
build_php7.0_zts_c() {
use_php_zts 7.0
wget https://phar.phpunit.de/phpunit-5.6.0.phar -O /usr/bin/phpunit
cd php/tests && /bin/bash ./test.sh && cd ../..
pushd conformance
# make test_php_c
popd
}
build_php7.0_mac() {
generate_php_test_proto
# Install PHP
curl -s https://php-osx.liip.ch/install.sh | bash -s 7.0
PHP_FOLDER=`find /usr/local -type d -name "php7-7.0*"` # The folder name may change upon time
export PATH="$PHP_FOLDER/bin:$PATH"
# Install phpunit
curl https://phar.phpunit.de/phpunit-5.6.0.phar -L -o phpunit.phar
chmod +x phpunit.phar
sudo mv phpunit.phar /usr/local/bin/phpunit
# Install valgrind
echo "#! /bin/bash" > valgrind
chmod ug+x valgrind
sudo mv valgrind /usr/local/bin/valgrind
# Test
cd php/tests && /bin/bash ./test.sh && cd ../..
pushd conformance
# make test_php_c
make test_php_c
popd
}
@ -551,10 +542,13 @@ build_php_all() {
build_php7.0
build_php5.5_c
build_php5.6_c
build_php7.0_c
# build_php7.0_c
build_php5.5_zts_c
build_php5.6_zts_c
build_php7.0_zts_c
}
build_php_all_32() {
build_php5.5_32
build_php5.5_c_32
}
# Note: travis currently does not support testing more than one language so the