diff --git a/.gitignore b/.gitignore
index 0cbcf50380..a7349c2aa8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -209,3 +209,6 @@ cmake/cmake-build-debug/
# IntelliJ
.idea
*.iml
+
+# BenchmarkDotNet
+BenchmarkDotNet.Artifacts/
diff --git a/Makefile.am b/Makefile.am
index 39c777c905..631df6f314 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -96,11 +96,14 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Benchmarks/Program.cs \
csharp/src/Google.Protobuf.Benchmarks/wrapper_benchmark_messages.proto \
csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs \
+ csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs \
+ csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs \
csharp/src/Google.Protobuf.Conformance/Conformance.cs \
csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj \
csharp/src/Google.Protobuf.Conformance/Program.cs \
csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj \
csharp/src/Google.Protobuf.JsonDump/Program.cs \
+ csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs \
csharp/src/Google.Protobuf.Test/ByteStringTest.cs \
csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs \
csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs \
@@ -127,6 +130,7 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs \
csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs \
csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs \
+ csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs \
csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs \
csharp/src/Google.Protobuf.Test/Reflection/DescriptorDeclarationTest.cs \
csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs \
@@ -258,6 +262,11 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs \
csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs \
csharp/src/Google.Protobuf/WireFormat.cs \
+ csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs \
+ csharp/src/Google.Protobuf/WritingPrimitives.cs \
+ csharp/src/Google.Protobuf/WriterInternalState.cs \
+ csharp/src/Google.Protobuf/WriteContext.cs \
+ csharp/src/Google.Protobuf/WriteBufferHelper.cs \
csharp/src/Google.Protobuf/UnknownField.cs \
csharp/src/Google.Protobuf/UnknownFieldSet.cs
@@ -758,22 +767,28 @@ php_EXTRA_DIST= \
composer.json \
php/README.md \
php/composer.json \
+ php/ext/google/protobuf/arena.c \
+ php/ext/google/protobuf/arena.h \
php/ext/google/protobuf/array.c \
- php/ext/google/protobuf/builtin_descriptors.inc \
+ php/ext/google/protobuf/array.h \
+ php/ext/google/protobuf/bundled_php.h \
php/ext/google/protobuf/config.m4 \
+ php/ext/google/protobuf/convert.c \
+ php/ext/google/protobuf/convert.h \
php/ext/google/protobuf/def.c \
- php/ext/google/protobuf/encode_decode.c \
+ php/ext/google/protobuf/def.h \
+ php/ext/google/protobuf/make-preload.php \
php/ext/google/protobuf/map.c \
+ php/ext/google/protobuf/map.h \
php/ext/google/protobuf/message.c \
+ php/ext/google/protobuf/message.h \
+ php/ext/google/protobuf/names.c \
+ php/ext/google/protobuf/names.h \
php/ext/google/protobuf/package.xml \
+ php/ext/google/protobuf/php-upb.c \
+ php/ext/google/protobuf/php-upb.h \
php/ext/google/protobuf/protobuf.c \
php/ext/google/protobuf/protobuf.h \
- php/ext/google/protobuf/storage.c \
- php/ext/google/protobuf/type_check.c \
- php/ext/google/protobuf/upb.c \
- php/ext/google/protobuf/upb.h \
- php/ext/google/protobuf/utf8.c \
- php/ext/google/protobuf/utf8.h \
php/generate_descriptor_protos.sh \
php/phpunit.xml \
php/release.sh \
@@ -908,6 +923,7 @@ php_EXTRA_DIST= \
php/tests/descriptors_test.php \
php/tests/encode_decode_test.php \
php/tests/gdb_test.sh \
+ php/tests/generate_protos.sh \
php/tests/generated_class_test.php \
php/tests/generated_phpdoc_test.php \
php/tests/generated_service_test.php \
diff --git a/Protobuf-C++.podspec b/Protobuf-C++.podspec
index 67a96cc7a0..6a51340d0f 100644
--- a/Protobuf-C++.podspec
+++ b/Protobuf-C++.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Protobuf-C++'
- s.version = '3.12.2'
+ s.version = '3.12.3'
s.summary = 'Protocol Buffers v3 runtime library for C++.'
s.homepage = 'https://github.com/google/protobuf'
s.license = '3-Clause BSD License'
diff --git a/configure.ac b/configure.ac
index e473a57914..b7c7f53068 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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.12.2],[protobuf@googlegroups.com],[protobuf])
+AC_INIT([Protocol Buffers],[3.12.3],[protobuf@googlegroups.com],[protobuf])
AM_MAINTAINER_MODE([enable])
diff --git a/conformance/failure_list_php_c.txt b/conformance/failure_list_php_c.txt
index f6c6bc8d24..cfed9f6d4d 100644
--- a/conformance/failure_list_php_c.txt
+++ b/conformance/failure_list_php_c.txt
@@ -1,23 +1,4 @@
-Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
-Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
-Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto2.JsonInput.FieldNameExtension.Validator
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
-Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
-Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
-Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
-Recommended.Proto3.JsonInput.MapFieldValueIsNull
-Recommended.Proto3.JsonInput.OneofZeroBytes.JsonOutput
-Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
-Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
-Recommended.Proto3.JsonInput.StringEndsWithEscapeChar
-Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
-Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
-Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
-Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator
-Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator
-Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
@@ -28,10 +9,8 @@ Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultO
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
@@ -76,36 +55,4 @@ Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOut
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[4].ProtobufOutput
-Required.DurationProtoInputTooLarge.JsonOutput
-Required.DurationProtoInputTooSmall.JsonOutput
Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
-Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
-Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
-Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput
-Required.Proto3.JsonInput.DurationMinValue.JsonOutput
-Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
-Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput
-Required.Proto3.JsonInput.FloatFieldNan.JsonOutput
-Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
-Required.Proto3.JsonInput.OneofFieldDuplicate
-Required.Proto3.JsonInput.RejectTopLevelNull
-Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
-Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
-Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
-Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
-Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
-Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput
-Required.TimestampProtoInputTooLarge.JsonOutput
-Required.TimestampProtoInputTooSmall.JsonOutput
diff --git a/conformance/failure_list_php_c_32.txt b/conformance/failure_list_php_c_32.txt
index 280e5ff3f9..cfed9f6d4d 100644
--- a/conformance/failure_list_php_c_32.txt
+++ b/conformance/failure_list_php_c_32.txt
@@ -1,28 +1,4 @@
-Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
-Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
-Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto2.JsonInput.FieldNameExtension.Validator
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
-Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
-Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
-Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator
-Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator
-Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
-Recommended.Proto3.JsonInput.MapFieldValueIsNull
-Recommended.Proto3.JsonInput.OneofZeroBytes.JsonOutput
-Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
-Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
-Recommended.Proto3.JsonInput.StringEndsWithEscapeChar
-Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
-Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
-Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
-Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator
-Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator
-Recommended.Proto3.JsonInput.TimestampHas9FractionalDigits.Validator
-Recommended.Proto3.JsonInput.TimestampHasZeroFractionalDigit.Validator
-Recommended.Proto3.JsonInput.TimestampZeroNormalized.Validator
-Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
@@ -33,10 +9,8 @@ Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultO
Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
@@ -81,64 +55,4 @@ Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOut
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[4].ProtobufOutput
-Required.DurationProtoInputTooLarge.JsonOutput
-Required.DurationProtoInputTooSmall.JsonOutput
Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
-Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
-Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
-Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput
-Required.Proto3.JsonInput.DurationMaxValue.JsonOutput
-Required.Proto3.JsonInput.DurationMaxValue.ProtobufOutput
-Required.Proto3.JsonInput.DurationMinValue.JsonOutput
-Required.Proto3.JsonInput.DurationMinValue.ProtobufOutput
-Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
-Required.Proto3.JsonInput.DurationRepeatedValue.ProtobufOutput
-Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput
-Required.Proto3.JsonInput.FloatFieldNan.JsonOutput
-Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
-Required.Proto3.JsonInput.Int64FieldMaxValue.JsonOutput
-Required.Proto3.JsonInput.Int64FieldMaxValueNotQuoted.JsonOutput
-Required.Proto3.JsonInput.Int64FieldMaxValueNotQuoted.ProtobufOutput
-Required.Proto3.JsonInput.Int64FieldMaxValue.ProtobufOutput
-Required.Proto3.JsonInput.Int64FieldMinValue.JsonOutput
-Required.Proto3.JsonInput.Int64FieldMinValueNotQuoted.JsonOutput
-Required.Proto3.JsonInput.Int64FieldMinValueNotQuoted.ProtobufOutput
-Required.Proto3.JsonInput.Int64FieldMinValue.ProtobufOutput
-Required.Proto3.JsonInput.OneofFieldDuplicate
-Required.Proto3.JsonInput.RejectTopLevelNull
-Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
-Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
-Required.Proto3.JsonInput.TimestampLeap.JsonOutput
-Required.Proto3.JsonInput.TimestampLeap.ProtobufOutput
-Required.Proto3.JsonInput.TimestampMaxValue.JsonOutput
-Required.Proto3.JsonInput.TimestampMaxValue.ProtobufOutput
-Required.Proto3.JsonInput.TimestampMinValue.JsonOutput
-Required.Proto3.JsonInput.TimestampMinValue.ProtobufOutput
-Required.Proto3.JsonInput.TimestampRepeatedValue.JsonOutput
-Required.Proto3.JsonInput.TimestampRepeatedValue.ProtobufOutput
-Required.Proto3.JsonInput.TimestampWithNegativeOffset.JsonOutput
-Required.Proto3.JsonInput.TimestampWithNegativeOffset.ProtobufOutput
-Required.Proto3.JsonInput.TimestampWithPositiveOffset.JsonOutput
-Required.Proto3.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
-Required.Proto3.JsonInput.Uint64FieldMaxValue.JsonOutput
-Required.Proto3.JsonInput.Uint64FieldMaxValueNotQuoted.JsonOutput
-Required.Proto3.JsonInput.Uint64FieldMaxValueNotQuoted.ProtobufOutput
-Required.Proto3.JsonInput.Uint64FieldMaxValue.ProtobufOutput
-Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
-Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
-Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
-Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput
-Required.TimestampProtoInputTooLarge.JsonOutput
-Required.TimestampProtoInputTooSmall.JsonOutput
diff --git a/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj b/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj
index e2fe2556f1..37bbc3ef2f 100644
--- a/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj
+++ b/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj
@@ -11,6 +11,10 @@
true
+
+
+
+
diff --git a/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs
index 2f226a323c..6df1c872c3 100644
--- a/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs
+++ b/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs
@@ -54,10 +54,12 @@ namespace Google.Protobuf.Benchmarks
// key is the encodedSize of string values
Dictionary stringInputBuffers;
+ Dictionary> stringInputBuffersSegmented;
Random random = new Random(417384220); // random but deterministic seed
public IEnumerable StringEncodedSizes => new[] { 1, 4, 10, 105, 10080 };
+ public IEnumerable StringSegmentedEncodedSizes => new[] { 105, 10080 };
[GlobalSetup]
public void GlobalSetup()
@@ -78,11 +80,18 @@ namespace Google.Protobuf.Benchmarks
fixedIntInputBuffer = CreateBufferWithRandomData(random, BytesToParse / sizeof(long), sizeof(long), paddingValueCount);
stringInputBuffers = new Dictionary();
- foreach(var encodedSize in StringEncodedSizes)
+ foreach (var encodedSize in StringEncodedSizes)
{
byte[] buffer = CreateBufferWithStrings(BytesToParse / encodedSize, encodedSize, encodedSize < 10 ? 10 : 1 );
stringInputBuffers.Add(encodedSize, buffer);
}
+
+ stringInputBuffersSegmented = new Dictionary>();
+ foreach (var encodedSize in StringSegmentedEncodedSizes)
+ {
+ byte[] buffer = CreateBufferWithStrings(BytesToParse / encodedSize, encodedSize, encodedSize < 10 ? 10 : 1);
+ stringInputBuffersSegmented.Add(encodedSize, ReadOnlySequenceFactory.CreateWithContent(buffer, segmentSize: 128, addEmptySegmentDelimiters: false));
+ }
}
// Total number of bytes that each benchmark will parse.
@@ -300,6 +309,19 @@ namespace Google.Protobuf.Benchmarks
return sum;
}
+ [Benchmark]
+ [ArgumentsSource(nameof(StringSegmentedEncodedSizes))]
+ public int ParseString_ParseContext_MultipleSegments(int encodedSize)
+ {
+ InitializeParseContext(stringInputBuffersSegmented[encodedSize], out ParseContext ctx);
+ int sum = 0;
+ for (int i = 0; i < BytesToParse / encodedSize; i++)
+ {
+ sum += ctx.ReadString().Length;
+ }
+ return sum;
+ }
+
[Benchmark]
[ArgumentsSource(nameof(StringEncodedSizes))]
public int ParseBytes_CodedInputStream(int encodedSize)
@@ -326,11 +348,29 @@ namespace Google.Protobuf.Benchmarks
return sum;
}
+ [Benchmark]
+ [ArgumentsSource(nameof(StringSegmentedEncodedSizes))]
+ public int ParseBytes_ParseContext_MultipleSegments(int encodedSize)
+ {
+ InitializeParseContext(stringInputBuffersSegmented[encodedSize], out ParseContext ctx);
+ int sum = 0;
+ for (int i = 0; i < BytesToParse / encodedSize; i++)
+ {
+ sum += ctx.ReadBytes().Length;
+ }
+ return sum;
+ }
+
private static void InitializeParseContext(byte[] buffer, out ParseContext ctx)
{
ParseContext.Initialize(new ReadOnlySequence(buffer), out ctx);
}
+ private static void InitializeParseContext(ReadOnlySequence buffer, out ParseContext ctx)
+ {
+ ParseContext.Initialize(buffer, out ctx);
+ }
+
private static byte[] CreateBufferWithRandomVarints(Random random, int valueCount, int encodedSize, int paddingValueCount)
{
MemoryStream ms = new MemoryStream();
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs
index 451709f4dd..7d3a238eb4 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs
@@ -55,12 +55,19 @@ namespace ProtobufUnittest {
"X2Jvb2xCEgoQX29wdGlvbmFsX3N0cmluZ0IRCg9fb3B0aW9uYWxfYnl0ZXNC",
"EAoOX29wdGlvbmFsX2NvcmRCGgoYX29wdGlvbmFsX25lc3RlZF9tZXNzYWdl",
"QhYKFF9sYXp5X25lc3RlZF9tZXNzYWdlQhcKFV9vcHRpb25hbF9uZXN0ZWRf",
- "ZW51bUIlCiFjb20uZ29vZ2xlLnByb3RvYnVmLnRlc3RpbmcucHJvdG9QAWIG",
- "cHJvdG8z"));
+ "ZW51bSKJAgoZVGVzdFByb3RvM09wdGlvbmFsTWVzc2FnZRJSCg5uZXN0ZWRf",
+ "bWVzc2FnZRgBIAEoCzI6LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQcm90bzNP",
+ "cHRpb25hbE1lc3NhZ2UuTmVzdGVkTWVzc2FnZRJgChdvcHRpb25hbF9uZXN0",
+ "ZWRfbWVzc2FnZRgCIAEoCzI6LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQcm90",
+ "bzNPcHRpb25hbE1lc3NhZ2UuTmVzdGVkTWVzc2FnZUgAiAEBGhoKDU5lc3Rl",
+ "ZE1lc3NhZ2USCQoBcxgBIAEoCUIaChhfb3B0aW9uYWxfbmVzdGVkX21lc3Nh",
+ "Z2VCJQohY29tLmdvb2dsZS5wcm90b2J1Zi50ZXN0aW5nLnByb3RvUAFiBnBy",
+ "b3RvMw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
- new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3Optional), global::ProtobufUnittest.TestProto3Optional.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalCord", "OptionalNestedMessage", "LazyNestedMessage", "OptionalNestedEnum", "SingularInt32", "SingularInt64" }, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalCord", "OptionalNestedMessage", "LazyNestedMessage", "OptionalNestedEnum" }, new[]{ typeof(global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage), global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage.Parser, new[]{ "Bb" }, new[]{ "Bb" }, null, null, null)})
+ new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3Optional), global::ProtobufUnittest.TestProto3Optional.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalCord", "OptionalNestedMessage", "LazyNestedMessage", "OptionalNestedEnum", "SingularInt32", "SingularInt64" }, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalCord", "OptionalNestedMessage", "LazyNestedMessage", "OptionalNestedEnum" }, new[]{ typeof(global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage), global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage.Parser, new[]{ "Bb" }, new[]{ "Bb" }, null, null, null)}),
+ new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3OptionalMessage), global::ProtobufUnittest.TestProto3OptionalMessage.Parser, new[]{ "NestedMessage", "OptionalNestedMessage" }, new[]{ "OptionalNestedMessage" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage), global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage.Parser, new[]{ "S" }, null, null, null, null)})
}));
}
#endregion
@@ -1377,6 +1384,411 @@ namespace ProtobufUnittest {
}
+ public sealed partial class TestProto3OptionalMessage : pb::IMessage
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ , pb::IBufferMessage
+ #endif
+ {
+ private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestProto3OptionalMessage());
+ private pb::UnknownFieldSet _unknownFields;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pb::MessageParser Parser { get { return _parser; } }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::ProtobufUnittest.UnittestProto3OptionalReflection.Descriptor.MessageTypes[1]; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public TestProto3OptionalMessage() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public TestProto3OptionalMessage(TestProto3OptionalMessage other) : this() {
+ nestedMessage_ = other.nestedMessage_ != null ? other.nestedMessage_.Clone() : null;
+ optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public TestProto3OptionalMessage Clone() {
+ return new TestProto3OptionalMessage(this);
+ }
+
+ /// Field number for the "nested_message" field.
+ public const int NestedMessageFieldNumber = 1;
+ private global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage nestedMessage_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage NestedMessage {
+ get { return nestedMessage_; }
+ set {
+ nestedMessage_ = value;
+ }
+ }
+
+ /// Field number for the "optional_nested_message" field.
+ public const int OptionalNestedMessageFieldNumber = 2;
+ private global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage optionalNestedMessage_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage OptionalNestedMessage {
+ get { return optionalNestedMessage_; }
+ set {
+ optionalNestedMessage_ = value;
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override bool Equals(object other) {
+ return Equals(other as TestProto3OptionalMessage);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public bool Equals(TestProto3OptionalMessage other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (!object.Equals(NestedMessage, other.NestedMessage)) return false;
+ if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false;
+ return Equals(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override int GetHashCode() {
+ int hash = 1;
+ if (nestedMessage_ != null) hash ^= NestedMessage.GetHashCode();
+ if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
+ return hash;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void WriteTo(pb::CodedOutputStream output) {
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ output.WriteRawMessage(this);
+ #else
+ if (nestedMessage_ != null) {
+ output.WriteRawTag(10);
+ output.WriteMessage(NestedMessage);
+ }
+ if (optionalNestedMessage_ != null) {
+ output.WriteRawTag(18);
+ output.WriteMessage(OptionalNestedMessage);
+ }
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
+ #endif
+ }
+
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+ if (nestedMessage_ != null) {
+ output.WriteRawTag(10);
+ output.WriteMessage(NestedMessage);
+ }
+ if (optionalNestedMessage_ != null) {
+ output.WriteRawTag(18);
+ output.WriteMessage(OptionalNestedMessage);
+ }
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(ref output);
+ }
+ }
+ #endif
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int CalculateSize() {
+ int size = 0;
+ if (nestedMessage_ != null) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(NestedMessage);
+ }
+ if (optionalNestedMessage_ != null) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage);
+ }
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
+ return size;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(TestProto3OptionalMessage other) {
+ if (other == null) {
+ return;
+ }
+ if (other.nestedMessage_ != null) {
+ if (nestedMessage_ == null) {
+ NestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage();
+ }
+ NestedMessage.MergeFrom(other.NestedMessage);
+ }
+ if (other.optionalNestedMessage_ != null) {
+ if (optionalNestedMessage_ == null) {
+ OptionalNestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage();
+ }
+ OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage);
+ }
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(pb::CodedInputStream input) {
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ input.ReadRawMessage(this);
+ #else
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+ break;
+ case 10: {
+ if (nestedMessage_ == null) {
+ NestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage();
+ }
+ input.ReadMessage(NestedMessage);
+ break;
+ }
+ case 18: {
+ if (optionalNestedMessage_ == null) {
+ OptionalNestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage();
+ }
+ input.ReadMessage(OptionalNestedMessage);
+ break;
+ }
+ }
+ }
+ #endif
+ }
+
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+ break;
+ case 10: {
+ if (nestedMessage_ == null) {
+ NestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage();
+ }
+ input.ReadMessage(NestedMessage);
+ break;
+ }
+ case 18: {
+ if (optionalNestedMessage_ == null) {
+ OptionalNestedMessage = new global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage();
+ }
+ input.ReadMessage(OptionalNestedMessage);
+ break;
+ }
+ }
+ }
+ }
+ #endif
+
+ #region Nested types
+ /// Container for nested types declared in the TestProto3OptionalMessage message type.
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static partial class Types {
+ public sealed partial class NestedMessage : pb::IMessage
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ , pb::IBufferMessage
+ #endif
+ {
+ private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage());
+ private pb::UnknownFieldSet _unknownFields;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pb::MessageParser Parser { get { return _parser; } }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::ProtobufUnittest.TestProto3OptionalMessage.Descriptor.NestedTypes[0]; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public NestedMessage() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public NestedMessage(NestedMessage other) : this() {
+ s_ = other.s_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public NestedMessage Clone() {
+ return new NestedMessage(this);
+ }
+
+ /// Field number for the "s" field.
+ public const int SFieldNumber = 1;
+ private string s_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public string S {
+ get { return s_; }
+ set {
+ s_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override bool Equals(object other) {
+ return Equals(other as NestedMessage);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public bool Equals(NestedMessage other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (S != other.S) return false;
+ return Equals(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override int GetHashCode() {
+ int hash = 1;
+ if (S.Length != 0) hash ^= S.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
+ return hash;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void WriteTo(pb::CodedOutputStream output) {
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ output.WriteRawMessage(this);
+ #else
+ if (S.Length != 0) {
+ output.WriteRawTag(10);
+ output.WriteString(S);
+ }
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
+ #endif
+ }
+
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+ if (S.Length != 0) {
+ output.WriteRawTag(10);
+ output.WriteString(S);
+ }
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(ref output);
+ }
+ }
+ #endif
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int CalculateSize() {
+ int size = 0;
+ if (S.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(S);
+ }
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
+ return size;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(NestedMessage other) {
+ if (other == null) {
+ return;
+ }
+ if (other.S.Length != 0) {
+ S = other.S;
+ }
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(pb::CodedInputStream input) {
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ input.ReadRawMessage(this);
+ #else
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+ break;
+ case 10: {
+ S = input.ReadString();
+ break;
+ }
+ }
+ }
+ #endif
+ }
+
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+ break;
+ case 10: {
+ S = input.ReadString();
+ break;
+ }
+ }
+ }
+ }
+ #endif
+
+ }
+
+ }
+ #endregion
+
+ }
+
#endregion
}
diff --git a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
index bcc6ace289..1fb3bb5039 100644
--- a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
+++ b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
@@ -324,7 +324,25 @@ namespace Google.Protobuf
Assert.AreEqual(message, message2);
}
}
-
+
+ [Test]
+ public void ReadWholeMessage_VaryingBlockSizes_FromSequence()
+ {
+ TestAllTypes message = SampleMessages.CreateFullTestAllTypes();
+
+ byte[] rawBytes = message.ToByteArray();
+ Assert.AreEqual(rawBytes.Length, message.CalculateSize());
+ TestAllTypes message2 = TestAllTypes.Parser.ParseFrom(rawBytes);
+ Assert.AreEqual(message, message2);
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize < 256; blockSize *= 2)
+ {
+ message2 = TestAllTypes.Parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(rawBytes, blockSize));
+ Assert.AreEqual(message, message2);
+ }
+ }
+
[Test]
public void ReadHugeBlob()
{
@@ -365,6 +383,70 @@ namespace Google.Protobuf
Assert.Throws(() => input.ReadBytes());
}
+ [Test]
+ public void ReadBlobGreaterThanCurrentLimit()
+ {
+ MemoryStream ms = new MemoryStream();
+ CodedOutputStream output = new CodedOutputStream(ms);
+ uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+ output.WriteRawVarint32(tag);
+ output.WriteRawVarint32(4);
+ output.WriteRawBytes(new byte[4]); // Pad with a few random bytes.
+ output.Flush();
+ ms.Position = 0;
+
+ CodedInputStream input = new CodedInputStream(ms);
+ Assert.AreEqual(tag, input.ReadTag());
+
+ // Specify limit smaller than data length
+ input.PushLimit(3);
+ Assert.Throws(() => input.ReadBytes());
+
+ AssertReadFromParseContext(new ReadOnlySequence(ms.ToArray()), (ref ParseContext ctx) =>
+ {
+ Assert.AreEqual(tag, ctx.ReadTag());
+ SegmentedBufferHelper.PushLimit(ref ctx.state, 3);
+ try
+ {
+ ctx.ReadBytes();
+ Assert.Fail();
+ }
+ catch (InvalidProtocolBufferException) {}
+ }, true);
+ }
+
+ [Test]
+ public void ReadStringGreaterThanCurrentLimit()
+ {
+ MemoryStream ms = new MemoryStream();
+ CodedOutputStream output = new CodedOutputStream(ms);
+ uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+ output.WriteRawVarint32(tag);
+ output.WriteRawVarint32(4);
+ output.WriteRawBytes(new byte[4]); // Pad with a few random bytes.
+ output.Flush();
+ ms.Position = 0;
+
+ CodedInputStream input = new CodedInputStream(ms.ToArray());
+ Assert.AreEqual(tag, input.ReadTag());
+
+ // Specify limit smaller than data length
+ input.PushLimit(3);
+ Assert.Throws(() => input.ReadString());
+
+ AssertReadFromParseContext(new ReadOnlySequence(ms.ToArray()), (ref ParseContext ctx) =>
+ {
+ Assert.AreEqual(tag, ctx.ReadTag());
+ SegmentedBufferHelper.PushLimit(ref ctx.state, 3);
+ try
+ {
+ ctx.ReadString();
+ Assert.Fail();
+ }
+ catch (InvalidProtocolBufferException) { }
+ }, true);
+ }
+
// Representations of a tag for field 0 with various wire types
[Test]
[TestCase(0)]
diff --git a/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs b/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs
index 588b559e9f..f0248ac3c3 100644
--- a/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs
+++ b/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs
@@ -41,11 +41,18 @@ namespace Google.Protobuf
{
internal static class ReadOnlySequenceFactory
{
- public static ReadOnlySequence CreateWithContent(byte[] data, int segmentSize = 1)
+ ///
+ /// Create a sequence from the specified data. The data will be divided up into segments in the sequence.
+ ///
+ public static ReadOnlySequence CreateWithContent(byte[] data, int segmentSize = 1, bool addEmptySegmentDelimiters = true)
{
var segments = new List();
- segments.Add(new byte[0]);
+ if (addEmptySegmentDelimiters)
+ {
+ segments.Add(new byte[0]);
+ }
+
var currentIndex = 0;
while (currentIndex < data.Length)
{
@@ -55,7 +62,11 @@ namespace Google.Protobuf
segment.Add(data[currentIndex++]);
}
segments.Add(segment.ToArray());
- segments.Add(new byte[0]);
+
+ if (addEmptySegmentDelimiters)
+ {
+ segments.Add(new byte[0]);
+ }
}
return CreateSegments(segments.ToArray());
diff --git a/csharp/src/Google.Protobuf.Test/testprotos.pb b/csharp/src/Google.Protobuf.Test/testprotos.pb
index f7313edc83..bde0dae504 100644
Binary files a/csharp/src/Google.Protobuf.Test/testprotos.pb and b/csharp/src/Google.Protobuf.Test/testprotos.pb differ
diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
index 69adcdfafc..19114caa24 100644
--- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
+++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
@@ -133,7 +133,7 @@ namespace Google.Protobuf.Collections
//
// Check that the supplied length doesn't exceed the underlying buffer.
// That prevents a malicious length from initializing a very large collection.
- if (codec.FixedSize > 0 && length % codec.FixedSize == 0 && IsDataAvailable(ref ctx, length))
+ if (codec.FixedSize > 0 && length % codec.FixedSize == 0 && ParsingPrimitives.IsDataAvailable(ref ctx.state, length))
{
EnsureSize(count + (length / codec.FixedSize));
@@ -167,24 +167,6 @@ namespace Google.Protobuf.Collections
}
}
- private bool IsDataAvailable(ref ParseContext ctx, int size)
- {
- // Data fits in remaining buffer
- if (size <= ctx.state.bufferSize - ctx.state.bufferPos)
- {
- return true;
- }
-
- // Data fits in remaining source data.
- // Note that this will never be true when reading from a stream as the total length is unknown.
- if (size < ctx.state.segmentedBufferHelper.TotalLength - ctx.state.totalBytesRetired - ctx.state.bufferPos)
- {
- return true;
- }
-
- return false;
- }
-
///
/// Calculates the size of this collection based on the given codec.
///
diff --git a/csharp/src/Google.Protobuf/ParserInternalState.cs b/csharp/src/Google.Protobuf/ParserInternalState.cs
index 50d489dfc4..cb4f47143c 100644
--- a/csharp/src/Google.Protobuf/ParserInternalState.cs
+++ b/csharp/src/Google.Protobuf/ParserInternalState.cs
@@ -43,7 +43,7 @@ using Google.Protobuf.Collections;
namespace Google.Protobuf
{
-
+
// warning: this is a mutable struct, so it needs to be only passed as a ref!
internal struct ParserInternalState
{
@@ -54,12 +54,12 @@ namespace Google.Protobuf
/// The position within the current buffer (i.e. the next byte to read)
///
internal int bufferPos;
-
+
///
/// Size of the current buffer
///
internal int bufferSize;
-
+
///
/// If we are currently inside a length-delimited block, this is the number of
/// bytes in the buffer that are still available once we leave the delimited block.
@@ -79,9 +79,9 @@ namespace Google.Protobuf
internal int totalBytesRetired;
internal int recursionDepth; // current recursion depth
-
+
internal SegmentedBufferHelper segmentedBufferHelper;
-
+
///
/// The last tag we read. 0 indicates we've read to the end of the stream
/// (or haven't read anything yet).
@@ -101,7 +101,7 @@ namespace Google.Protobuf
// If non-null, the top level parse method was started with given coded input stream as an argument
// which also means we can potentially fallback to calling MergeFrom(CodedInputStream cis) if needed.
internal CodedInputStream CodedInputStream => segmentedBufferHelper.CodedInputStream;
-
+
///
/// Internal-only property; when set to true, unknown fields will be discarded while parsing.
///
diff --git a/csharp/src/Google.Protobuf/ParsingPrimitives.cs b/csharp/src/Google.Protobuf/ParsingPrimitives.cs
index ebb40840aa..e270ed8aa1 100644
--- a/csharp/src/Google.Protobuf/ParsingPrimitives.cs
+++ b/csharp/src/Google.Protobuf/ParsingPrimitives.cs
@@ -34,6 +34,7 @@ using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -49,6 +50,7 @@ namespace Google.Protobuf
[SecuritySafeCritical]
internal static class ParsingPrimitives
{
+ private const int StackallocThreshold = 256;
///
/// Reads a length for length-delimited data.
@@ -58,7 +60,6 @@ namespace Google.Protobuf
/// to make the calling code clearer.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
-
public static int ParseLength(ref ReadOnlySpan buffer, ref ParserInternalState state)
{
return (int)ParseRawVarint32(ref buffer, ref state);
@@ -437,14 +438,6 @@ namespace Google.Protobuf
throw InvalidProtocolBufferException.NegativeSize();
}
- if (state.totalBytesRetired + state.bufferPos + size > state.currentLimit)
- {
- // Read to the end of the stream (up to the current limit) anyway.
- SkipRawBytes(ref buffer, ref state, state.currentLimit - state.totalBytesRetired - state.bufferPos);
- // Then fail.
- throw InvalidProtocolBufferException.TruncatedMessage();
- }
-
if (size <= state.bufferSize - state.bufferPos)
{
// We have all the bytes we need already.
@@ -453,36 +446,22 @@ namespace Google.Protobuf
state.bufferPos += size;
return bytes;
}
- else if (size < buffer.Length || size < state.segmentedBufferHelper.TotalLength)
+
+ return ReadRawBytesSlow(ref buffer, ref state, size);
+ }
+
+ private static byte[] ReadRawBytesSlow(ref ReadOnlySpan buffer, ref ParserInternalState state, int size)
+ {
+ ValidateCurrentLimit(ref buffer, ref state, size);
+
+ if ((!state.segmentedBufferHelper.TotalLength.HasValue && size < buffer.Length) ||
+ IsDataAvailableInSource(ref state, size))
{
// Reading more bytes than are in the buffer, but not an excessive number
// of bytes. We can safely allocate the resulting array ahead of time.
- // First copy what we have.
byte[] bytes = new byte[size];
- var bytesSpan = new Span(bytes);
- int pos = state.bufferSize - state.bufferPos;
- buffer.Slice(state.bufferPos, pos).CopyTo(bytesSpan.Slice(0, pos));
- state.bufferPos = state.bufferSize;
-
- // We want to use RefillBuffer() and then copy from the buffer into our
- // byte array rather than reading directly into our byte array because
- // the input may be unbuffered.
- state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true);
-
- while (size - pos > state.bufferSize)
- {
- buffer.Slice(0, state.bufferSize)
- .CopyTo(bytesSpan.Slice(pos, state.bufferSize));
- pos += state.bufferSize;
- state.bufferPos = state.bufferSize;
- state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true);
- }
-
- buffer.Slice(0, size - pos)
- .CopyTo(bytesSpan.Slice(pos, size - pos));
- state.bufferPos = size - pos;
-
+ ReadRawBytesIntoSpan(ref buffer, ref state, size, bytes);
return bytes;
}
else
@@ -518,7 +497,7 @@ namespace Google.Protobuf
}
// OK, got everything. Now concatenate it all into one buffer.
- byte[] bytes = new byte[size];
+ byte[] bytes = new byte[size];
int newPos = 0;
foreach (byte[] chunk in chunks)
{
@@ -543,13 +522,7 @@ namespace Google.Protobuf
throw InvalidProtocolBufferException.NegativeSize();
}
- if (state.totalBytesRetired + state.bufferPos + size > state.currentLimit)
- {
- // Read to the end of the stream anyway.
- SkipRawBytes(ref buffer, ref state, state.currentLimit - state.totalBytesRetired - state.bufferPos);
- // Then fail.
- throw InvalidProtocolBufferException.TruncatedMessage();
- }
+ ValidateCurrentLimit(ref buffer, ref state, size);
if (size <= state.bufferSize - state.bufferPos)
{
@@ -619,7 +592,7 @@ namespace Google.Protobuf
}
#if GOOGLE_PROTOBUF_SUPPORT_FAST_STRING
- if (length <= state.bufferSize - state.bufferPos && length > 0)
+ if (length <= state.bufferSize - state.bufferPos)
{
// Fast path: all bytes to decode appear in the same span.
ReadOnlySpan data = buffer.Slice(state.bufferPos, length);
@@ -638,20 +611,76 @@ namespace Google.Protobuf
}
#endif
- var decoder = WritingPrimitives.Utf8Encoding.GetDecoder();
+ return ReadStringSlow(ref buffer, ref state, length);
+ }
- // TODO: even if GOOGLE_PROTOBUF_SUPPORT_FAST_STRING is not supported,
- // we could still create a string efficiently by using Utf8Encoding.GetString(byte[] bytes, int index, int count)
- // whenever the buffer is backed by a byte array (and avoid creating a new byte array), but the problem is
- // there is no way to get the underlying byte array from a span.
+ ///
+ /// Reads a string assuming that it is spread across multiple spans in a .
+ ///
+ private static string ReadStringSlow(ref ReadOnlySpan buffer, ref ParserInternalState state, int length)
+ {
+ ValidateCurrentLimit(ref buffer, ref state, length);
+
+#if GOOGLE_PROTOBUF_SUPPORT_FAST_STRING
+ if (IsDataAvailable(ref state, length))
+ {
+ // Read string data into a temporary buffer, either stackalloc'ed or from ArrayPool
+ // Once all data is read then call Encoding.GetString on buffer and return to pool if needed.
- // TODO: in case the string spans multiple buffer segments, creating a char[] and decoding into it and then
- // creating a string from that array might be more efficient than creating a string from the copied bytes.
+ byte[] byteArray = null;
+ Span byteSpan = length <= StackallocThreshold ?
+ stackalloc byte[length] :
+ (byteArray = ArrayPool.Shared.Rent(length));
+
+ try
+ {
+ unsafe
+ {
+ fixed (byte* pByteSpan = &MemoryMarshal.GetReference(byteSpan))
+ {
+ // Compiler doesn't like that a potentially stackalloc'd Span is being used
+ // in a method with a "ref Span buffer" argument. If the stackalloc'd span was assigned
+ // to the ref argument then bad things would happen. We'll never do that so it is ok.
+ // Make compiler happy by passing a new span created from pointer.
+ var tempSpan = new Span(pByteSpan, byteSpan.Length);
+ ReadRawBytesIntoSpan(ref buffer, ref state, length, tempSpan);
+
+ return WritingPrimitives.Utf8Encoding.GetString(pByteSpan, length);
+ }
+ }
+ }
+ finally
+ {
+ if (byteArray != null)
+ {
+ ArrayPool.Shared.Return(byteArray);
+ }
+ }
+ }
+#endif
// Slow path: Build a byte array first then copy it.
+ // This will be called when reading from a Stream because we don't know the length of the stream,
+ // or there is not enough data in the sequence. If there is not enough data then ReadRawBytes will
+ // throw an exception.
return WritingPrimitives.Utf8Encoding.GetString(ReadRawBytes(ref buffer, ref state, length), 0, length);
}
+ ///
+ /// Validates that the specified size doesn't exceed the current limit. If it does then remaining bytes
+ /// are skipped and an error is thrown.
+ ///
+ private static void ValidateCurrentLimit(ref ReadOnlySpan buffer, ref ParserInternalState state, int size)
+ {
+ if (state.totalBytesRetired + state.bufferPos + size > state.currentLimit)
+ {
+ // Read to the end of the stream (up to the current limit) anyway.
+ SkipRawBytes(ref buffer, ref state, state.currentLimit - state.totalBytesRetired - state.bufferPos);
+ // Then fail.
+ throw InvalidProtocolBufferException.TruncatedMessage();
+ }
+ }
+
[SecuritySafeCritical]
private static byte ReadRawByte(ref ReadOnlySpan buffer, ref ParserInternalState state)
{
@@ -731,5 +760,56 @@ namespace Google.Protobuf
{
return (long)(n >> 1) ^ -(long)(n & 1);
}
+
+ ///
+ /// Checks whether there is known data available of the specified size remaining to parse.
+ /// When parsing from a Stream this can return false because we have no knowledge of the amount
+ /// of data remaining in the stream until it is read.
+ ///
+ public static bool IsDataAvailable(ref ParserInternalState state, int size)
+ {
+ // Data fits in remaining buffer
+ if (size <= state.bufferSize - state.bufferPos)
+ {
+ return true;
+ }
+
+ return IsDataAvailableInSource(ref state, size);
+ }
+
+ ///
+ /// Checks whether there is known data available of the specified size remaining to parse
+ /// in the underlying data source.
+ /// When parsing from a Stream this will return false because we have no knowledge of the amount
+ /// of data remaining in the stream until it is read.
+ ///
+ private static bool IsDataAvailableInSource(ref ParserInternalState state, int size)
+ {
+ // Data fits in remaining source data.
+ // Note that this will never be true when reading from a stream as the total length is unknown.
+ return size <= state.segmentedBufferHelper.TotalLength - state.totalBytesRetired - state.bufferPos;
+ }
+
+ ///
+ /// Read raw bytes of the specified length into a span. The amount of data available and the current limit should
+ /// be checked before calling this method.
+ ///
+ private static void ReadRawBytesIntoSpan(ref ReadOnlySpan buffer, ref ParserInternalState state, int length, Span byteSpan)
+ {
+ int remainingByteLength = length;
+ while (remainingByteLength > 0)
+ {
+ if (state.bufferSize - state.bufferPos == 0)
+ {
+ state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true);
+ }
+
+ ReadOnlySpan unreadSpan = buffer.Slice(state.bufferPos, Math.Min(remainingByteLength, state.bufferSize - state.bufferPos));
+ unreadSpan.CopyTo(byteSpan.Slice(length - remainingByteLength));
+
+ remainingByteLength -= unreadSpan.Length;
+ state.bufferPos += unreadSpan.Length;
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh
index e533d05b43..dc03fee019 100755
--- a/generate_descriptor_proto.sh
+++ b/generate_descriptor_proto.sh
@@ -62,7 +62,7 @@ do
PROTOC=$BOOTSTRAP_PROTOC
BOOTSTRAP_PROTOC=""
else
- make $@ protoc
+ make -j$(nproc) $@ protoc
if test $? -ne 0; then
echo "Failed to build protoc."
exit 1
diff --git a/js/gulpfile.js b/js/gulpfile.js
index a81c011179..8137b90702 100644
--- a/js/gulpfile.js
+++ b/js/gulpfile.js
@@ -71,13 +71,16 @@ gulp.task('genproto_group1_closure', function (cb) {
});
});
-gulp.task('genproto_group2_closure', function (cb) {
- exec(protoc + ' --js_out=library=testproto_libs2,binary:. -I ../src -I . -I commonjs ' + group2Protos.join(' '),
- function (err, stdout, stderr) {
- console.log(stdout);
- console.log(stderr);
- cb(err);
- });
+gulp.task('genproto_group2_closure', function(cb) {
+ exec(
+ protoc +
+ ' --experimental_allow_proto3_optional --js_out=library=testproto_libs2,binary:. -I ../src -I . -I commonjs ' +
+ group2Protos.join(' '),
+ function(err, stdout, stderr) {
+ console.log(stdout);
+ console.log(stderr);
+ cb(err);
+ });
});
gulp.task('genproto_well_known_types_commonjs', function (cb) {
@@ -98,13 +101,16 @@ gulp.task('genproto_group1_commonjs', function (cb) {
});
});
-gulp.task('genproto_group2_commonjs', function (cb) {
- exec('mkdir -p commonjs_out && ' + protoc + ' --js_out=import_style=commonjs,binary:commonjs_out -I ../src -I commonjs -I . ' + group2Protos.join(' '),
- function (err, stdout, stderr) {
- console.log(stdout);
- console.log(stderr);
- cb(err);
- });
+gulp.task('genproto_group2_commonjs', function(cb) {
+ exec(
+ 'mkdir -p commonjs_out && ' + protoc +
+ ' --experimental_allow_proto3_optional --js_out=import_style=commonjs,binary:commonjs_out -I ../src -I commonjs -I . ' +
+ group2Protos.join(' '),
+ function(err, stdout, stderr) {
+ console.log(stdout);
+ console.log(stderr);
+ cb(err);
+ });
});
gulp.task('genproto_commonjs_wellknowntypes', function (cb) {
diff --git a/js/package.json b/js/package.json
index 7fd5e69679..e4934e544c 100644
--- a/js/package.json
+++ b/js/package.json
@@ -1,6 +1,6 @@
{
"name": "google-protobuf",
- "version": "3.12.2",
+ "version": "3.12.3",
"description": "Protocol Buffers for JavaScript",
"main": "google-protobuf.js",
"files": [
diff --git a/js/proto3_test.js b/js/proto3_test.js
index 79acc3c261..fd59ae50d6 100644
--- a/js/proto3_test.js
+++ b/js/proto3_test.js
@@ -77,7 +77,7 @@ describe('proto3Test', function() {
it('testEqualsProto3', function() {
var msg1 = new proto.jspb.test.TestProto3();
var msg2 = new proto.jspb.test.TestProto3();
- msg2.setOptionalString('');
+ msg2.setSingularString('');
assertTrue(jspb.Message.equals(msg1, msg2));
});
@@ -90,12 +90,12 @@ describe('proto3Test', function() {
var msg = new proto.jspb.test.TestProto3();
// Setting should work normally.
- msg.setOptionalString('optionalString');
- assertEquals(msg.getOptionalString(), 'optionalString');
+ msg.setSingularString('optionalString');
+ assertEquals(msg.getSingularString(), 'optionalString');
// Clearing should work too ...
- msg.setOptionalString('');
- assertEquals(msg.getOptionalString(), '');
+ msg.setSingularString('');
+ assertEquals(msg.getSingularString(), '');
// ... and shouldn't affect the equality with a brand new message.
assertTrue(jspb.Message.equals(msg, new proto.jspb.test.TestProto3()));
@@ -107,6 +107,58 @@ describe('proto3Test', function() {
it('testProto3FieldDefaults', function() {
var msg = new proto.jspb.test.TestProto3();
+ assertEquals(msg.getSingularInt32(), 0);
+ assertEquals(msg.getSingularInt64(), 0);
+ assertEquals(msg.getSingularUint32(), 0);
+ assertEquals(msg.getSingularUint64(), 0);
+ assertEquals(msg.getSingularSint32(), 0);
+ assertEquals(msg.getSingularSint64(), 0);
+ assertEquals(msg.getSingularFixed32(), 0);
+ assertEquals(msg.getSingularFixed64(), 0);
+ assertEquals(msg.getSingularSfixed32(), 0);
+ assertEquals(msg.getSingularSfixed64(), 0);
+ assertEquals(msg.getSingularFloat(), 0);
+ assertEquals(msg.getSingularDouble(), 0);
+ assertEquals(msg.getSingularString(), '');
+
+ // TODO(b/26173701): when we change bytes fields default getter to return
+ // Uint8Array, we'll want to switch this assertion to match the u8 case.
+ assertEquals(typeof msg.getSingularBytes(), 'string');
+ assertEquals(msg.getSingularBytes_asU8() instanceof Uint8Array, true);
+ assertEquals(typeof msg.getSingularBytes_asB64(), 'string');
+ assertEquals(msg.getSingularBytes().length, 0);
+ assertEquals(msg.getSingularBytes_asU8().length, 0);
+ assertEquals(msg.getSingularBytes_asB64(), '');
+
+ assertEquals(
+ msg.getSingularForeignEnum(), proto.jspb.test.Proto3Enum.PROTO3_FOO);
+ assertEquals(msg.getSingularForeignMessage(), undefined);
+ assertEquals(msg.getSingularForeignMessage(), undefined);
+
+ assertEquals(msg.getRepeatedInt32List().length, 0);
+ assertEquals(msg.getRepeatedInt64List().length, 0);
+ assertEquals(msg.getRepeatedUint32List().length, 0);
+ assertEquals(msg.getRepeatedUint64List().length, 0);
+ assertEquals(msg.getRepeatedSint32List().length, 0);
+ assertEquals(msg.getRepeatedSint64List().length, 0);
+ assertEquals(msg.getRepeatedFixed32List().length, 0);
+ assertEquals(msg.getRepeatedFixed64List().length, 0);
+ assertEquals(msg.getRepeatedSfixed32List().length, 0);
+ assertEquals(msg.getRepeatedSfixed64List().length, 0);
+ assertEquals(msg.getRepeatedFloatList().length, 0);
+ assertEquals(msg.getRepeatedDoubleList().length, 0);
+ assertEquals(msg.getRepeatedStringList().length, 0);
+ assertEquals(msg.getRepeatedBytesList().length, 0);
+ assertEquals(msg.getRepeatedForeignEnumList().length, 0);
+ assertEquals(msg.getRepeatedForeignMessageList().length, 0);
+ });
+
+ /**
+ * Test presence for proto3 optional fields.
+ */
+ it('testProto3Optional', function() {
+ var msg = new proto.jspb.test.TestProto3();
+
assertEquals(msg.getOptionalInt32(), 0);
assertEquals(msg.getOptionalInt64(), 0);
assertEquals(msg.getOptionalUint32(), 0);
@@ -135,51 +187,65 @@ describe('proto3Test', function() {
assertEquals(msg.getOptionalForeignMessage(), undefined);
assertEquals(msg.getOptionalForeignMessage(), undefined);
- assertEquals(msg.getRepeatedInt32List().length, 0);
- assertEquals(msg.getRepeatedInt64List().length, 0);
- assertEquals(msg.getRepeatedUint32List().length, 0);
- assertEquals(msg.getRepeatedUint64List().length, 0);
- assertEquals(msg.getRepeatedSint32List().length, 0);
- assertEquals(msg.getRepeatedSint64List().length, 0);
- assertEquals(msg.getRepeatedFixed32List().length, 0);
- assertEquals(msg.getRepeatedFixed64List().length, 0);
- assertEquals(msg.getRepeatedSfixed32List().length, 0);
- assertEquals(msg.getRepeatedSfixed64List().length, 0);
- assertEquals(msg.getRepeatedFloatList().length, 0);
- assertEquals(msg.getRepeatedDoubleList().length, 0);
- assertEquals(msg.getRepeatedStringList().length, 0);
- assertEquals(msg.getRepeatedBytesList().length, 0);
- assertEquals(msg.getRepeatedForeignEnumList().length, 0);
- assertEquals(msg.getRepeatedForeignMessageList().length, 0);
+ // Serializing an empty proto yields the empty string.
+ assertEquals(msg.serializeBinary().length, 0);
- });
+ // Values start as unset, but can be explicitly set even to default values
+ // like 0.
+ assertFalse(msg.hasOptionalInt32());
+ msg.setOptionalInt32(0);
+ assertTrue(msg.hasOptionalInt32());
+
+ assertFalse(msg.hasOptionalInt64());
+ msg.setOptionalInt64(0);
+ assertTrue(msg.hasOptionalInt64());
+
+ assertFalse(msg.hasOptionalString());
+ msg.setOptionalString('');
+ assertTrue(msg.hasOptionalString());
+
+ // Now the proto will have a non-zero size, even though its values are 0.
+ var serialized = msg.serializeBinary();
+ assertNotEquals(serialized.length, 0);
+
+ var msg2 = proto.jspb.test.TestProto3.deserializeBinary(serialized);
+ assertTrue(msg2.hasOptionalInt32());
+ assertTrue(msg2.hasOptionalInt64());
+ assertTrue(msg2.hasOptionalString());
+ // We can clear fields to go back to empty.
+ msg2.clearOptionalInt32();
+ assertFalse(msg2.hasOptionalInt32());
+
+ msg2.clearOptionalString();
+ assertFalse(msg2.hasOptionalString());
+ });
/**
- * Test that all fields can be set and read via a serialization roundtrip.
+ * Test that all fields can be set ,and read via a serialization roundtrip.
*/
it('testProto3FieldSetGet', function() {
var msg = new proto.jspb.test.TestProto3();
- msg.setOptionalInt32(-42);
- msg.setOptionalInt64(-0x7fffffff00000000);
- msg.setOptionalUint32(0x80000000);
- msg.setOptionalUint64(0xf000000000000000);
- msg.setOptionalSint32(-100);
- msg.setOptionalSint64(-0x8000000000000000);
- msg.setOptionalFixed32(1234);
- msg.setOptionalFixed64(0x1234567800000000);
- msg.setOptionalSfixed32(-1234);
- msg.setOptionalSfixed64(-0x1234567800000000);
- msg.setOptionalFloat(1.5);
- msg.setOptionalDouble(-1.5);
- msg.setOptionalBool(true);
- msg.setOptionalString('hello world');
- msg.setOptionalBytes(BYTES);
+ msg.setSingularInt32(-42);
+ msg.setSingularInt64(-0x7fffffff00000000);
+ msg.setSingularUint32(0x80000000);
+ msg.setSingularUint64(0xf000000000000000);
+ msg.setSingularSint32(-100);
+ msg.setSingularSint64(-0x8000000000000000);
+ msg.setSingularFixed32(1234);
+ msg.setSingularFixed64(0x1234567800000000);
+ msg.setSingularSfixed32(-1234);
+ msg.setSingularSfixed64(-0x1234567800000000);
+ msg.setSingularFloat(1.5);
+ msg.setSingularDouble(-1.5);
+ msg.setSingularBool(true);
+ msg.setSingularString('hello world');
+ msg.setSingularBytes(BYTES);
var submsg = new proto.jspb.test.ForeignMessage();
submsg.setC(16);
- msg.setOptionalForeignMessage(submsg);
- msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
+ msg.setSingularForeignMessage(submsg);
+ msg.setSingularForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
msg.setRepeatedInt32List([-42]);
msg.setRepeatedInt64List([-0x7fffffff00000000]);
@@ -206,24 +272,24 @@ describe('proto3Test', function() {
var serialized = msg.serializeBinary();
msg = proto.jspb.test.TestProto3.deserializeBinary(serialized);
- assertEquals(msg.getOptionalInt32(), -42);
- assertEquals(msg.getOptionalInt64(), -0x7fffffff00000000);
- assertEquals(msg.getOptionalUint32(), 0x80000000);
- assertEquals(msg.getOptionalUint64(), 0xf000000000000000);
- assertEquals(msg.getOptionalSint32(), -100);
- assertEquals(msg.getOptionalSint64(), -0x8000000000000000);
- assertEquals(msg.getOptionalFixed32(), 1234);
- assertEquals(msg.getOptionalFixed64(), 0x1234567800000000);
- assertEquals(msg.getOptionalSfixed32(), -1234);
- assertEquals(msg.getOptionalSfixed64(), -0x1234567800000000);
- assertEquals(msg.getOptionalFloat(), 1.5);
- assertEquals(msg.getOptionalDouble(), -1.5);
- assertEquals(msg.getOptionalBool(), true);
- assertEquals(msg.getOptionalString(), 'hello world');
- assertEquals(true, bytesCompare(msg.getOptionalBytes(), BYTES));
- assertEquals(msg.getOptionalForeignMessage().getC(), 16);
- assertEquals(msg.getOptionalForeignEnum(),
- proto.jspb.test.Proto3Enum.PROTO3_BAR);
+ assertEquals(msg.getSingularInt32(), -42);
+ assertEquals(msg.getSingularInt64(), -0x7fffffff00000000);
+ assertEquals(msg.getSingularUint32(), 0x80000000);
+ assertEquals(msg.getSingularUint64(), 0xf000000000000000);
+ assertEquals(msg.getSingularSint32(), -100);
+ assertEquals(msg.getSingularSint64(), -0x8000000000000000);
+ assertEquals(msg.getSingularFixed32(), 1234);
+ assertEquals(msg.getSingularFixed64(), 0x1234567800000000);
+ assertEquals(msg.getSingularSfixed32(), -1234);
+ assertEquals(msg.getSingularSfixed64(), -0x1234567800000000);
+ assertEquals(msg.getSingularFloat(), 1.5);
+ assertEquals(msg.getSingularDouble(), -1.5);
+ assertEquals(msg.getSingularBool(), true);
+ assertEquals(msg.getSingularString(), 'hello world');
+ assertEquals(true, bytesCompare(msg.getSingularBytes(), BYTES));
+ assertEquals(msg.getSingularForeignMessage().getC(), 16);
+ assertEquals(
+ msg.getSingularForeignEnum(), proto.jspb.test.Proto3Enum.PROTO3_BAR);
assertElementsEquals(msg.getRepeatedInt32List(), [-42]);
assertElementsEquals(msg.getRepeatedInt64List(), [-0x7fffffff00000000]);
@@ -327,20 +393,20 @@ describe('proto3Test', function() {
// Set each primitive to a non-default value, then back to its default, to
// ensure that the serialization is actually checking the value and not just
// whether it has ever been set.
- msg.setOptionalInt32(42);
- msg.setOptionalInt32(0);
- msg.setOptionalDouble(3.14);
- msg.setOptionalDouble(0.0);
- msg.setOptionalBool(true);
- msg.setOptionalBool(false);
- msg.setOptionalString('hello world');
- msg.setOptionalString('');
- msg.setOptionalBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
- msg.setOptionalBytes('');
- msg.setOptionalForeignMessage(new proto.jspb.test.ForeignMessage());
- msg.setOptionalForeignMessage(null);
- msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
- msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_FOO);
+ msg.setSingularInt32(42);
+ msg.setSingularInt32(0);
+ msg.setSingularDouble(3.14);
+ msg.setSingularDouble(0.0);
+ msg.setSingularBool(true);
+ msg.setSingularBool(false);
+ msg.setSingularString('hello world');
+ msg.setSingularString('');
+ msg.setSingularBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
+ msg.setSingularBytes('');
+ msg.setSingularForeignMessage(new proto.jspb.test.ForeignMessage());
+ msg.setSingularForeignMessage(null);
+ msg.setSingularForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
+ msg.setSingularForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_FOO);
msg.setOneofUint32(32);
msg.clearOneofUint32();
@@ -355,27 +421,25 @@ describe('proto3Test', function() {
it('testBytesFieldsInterop', function() {
var msg = new proto.jspb.test.TestProto3();
// Set as a base64 string and check all the getters work.
- msg.setOptionalBytes(BYTES_B64);
- assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
- assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
- assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+ msg.setSingularBytes(BYTES_B64);
+ assertTrue(bytesCompare(msg.getSingularBytes_asU8(), BYTES));
+ assertTrue(bytesCompare(msg.getSingularBytes_asB64(), BYTES));
+ assertTrue(bytesCompare(msg.getSingularBytes(), BYTES));
// Test binary serialize round trip doesn't break it.
msg = proto.jspb.test.TestProto3.deserializeBinary(msg.serializeBinary());
- assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
- assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
- assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+ assertTrue(bytesCompare(msg.getSingularBytes_asU8(), BYTES));
+ assertTrue(bytesCompare(msg.getSingularBytes_asB64(), BYTES));
+ assertTrue(bytesCompare(msg.getSingularBytes(), BYTES));
msg = new proto.jspb.test.TestProto3();
// Set as a Uint8Array and check all the getters work.
- msg.setOptionalBytes(BYTES);
- assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
- assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
- assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
-
+ msg.setSingularBytes(BYTES);
+ assertTrue(bytesCompare(msg.getSingularBytes_asU8(), BYTES));
+ assertTrue(bytesCompare(msg.getSingularBytes_asB64(), BYTES));
+ assertTrue(bytesCompare(msg.getSingularBytes(), BYTES));
});
-
it('testTimestampWellKnownType', function() {
var msg = new proto.google.protobuf.Timestamp();
msg.fromDate(new Date(123456789));
diff --git a/js/proto3_test.proto b/js/proto3_test.proto
index f23e19c9d8..14f104ef56 100644
--- a/js/proto3_test.proto
+++ b/js/proto3_test.proto
@@ -30,29 +30,48 @@
syntax = "proto3";
-import "testbinary.proto";
-
package jspb.test;
+import "testbinary.proto";
+
message TestProto3 {
- int32 optional_int32 = 1;
- int64 optional_int64 = 2;
- uint32 optional_uint32 = 3;
- uint64 optional_uint64 = 4;
- sint32 optional_sint32 = 5;
- sint64 optional_sint64 = 6;
- fixed32 optional_fixed32 = 7;
- fixed64 optional_fixed64 = 8;
- sfixed32 optional_sfixed32 = 9;
- sfixed64 optional_sfixed64 = 10;
- float optional_float = 11;
- double optional_double = 12;
- bool optional_bool = 13;
- string optional_string = 14;
- bytes optional_bytes = 15;
+ int32 singular_int32 = 1;
+ int64 singular_int64 = 2;
+ uint32 singular_uint32 = 3;
+ uint64 singular_uint64 = 4;
+ sint32 singular_sint32 = 5;
+ sint64 singular_sint64 = 6;
+ fixed32 singular_fixed32 = 7;
+ fixed64 singular_fixed64 = 8;
+ sfixed32 singular_sfixed32 = 9;
+ sfixed64 singular_sfixed64 = 10;
+ float singular_float = 11;
+ double singular_double = 12;
+ bool singular_bool = 13;
+ string singular_string = 14;
+ bytes singular_bytes = 15;
- ForeignMessage optional_foreign_message = 19;
- Proto3Enum optional_foreign_enum = 22;
+ ForeignMessage singular_foreign_message = 19;
+ Proto3Enum singular_foreign_enum = 22;
+
+ optional int32 optional_int32 = 121;
+ optional int64 optional_int64 = 122;
+ optional uint32 optional_uint32 = 123;
+ optional uint64 optional_uint64 = 124;
+ optional sint32 optional_sint32 = 125;
+ optional sint64 optional_sint64 = 126;
+ optional fixed32 optional_fixed32 = 127;
+ optional fixed64 optional_fixed64 = 128;
+ optional sfixed32 optional_sfixed32 = 129;
+ optional sfixed64 optional_sfixed64 = 130;
+ optional float optional_float = 131;
+ optional double optional_double = 132;
+ optional bool optional_bool = 133;
+ optional string optional_string = 134;
+ optional bytes optional_bytes = 135;
+
+ optional ForeignMessage optional_foreign_message = 136;
+ optional Proto3Enum optional_foreign_enum = 137;
repeated int32 repeated_int32 = 31;
repeated int64 repeated_int64 = 32;
@@ -73,7 +92,6 @@ message TestProto3 {
repeated ForeignMessage repeated_foreign_message = 49;
repeated Proto3Enum repeated_foreign_enum = 52;
-
oneof oneof_field {
uint32 oneof_uint32 = 111;
ForeignMessage oneof_foreign_message = 112;
diff --git a/php/ext/google/protobuf2/arena.c b/php/ext/google/protobuf/arena.c
similarity index 100%
rename from php/ext/google/protobuf2/arena.c
rename to php/ext/google/protobuf/arena.c
diff --git a/php/ext/google/protobuf2/arena.h b/php/ext/google/protobuf/arena.h
similarity index 100%
rename from php/ext/google/protobuf2/arena.h
rename to php/ext/google/protobuf/arena.h
diff --git a/php/ext/google/protobuf/array.c b/php/ext/google/protobuf/array.c
index 5174f4a78b..571d3e41cd 100644
--- a/php/ext/google/protobuf/array.c
+++ b/php/ext/google/protobuf/array.c
@@ -28,389 +28,268 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include
+#include "array.h"
+
#include
#include
-#include "protobuf.h"
+#include
-ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
- ZEND_ARG_INFO(0, index)
-ZEND_END_ARG_INFO()
+// This is not self-contained: it must be after other Zend includes.
+#include
-ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2)
- ZEND_ARG_INFO(0, index)
- ZEND_ARG_INFO(0, newval)
-ZEND_END_ARG_INFO()
+#include "arena.h"
+#include "convert.h"
+#include "def.h"
+#include "php-upb.h"
+#include "protobuf.h"
-ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
-ZEND_END_ARG_INFO()
+static void RepeatedFieldIter_make(zval *val, zval *repeated_field);
-static zend_function_entry repeated_field_methods[] = {
- PHP_ME(RepeatedField, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(RepeatedField, append, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(RepeatedField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
- PHP_ME(RepeatedField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC)
- PHP_ME(RepeatedField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC)
- PHP_ME(RepeatedField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC)
- PHP_ME(RepeatedField, count, arginfo_void, ZEND_ACC_PUBLIC)
- PHP_ME(RepeatedField, getIterator, arginfo_void, ZEND_ACC_PUBLIC)
- ZEND_FE_END
-};
+// -----------------------------------------------------------------------------
+// RepeatedField
+// -----------------------------------------------------------------------------
-static zend_function_entry repeated_field_iter_methods[] = {
- PHP_ME(RepeatedFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC)
- PHP_ME(RepeatedFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC)
- PHP_ME(RepeatedFieldIter, key, arginfo_void, ZEND_ACC_PUBLIC)
- PHP_ME(RepeatedFieldIter, next, arginfo_void, ZEND_ACC_PUBLIC)
- PHP_ME(RepeatedFieldIter, valid, arginfo_void, ZEND_ACC_PUBLIC)
- ZEND_FE_END
-};
+typedef struct {
+ zend_object std;
+ zval arena;
+ upb_array *array;
+ upb_fieldtype_t type;
+ const Descriptor* desc; // When values are messages.
+} RepeatedField;
-// Forward declare static functions.
-
-static int repeated_field_array_init(zval *array, upb_fieldtype_t type,
- uint size ZEND_FILE_LINE_DC);
-static void repeated_field_write_dimension(zval *object, zval *offset,
- zval *value TSRMLS_DC);
-static HashTable *repeated_field_get_gc(zval *object, CACHED_VALUE **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
+zend_class_entry *RepeatedField_class_entry;
+static zend_object_handlers RepeatedField_object_handlers;
-// -----------------------------------------------------------------------------
-// RepeatedField creation/destruction
-// -----------------------------------------------------------------------------
+// PHP Object Handlers /////////////////////////////////////////////////////////
-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
-
-PHP_PROTO_OBJECT_EMPTY_DTOR_START(RepeatedField, repeated_field)
-PHP_PROTO_OBJECT_DTOR_END
-
-// 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)
-
-// 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);
+/**
+ * RepeatedField_create()
+ *
+ * PHP class entry function to allocate and initialize a new RepeatedField
+ * object.
+ */
+static zend_object* RepeatedField_create(zend_class_entry *class_type) {
+ RepeatedField *intern = emalloc(sizeof(RepeatedField));
+ zend_object_std_init(&intern->std, class_type);
+ intern->std.handlers = &RepeatedField_object_handlers;
+ Arena_Init(&intern->arena);
+ intern->array = NULL;
+ intern->desc = NULL;
+ // Skip object_properties_init(), we don't allow derived classes.
+ return &intern->std;
}
-static inline void php_proto_array_object_release(void *value) {
- zval_ptr_dtor(value);
-}
-static inline void php_proto_array_default_release(void *value) {
-}
-#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) {
- zval_ptr_dtor(value);
-}
-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);
-
- 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);
- break;
- default:
- zend_hash_init(Z_ARRVAL_P(array), size, NULL,
- php_proto_array_default_release, 0);
- }
- return SUCCESS;
+/**
+ * RepeatedField_dtor()
+ *
+ * Object handler to destroy a RepeatedField. This releases all resources
+ * associated with the message. Note that it is possible to access a destroyed
+ * object from PHP in rare cases.
+ */
+static void RepeatedField_destructor(zend_object* obj) {
+ RepeatedField* intern = (RepeatedField*)obj;
+ ObjCache_Delete(intern->array);
+ zval_ptr_dtor(&intern->arena);
+ zend_object_std_dtor(&intern->std);
}
-// -----------------------------------------------------------------------------
-// RepeatedField Handlers
-// -----------------------------------------------------------------------------
+static HashTable *RepeatedField_GetProperties(zval *object TSRMLS_DC) {
+ return NULL; // We do not have a properties table.
+}
-static void repeated_field_write_dimension(zval *object, zval *offset,
- zval *value TSRMLS_DC) {
- uint64_t index;
+static zval *RepeatedField_GetPropertyPtrPtr(zval *object, zval *member,
+ int type, void **cache_slot) {
+ return NULL; // We don't offer direct references to our properties.
+}
- RepeatedField *intern = UNBOX(RepeatedField, object);
- HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
- int size = native_slot_size(intern->type);
+// C Functions from array.h ////////////////////////////////////////////////////
- unsigned char memory[NATIVE_SLOT_MAX_SIZE];
- memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
+// These are documented in the header file.
- if (!native_slot_set_by_array(intern->type, intern->msg_ce, memory,
- value TSRMLS_CC)) {
+void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr,
+ const upb_fielddef *f, zval *arena) {
+ if (!arr) {
+ ZVAL_NULL(val);
return;
}
- if (!offset || Z_TYPE_P(offset) == IS_NULL) {
- index = zend_hash_num_elements(PHP_PROTO_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);
- return;
- }
- } else {
- return;
- }
+ if (!ObjCache_Get(arr, val)) {
+ RepeatedField *intern = emalloc(sizeof(RepeatedField));
+ zend_object_std_init(&intern->std, RepeatedField_class_entry);
+ intern->std.handlers = &RepeatedField_object_handlers;
+ ZVAL_COPY(&intern->arena, arena);
+ intern->array = arr;
+ intern->type = upb_fielddef_type(f);
+ intern->desc = Descriptor_GetFromFieldDef(f);
+ // Skip object_properties_init(), we don't allow derived classes.
+ ObjCache_Add(intern->array, &intern->std);
+ ZVAL_OBJ(val, &intern->std);
}
+}
- if (intern->type == UPB_TYPE_MESSAGE) {
- php_proto_zend_hash_index_update_zval(ht, index, *(zval**)memory);
- } else {
- php_proto_zend_hash_index_update_mem(ht, index, memory, size, NULL);
+upb_array *RepeatedField_GetUpbArray(zval *val, const upb_fielddef *f,
+ upb_arena *arena) {
+ if (Z_ISREF_P(val)) {
+ ZVAL_DEREF(val);
}
-}
-#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);
-}
+ if (Z_TYPE_P(val) == IS_ARRAY) {
+ // Auto-construct, eg. [1, 2, 3] -> upb_array([1, 2, 3]).
+ upb_array *arr = upb_array_new(arena, upb_fielddef_type(f));
+ HashTable *table = HASH_OF(val);
+ HashPosition pos;
+ upb_fieldtype_t type = upb_fielddef_type(f);
+ const Descriptor *desc = Descriptor_GetFromFieldDef(f);
-// -----------------------------------------------------------------------------
-// C RepeatedField Utilities
-// -----------------------------------------------------------------------------
+ zend_hash_internal_pointer_reset_ex(table, &pos);
+
+ while (true) {
+ zval *zv = zend_hash_get_current_data_ex(table, &pos);
+ upb_msgval val;
-void *repeated_field_index_native(RepeatedField *intern, int index TSRMLS_DC) {
- HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
- void *value;
+ if (!zv) return arr;
- if (intern->type == UPB_TYPE_MESSAGE) {
- if (php_proto_zend_hash_index_find_zval(ht, index, (void **)&value) ==
- FAILURE) {
- zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index);
- return NULL;
+ if (!Convert_PhpToUpbAutoWrap(zv, &val, type, desc, arena)) {
+ return NULL;
+ }
+
+ upb_array_append(arr, val, arena);
+ zend_hash_move_forward_ex(table, &pos);
}
- } else {
- if (php_proto_zend_hash_index_find_mem(ht, index, (void **)&value) ==
- FAILURE) {
- zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index);
- return NULL;
+ } else if (Z_TYPE_P(val) == IS_OBJECT &&
+ Z_OBJCE_P(val) == RepeatedField_class_entry) {
+ // Unwrap existing RepeatedField object to get the upb_array* inside.
+ RepeatedField *intern = (RepeatedField*)Z_OBJ_P(val);
+ const Descriptor *desc = Descriptor_GetFromFieldDef(f);
+
+ if (intern->type != upb_fielddef_type(f) || intern->desc != desc) {
+ php_error_docref(NULL, E_USER_ERROR,
+ "Wrong type for this repeated field.");
}
- }
-
- return value;
-}
-void repeated_field_push_native(RepeatedField *intern, void *value) {
- HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
- int size = native_slot_size(intern->type);
- if (intern->type == UPB_TYPE_MESSAGE) {
- php_proto_zend_hash_next_index_insert_zval(ht, value);
+ upb_arena_fuse(arena, Arena_Get(&intern->arena));
+ return intern->array;
} else {
- php_proto_zend_hash_next_index_insert_mem(ht, (void **)value, size, NULL);
+ php_error_docref(NULL, E_USER_ERROR, "Must be a repeated field");
+ return NULL;
}
}
-void repeated_field_ensure_created(
- const upb_fielddef *field,
- CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC) {
- if (ZVAL_IS_NULL(CACHED_PTR_TO_ZVAL_PTR(repeated_field))) {
- zval_ptr_dtor(repeated_field);
-#if PHP_MAJOR_VERSION < 7
- MAKE_STD_ZVAL(CACHED_PTR_TO_ZVAL_PTR(repeated_field));
-#endif
- repeated_field_create_with_field(repeated_field_type, field,
- repeated_field PHP_PROTO_TSRMLS_CC);
- }
-}
-
-void repeated_field_create_with_field(
- zend_class_entry *ce, const upb_fielddef *field,
- CACHED_VALUE *repeated_field PHP_PROTO_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);
-}
-
-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);
-
- RepeatedField *intern =
- UNBOX(RepeatedField, CACHED_TO_ZVAL_PTR(*repeated_field));
- 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
-}
-
-
-// -----------------------------------------------------------------------------
-// PHP RepeatedField Methods
-// -----------------------------------------------------------------------------
+// RepeatedField PHP methods ///////////////////////////////////////////////////
/**
+ * RepeatedField::__construct()
+ *
* Constructs an instance of RepeatedField.
* @param long Type of the stored element.
- * @param string Message/Enum class name (message/enum fields only).
+ * @param string Message/Enum class.
*/
PHP_METHOD(RepeatedField, __construct) {
- long type;
+ RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
+ upb_arena *arena = Arena_Get(&intern->arena);
+ zend_long type;
zend_class_entry* klass = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|C", &type, &klass) ==
- FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|C", &type, &klass) != SUCCESS) {
return;
}
- RepeatedField *intern = UNBOX(RepeatedField, getThis());
- 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
+ intern->type = pbphp_dtype_to_type(type);
+ intern->desc = Descriptor_GetFromClassEntry(klass);
if (intern->type == UPB_TYPE_MESSAGE && klass == NULL) {
- zend_error(E_USER_ERROR, "Message type must have concrete class.");
+ php_error_docref(NULL, E_USER_ERROR,
+ "Message/enum type must have concrete class.");
return;
}
- // TODO(teboring): Consider enum.
+ intern->array = upb_array_new(arena, intern->type);
+ ObjCache_Add(intern->array, &intern->std);
}
/**
+ * RepeatedField::append()
+ *
* Append element to the end of the repeated field.
* @param object The element to be added.
*/
PHP_METHOD(RepeatedField, append) {
- zval *value;
+ RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
+ upb_arena *arena = Arena_Get(&intern->arena);
+ zval *php_val;
+ upb_msgval msgval;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) ==
- FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &php_val) != SUCCESS ||
+ !Convert_PhpToUpb(php_val, &msgval, intern->type, intern->desc, arena)) {
return;
}
- repeated_field_write_dimension(getThis(), NULL, value TSRMLS_CC);
+
+ upb_array_append(intern->array, msgval, arena);
}
/**
- * Check whether the element at given index exists.
+ * RepeatedField::offsetExists()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ * isset($arr[$idx]);
+ * empty($arr[$idx]);
+ *
* @param long The index to be checked.
* @return bool True if the element at the given index exists.
*/
PHP_METHOD(RepeatedField, offsetExists) {
- long index;
+ RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
+ zend_long index;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
- FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
return;
}
- RepeatedField *intern = UNBOX(RepeatedField, getThis());
-
- RETURN_BOOL(index >= 0 &&
- index < zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array)));
+ RETURN_BOOL(index >= 0 && index < upb_array_size(intern->array));
}
/**
- * Return the element at the given index.
- * This will also be called for: $ele = $arr[0]
+ * RepeatedField::offsetGet()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ * $x = $arr[$idx];
+ *
* @param long The index of the element to be fetched.
* @return object The stored element at given index.
* @exception Invalid type for index.
* @exception Non-existing index.
*/
PHP_METHOD(RepeatedField, offsetGet) {
- long index;
- void *memory;
+ RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
+ zend_long index;
+ upb_msgval msgval;
+ zval ret;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
- FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
return;
}
- RepeatedField *intern = UNBOX(RepeatedField, getThis());
- HashTable *table = PHP_PROTO_HASH_OF(intern->array);
-
- if (intern->type == UPB_TYPE_MESSAGE) {
- if (php_proto_zend_hash_index_find_zval(table, index, (void **)&memory) ==
- FAILURE) {
- zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
- return;
- }
- } else {
- if (php_proto_zend_hash_index_find_mem(table, index, (void **)&memory) ==
- FAILURE) {
- zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
- return;
- }
+ if (index < 0 || index >= upb_array_size(intern->array)) {
+ 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);
+
+ msgval = upb_array_get(intern->array, index);
+ Convert_UpbToPhp(msgval, &ret, intern->type, intern->desc, &intern->arena);
+ RETURN_ZVAL(&ret, 0, 1);
}
/**
- * Assign the element at the given index.
- * This will also be called for: $arr []= $ele and $arr[0] = ele
+ * RepeatedField::offsetSet()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ * $arr[$idx] = $x;
+ * $arr []= $x; // Append
+ *
* @param long The index of the element to be assigned.
* @param object The element to be assigned.
* @exception Invalid type for index.
@@ -418,140 +297,306 @@ PHP_METHOD(RepeatedField, offsetGet) {
* @exception Incorrect type of the element.
*/
PHP_METHOD(RepeatedField, offsetSet) {
- zval *index, *value;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &index, &value) ==
- FAILURE) {
+ RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
+ upb_arena *arena = Arena_Get(&intern->arena);
+ size_t size = upb_array_size(intern->array);
+ zval *offset, *val;
+ int64_t index;
+ upb_msgval msgval;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &offset, &val) != SUCCESS) {
+ return;
+ }
+
+ if (Z_TYPE_P(offset) == IS_NULL) {
+ index = size;
+ } else if (!Convert_PhpToInt64(offset, &index)) {
return;
}
- repeated_field_write_dimension(getThis(), index, value TSRMLS_CC);
+
+ if (!Convert_PhpToUpb(val, &msgval, intern->type, intern->desc, arena)) {
+ return;
+ }
+
+ if (index > size) {
+ zend_error(E_USER_ERROR, "Element at index %ld doesn't exist.\n", index);
+ } else if (index == size) {
+ upb_array_append(intern->array, msgval, Arena_Get(&intern->arena));
+ } else {
+ upb_array_set(intern->array, index, msgval);
+ }
}
/**
- * Remove the element at the given index.
- * This will also be called for: unset($arr)
+ * RepeatedField::offsetUnset()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ * unset($arr[$idx]);
+ *
* @param long The index of the element to be removed.
* @exception Invalid type for index.
* @exception The element to be removed is not at the end of the RepeatedField.
*/
PHP_METHOD(RepeatedField, offsetUnset) {
- long index;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
- FAILURE) {
+ RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
+ zend_long index;
+ zend_long size = upb_array_size(intern->array);
+
+ // Only the element at the end of the array can be removed.
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) != SUCCESS) {
return;
}
- RepeatedField *intern = UNBOX(RepeatedField, getThis());
-
- // 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)) {
- zend_error(E_USER_ERROR, "Cannot remove element at %ld.\n", index);
+ if (size == 0 || index != size - 1) {
+ php_error_docref(NULL, E_USER_ERROR, "Cannot remove element at %ld.\n",
+ index);
return;
}
- zend_hash_index_del(PHP_PROTO_HASH_OF(intern->array), index);
+ upb_array_resize(intern->array, size - 1, Arena_Get(&intern->arena));
}
/**
+ * RepeatedField::count()
+ *
+ * Implements the Countable interface. Invoked when PHP code calls:
+ *
+ * $len = count($arr);
* Return the number of stored elements.
* This will also be called for: count($arr)
* @return long The number of stored elements.
*/
PHP_METHOD(RepeatedField, count) {
- RepeatedField *intern = UNBOX(RepeatedField, getThis());
+ RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
if (zend_parse_parameters_none() == FAILURE) {
return;
}
- RETURN_LONG(zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array)));
+ RETURN_LONG(upb_array_size(intern->array));
}
/**
- * Return the beginning iterator.
- * This will also be called for: foreach($arr)
+ * RepeatedField::getIterator()
+ *
+ * Implements the IteratorAggregate interface. Invoked when PHP code calls:
+ *
+ * foreach ($arr) {}
+ *
* @return object Beginning iterator.
*/
PHP_METHOD(RepeatedField, getIterator) {
- CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(return_value,
- repeated_field_iter_type);
-
- RepeatedField *intern = UNBOX(RepeatedField, getThis());
- RepeatedFieldIter *iter = UNBOX(RepeatedFieldIter, return_value);
- iter->repeated_field = intern;
- iter->position = 0;
+ zval ret;
+ RepeatedFieldIter_make(&ret, getThis());
+ RETURN_ZVAL(&ret, 0, 1);
}
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
+ ZEND_ARG_INFO(0, index)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, newval)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry repeated_field_methods[] = {
+ PHP_ME(RepeatedField, __construct, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedField, append, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedField, count, arginfo_void, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedField, getIterator, arginfo_void, ZEND_ACC_PUBLIC)
+ ZEND_FE_END
+};
+
// -----------------------------------------------------------------------------
-// RepeatedFieldIter creation/destruction
+// PHP RepeatedFieldIter
// -----------------------------------------------------------------------------
-// Define object free method.
-PHP_PROTO_OBJECT_EMPTY_FREE_START(RepeatedFieldIter, repeated_field_iter)
-PHP_PROTO_OBJECT_FREE_END
+typedef struct {
+ zend_object std;
+ zval repeated_field;
+ zend_long position;
+} RepeatedFieldIter;
-PHP_PROTO_OBJECT_EMPTY_DTOR_START(RepeatedFieldIter, repeated_field_iter)
-PHP_PROTO_OBJECT_DTOR_END
+zend_class_entry *RepeatedFieldIter_class_entry;
+static zend_object_handlers repeated_field_iter_object_handlers;
-// 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)
+/**
+ * RepeatedFieldIter_create()
+ *
+ * PHP class entry function to allocate and initialize a new RepeatedFieldIter
+ * object.
+ */
+zend_object* RepeatedFieldIter_create(zend_class_entry *class_type) {
+ RepeatedFieldIter *intern = emalloc(sizeof(RepeatedFieldIter));
+ zend_object_std_init(&intern->std, class_type);
+ intern->std.handlers = &repeated_field_iter_object_handlers;
+ ZVAL_NULL(&intern->repeated_field);
+ intern->position = 0;
+ // Skip object_properties_init(), we don't allow derived classes.
+ return &intern->std;
+}
-// 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
+/**
+ * RepeatedFieldIter_dtor()
+ *
+ * Object handler to destroy a RepeatedFieldIter. This releases all resources
+ * associated with the message. Note that it is possible to access a destroyed
+ * object from PHP in rare cases.
+ */
+static void RepeatedFieldIter_dtor(zend_object* obj) {
+ RepeatedFieldIter* intern = (RepeatedFieldIter*)obj;
+ zval_ptr_dtor(&intern->repeated_field);
+ zend_object_std_dtor(&intern->std);
+}
-// -----------------------------------------------------------------------------
-// PHP RepeatedFieldIter Methods
-// -----------------------------------------------------------------------------
+/**
+ * RepeatedFieldIter_make()
+ *
+ * C function to create a RepeatedFieldIter.
+ */
+static void RepeatedFieldIter_make(zval *val, zval *repeated_field) {
+ RepeatedFieldIter *iter;
+ ZVAL_OBJ(val, RepeatedFieldIter_class_entry->create_object(
+ RepeatedFieldIter_class_entry));
+ iter = (RepeatedFieldIter*)Z_OBJ_P(val);
+ ZVAL_COPY(&iter->repeated_field, repeated_field);
+}
+/*
+ * When a user writes:
+ *
+ * foreach($arr as $key => $val) {}
+ *
+ * PHP's iterator protocol is:
+ *
+ * $iter = $arr->getIterator();
+ * for ($iter->rewind(); $iter->valid(); $iter->next()) {
+ * $key = $iter->key();
+ * $val = $iter->current();
+ * }
+ */
+
+/**
+ * RepeatedFieldIter::rewind()
+ *
+ * Implements the Iterator interface. Sets the iterator to the first element.
+ */
PHP_METHOD(RepeatedFieldIter, rewind) {
- RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis());
+ RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
intern->position = 0;
}
+/**
+ * RepeatedFieldIter::current()
+ *
+ * Implements the Iterator interface. Returns the current value.
+ */
PHP_METHOD(RepeatedFieldIter, current) {
- RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis());
- RepeatedField *repeated_field = intern->repeated_field;
-
- long index = 0;
- void *memory;
+ RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
+ RepeatedField *field = (RepeatedField*)Z_OBJ_P(&intern->repeated_field);
+ upb_array *array = field->array;
+ zend_long index = intern->position;
+ upb_msgval msgval;
+ zval ret;
+
+ if (index < 0 || index >= upb_array_size(array)) {
+ zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
+ }
- HashTable *table = PHP_PROTO_HASH_OF(repeated_field->array);
+ msgval = upb_array_get(array, index);
- if (repeated_field->type == UPB_TYPE_MESSAGE) {
- if (php_proto_zend_hash_index_find_zval(table, intern->position,
- (void **)&memory) == FAILURE) {
- zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
- return;
- }
- } else {
- if (php_proto_zend_hash_index_find_mem(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);
+ Convert_UpbToPhp(msgval, &ret, field->type, field->desc, &field->arena);
+ RETURN_ZVAL(&ret, 0, 1);
}
+/**
+ * RepeatedFieldIter::key()
+ *
+ * Implements the Iterator interface. Returns the current key.
+ */
PHP_METHOD(RepeatedFieldIter, key) {
- RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis());
+ RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
RETURN_LONG(intern->position);
}
+/**
+ * RepeatedFieldIter::next()
+ *
+ * Implements the Iterator interface. Advances to the next element.
+ */
PHP_METHOD(RepeatedFieldIter, next) {
- RepeatedFieldIter *intern = UNBOX(RepeatedFieldIter, getThis());
+ RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
++intern->position;
}
+/**
+ * RepeatedFieldIter::valid()
+ *
+ * Implements the Iterator interface. Returns true if this is a valid element.
+ */
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 = (RepeatedFieldIter*)Z_OBJ_P(getThis());
+ RepeatedField *field = (RepeatedField*)Z_OBJ_P(&intern->repeated_field);
+ RETURN_BOOL(intern->position < upb_array_size(field->array));
+}
+
+static zend_function_entry repeated_field_iter_methods[] = {
+ PHP_ME(RepeatedFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedFieldIter, key, arginfo_void, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedFieldIter, next, arginfo_void, ZEND_ACC_PUBLIC)
+ PHP_ME(RepeatedFieldIter, valid, arginfo_void, ZEND_ACC_PUBLIC)
+ ZEND_FE_END
+};
+
+// -----------------------------------------------------------------------------
+// Module init.
+// -----------------------------------------------------------------------------
+
+/**
+ * Array_ModuleInit()
+ *
+ * Called when the C extension is loaded to register all types.
+ */
+void Array_ModuleInit() {
+ zend_class_entry tmp_ce;
+ zend_object_handlers *h;
+
+ // RepeatedField.
+ INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\RepeatedField",
+ repeated_field_methods);
+
+ RepeatedField_class_entry = zend_register_internal_class(&tmp_ce);
+ zend_class_implements(RepeatedField_class_entry, 3, spl_ce_ArrayAccess,
+ zend_ce_aggregate, spl_ce_Countable);
+ RepeatedField_class_entry->ce_flags |= ZEND_ACC_FINAL;
+ RepeatedField_class_entry->create_object = RepeatedField_create;
+
+ h = &RepeatedField_object_handlers;
+ memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+ h->dtor_obj = RepeatedField_destructor;
+ h->get_properties = RepeatedField_GetProperties;
+ h->get_property_ptr_ptr = RepeatedField_GetPropertyPtrPtr;
+
+ // RepeatedFieldIter
+ INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\RepeatedFieldIter",
+ repeated_field_iter_methods);
+
+ RepeatedFieldIter_class_entry = zend_register_internal_class(&tmp_ce);
+ zend_class_implements(RepeatedFieldIter_class_entry, 1, zend_ce_iterator);
+ RepeatedFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL;
+ RepeatedFieldIter_class_entry->create_object = RepeatedFieldIter_create;
+
+ h = &repeated_field_iter_object_handlers;
+ memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+ h->dtor_obj = RepeatedFieldIter_dtor;
}
diff --git a/php/ext/google/protobuf2/array.h b/php/ext/google/protobuf/array.h
similarity index 100%
rename from php/ext/google/protobuf2/array.h
rename to php/ext/google/protobuf/array.h
diff --git a/php/ext/google/protobuf/builtin_descriptors.inc b/php/ext/google/protobuf/builtin_descriptors.inc
deleted file mode 100644
index 1bb5dbfa85..0000000000
--- a/php/ext/google/protobuf/builtin_descriptors.inc
+++ /dev/null
@@ -1,635 +0,0 @@
-unsigned char descriptor_proto[] = {
- 0x0a, 0x9b, 0x3b, 0x0a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73,
- 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x4d, 0x0a, 0x11, 0x46, 0x69,
- 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
- 0x53, 0x65, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18,
- 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
- 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
- 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
- 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x04, 0x66, 0x69, 0x6c,
- 0x65, 0x22, 0xe4, 0x04, 0x0a, 0x13, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
- 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a,
- 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12,
- 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63,
- 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70,
- 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x70,
- 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64,
- 0x65, 0x6e, 0x63, 0x79, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x05, 0x52, 0x10,
- 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64,
- 0x65, 0x6e, 0x63, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x65, 0x61, 0x6b,
- 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18,
- 0x0b, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0e, 0x77, 0x65, 0x61, 0x6b, 0x44,
- 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x43, 0x0a,
- 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70,
- 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f,
- 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
- 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
- 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61,
- 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e,
- 0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
- 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72,
- 0x6f, 0x74, 0x6f, 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70,
- 0x65, 0x12, 0x41, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
- 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x6f,
- 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
- 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52,
- 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x09,
- 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69,
- 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
- 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65,
- 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
- 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
- 0x73, 0x12, 0x49, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
- 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x09, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f,
- 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f,
- 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65,
- 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6e, 0x74,
- 0x61, 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x79,
- 0x6e, 0x74, 0x61, 0x78, 0x22, 0xb9, 0x06, 0x0a, 0x0f, 0x44, 0x65, 0x73,
- 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
- 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x05,
- 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44,
- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f,
- 0x74, 0x6f, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x43, 0x0a,
- 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
- 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
- 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74,
- 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x6e, 0x65,
- 0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
- 0x6f, 0x52, 0x0a, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70,
- 0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x79,
- 0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67,
- 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
- 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x08,
- 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x58, 0x0a, 0x0f,
- 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61,
- 0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e,
- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
- 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x78, 0x74, 0x65,
- 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0e,
- 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e,
- 0x67, 0x65, 0x12, 0x44, 0x0a, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f,
- 0x64, 0x65, 0x63, 0x6c, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25,
- 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
- 0x6f, 0x52, 0x09, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x63, 0x6c,
- 0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
- 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
- 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
- 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
- 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12,
- 0x55, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f,
- 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65,
- 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52,
- 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e,
- 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
- 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28,
- 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e,
- 0x61, 0x6d, 0x65, 0x1a, 0x7a, 0x0a, 0x0e, 0x45, 0x78, 0x74, 0x65, 0x6e,
- 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a,
- 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
- 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65,
- 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e,
- 0x64, 0x12, 0x40, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f,
- 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
- 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61,
- 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07,
- 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x37, 0x0a, 0x0d, 0x52,
- 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65,
- 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
- 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
- 0x03, 0x65, 0x6e, 0x64, 0x22, 0x7c, 0x0a, 0x15, 0x45, 0x78, 0x74, 0x65,
- 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70,
- 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69,
- 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74,
- 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69,
- 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70,
- 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a,
- 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x98,
- 0x06, 0x0a, 0x14, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12,
- 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e,
- 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
- 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x05, 0x6c,
- 0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b,
- 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
- 0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x61, 0x62,
- 0x65, 0x6c, 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05,
- 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
- 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
- 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x79, 0x70, 0x65,
- 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79,
- 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
- 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e,
- 0x64, 0x65, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75,
- 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56,
- 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x6e, 0x65, 0x6f,
- 0x66, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x09, 0x20, 0x01, 0x28,
- 0x05, 0x52, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x49, 0x6e, 0x64, 0x65,
- 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x6e, 0x61,
- 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6a, 0x73,
- 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70,
- 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69,
- 0x6f, 0x6e, 0x73, 0x22, 0xb6, 0x02, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65,
- 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55,
- 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50,
- 0x45, 0x5f, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a,
- 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10,
- 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49,
- 0x4e, 0x54, 0x36, 0x34, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59,
- 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x05, 0x12, 0x10,
- 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44,
- 0x36, 0x34, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45,
- 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x07, 0x12, 0x0d,
- 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10,
- 0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54,
- 0x52, 0x49, 0x4e, 0x47, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59,
- 0x50, 0x45, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x0a, 0x12, 0x10,
- 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41,
- 0x47, 0x45, 0x10, 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45,
- 0x5f, 0x42, 0x59, 0x54, 0x45, 0x53, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b,
- 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10,
- 0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e,
- 0x55, 0x4d, 0x10, 0x0e, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45,
- 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x0f, 0x12,
- 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58,
- 0x45, 0x44, 0x36, 0x34, 0x10, 0x10, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59,
- 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x11, 0x12,
- 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54,
- 0x36, 0x34, 0x10, 0x12, 0x22, 0x43, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65,
- 0x6c, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4f,
- 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x12, 0x0a,
- 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49,
- 0x52, 0x45, 0x44, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42,
- 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10,
- 0x03, 0x22, 0x63, 0x0a, 0x14, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
- 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a,
- 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65,
- 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe3, 0x02, 0x0a, 0x13, 0x45,
- 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
- 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
- 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
- 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
- 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73,
- 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
- 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x6f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69,
- 0x6f, 0x6e, 0x73, 0x12, 0x5d, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72,
- 0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e,
- 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
- 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65,
- 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52,
- 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e,
- 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
- 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28,
- 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e,
- 0x61, 0x6d, 0x65, 0x1a, 0x3b, 0x0a, 0x11, 0x45, 0x6e, 0x75, 0x6d, 0x52,
- 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65,
- 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
- 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
- 0x03, 0x65, 0x6e, 0x64, 0x22, 0x83, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x75,
- 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d,
- 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e,
- 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x07, 0x6f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21,
- 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c,
- 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x16, 0x53,
- 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x6d, 0x65, 0x74,
- 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e,
- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
- 0x6f, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x39, 0x0a,
- 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72,
- 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
- 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x89, 0x02, 0x0a,
- 0x15, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12,
- 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e,
- 0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70,
- 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f,
- 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
- 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x38,
- 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65,
- 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
- 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x10,
- 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61,
- 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
- 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
- 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x30,
- 0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72,
- 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08,
- 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x73, 0x65, 0x72,
- 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67,
- 0x22, 0x92, 0x09, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x61, 0x76, 0x61,
- 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x0b, 0x6a, 0x61, 0x76, 0x61, 0x50, 0x61, 0x63, 0x6b,
- 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x6a, 0x61, 0x76, 0x61, 0x5f,
- 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e,
- 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6a,
- 0x61, 0x76, 0x61, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73,
- 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x6a, 0x61, 0x76,
- 0x61, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x66,
- 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
- 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x6a, 0x61, 0x76, 0x61, 0x4d,
- 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73,
- 0x12, 0x44, 0x0a, 0x1d, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e,
- 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73,
- 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x14, 0x20,
- 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x19, 0x6a, 0x61, 0x76,
- 0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x71, 0x75,
- 0x61, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3a,
- 0x0a, 0x16, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e,
- 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x74, 0x66, 0x38,
- 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73,
- 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x53, 0x74, 0x72, 0x69, 0x6e,
- 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x74, 0x66, 0x38, 0x12, 0x53,
- 0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x5f, 0x66,
- 0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x67,
- 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
- 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
- 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d,
- 0x6f, 0x64, 0x65, 0x3a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x52, 0x0b,
- 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x46, 0x6f, 0x72, 0x12,
- 0x1d, 0x0a, 0x0a, 0x67, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
- 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x6f, 0x50,
- 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x63, 0x63,
- 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72,
- 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a,
- 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x63, 0x63, 0x47, 0x65,
- 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
- 0x73, 0x12, 0x39, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65,
- 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
- 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
- 0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e,
- 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
- 0x12, 0x35, 0x0a, 0x13, 0x70, 0x79, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72,
- 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18,
- 0x12, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65,
- 0x52, 0x11, 0x70, 0x79, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53,
- 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x14, 0x70,
- 0x68, 0x70, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73,
- 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x2a, 0x20, 0x01, 0x28,
- 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x12, 0x70, 0x68,
- 0x70, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76,
- 0x69, 0x63, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72,
- 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08,
- 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70,
- 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2f, 0x0a, 0x10, 0x63,
- 0x63, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x72, 0x65,
- 0x6e, 0x61, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66,
- 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0e, 0x63, 0x63, 0x45, 0x6e, 0x61, 0x62,
- 0x6c, 0x65, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x12, 0x2a, 0x0a, 0x11,
- 0x6f, 0x62, 0x6a, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x70,
- 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x0f, 0x6f, 0x62, 0x6a, 0x63, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72,
- 0x65, 0x66, 0x69, 0x78, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x73, 0x68, 0x61,
- 0x72, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
- 0x18, 0x25, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x73, 0x68, 0x61,
- 0x72, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
- 0x21, 0x0a, 0x0c, 0x73, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x70, 0x72, 0x65,
- 0x66, 0x69, 0x78, 0x18, 0x27, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73,
- 0x77, 0x69, 0x66, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x28,
- 0x0a, 0x10, 0x70, 0x68, 0x70, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f,
- 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0e, 0x70, 0x68, 0x70, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72,
- 0x65, 0x66, 0x69, 0x78, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x68, 0x70, 0x5f,
- 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x29, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x68, 0x70, 0x4e, 0x61, 0x6d, 0x65,
- 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x70, 0x68, 0x70,
- 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6e, 0x61,
- 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x2c, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x14, 0x70, 0x68, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
- 0x74, 0x61, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
- 0x21, 0x0a, 0x0c, 0x72, 0x75, 0x62, 0x79, 0x5f, 0x70, 0x61, 0x63, 0x6b,
- 0x61, 0x67, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72,
- 0x75, 0x62, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x58,
- 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
- 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7,
- 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
- 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
- 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
- 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69,
- 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
- 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0c, 0x4f, 0x70, 0x74, 0x69,
- 0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05,
- 0x53, 0x50, 0x45, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43,
- 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x02, 0x12, 0x10,
- 0x0a, 0x0c, 0x4c, 0x49, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49,
- 0x4d, 0x45, 0x10, 0x03, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80,
- 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x26, 0x10, 0x27, 0x22, 0xd1, 0x02,
- 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73,
- 0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x77, 0x69, 0x72, 0x65,
- 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x14, 0x6d, 0x65,
- 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x57, 0x69, 0x72, 0x65,
- 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x4c, 0x0a, 0x1f, 0x6e, 0x6f,
- 0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x5f, 0x64, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x63,
- 0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a,
- 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x1c, 0x6e, 0x6f, 0x53, 0x74,
- 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72,
- 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74,
- 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
- 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61,
- 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, 0x65,
- 0x6e, 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
- 0x6d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x58, 0x0a, 0x14,
- 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
- 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e,
- 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74,
- 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69,
- 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80,
- 0x02, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10,
- 0x0a, 0x22, 0xe2, 0x03, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x63, 0x74,
- 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e,
- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x06,
- 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x52, 0x05, 0x63, 0x74, 0x79, 0x70,
- 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65,
- 0x64, 0x12, 0x47, 0x0a, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x18,
- 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
- 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
- 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
- 0x2e, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x09, 0x4a, 0x53, 0x5f,
- 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x52, 0x06, 0x6a, 0x73, 0x74, 0x79,
- 0x70, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x05,
- 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
- 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70,
- 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65,
- 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x04,
- 0x77, 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
- 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x12,
- 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72,
- 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18,
- 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f,
- 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
- 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
- 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e,
- 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79,
- 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47,
- 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, 0x52, 0x44, 0x10, 0x01,
- 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50,
- 0x49, 0x45, 0x43, 0x45, 0x10, 0x02, 0x22, 0x35, 0x0a, 0x06, 0x4a, 0x53,
- 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e,
- 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4a,
- 0x53, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d,
- 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10,
- 0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02,
- 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x73, 0x0a, 0x0c, 0x4f, 0x6e,
- 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58,
- 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
- 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7,
- 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
- 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
- 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
- 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69,
- 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
- 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80,
- 0x80, 0x80, 0x02, 0x22, 0xc0, 0x01, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d,
- 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61,
- 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41,
- 0x6c, 0x69, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72,
- 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
- 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70,
- 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75,
- 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64,
- 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69,
- 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
- 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65,
- 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
- 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02,
- 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x9e, 0x01, 0x0a, 0x10, 0x45,
- 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69,
- 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65,
- 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a,
- 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72,
- 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e,
- 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f,
- 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e,
- 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
- 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
- 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22,
- 0x9c, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65,
- 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01,
- 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64,
- 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a,
- 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
- 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55,
- 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64,
- 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e,
- 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80,
- 0x80, 0x02, 0x22, 0xe0, 0x02, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, 0x6f,
- 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a,
- 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21,
- 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
- 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12,
- 0x71, 0x0a, 0x11, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e,
- 0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x22, 0x20, 0x01,
- 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74,
- 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49,
- 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65,
- 0x76, 0x65, 0x6c, 0x3a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54,
- 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e,
- 0x52, 0x10, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63,
- 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e,
- 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f,
- 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e,
- 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
- 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
- 0x22, 0x50, 0x0a, 0x10, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65,
- 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x17, 0x0a, 0x13,
- 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f,
- 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a,
- 0x0f, 0x4e, 0x4f, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x45, 0x46, 0x46,
- 0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x44,
- 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x2a, 0x09,
- 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9a, 0x03,
- 0x0a, 0x13, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
- 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65,
- 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
- 0x6e, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x52, 0x04,
- 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e,
- 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x64, 0x65, 0x6e,
- 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
- 0x2c, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f,
- 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20,
- 0x01, 0x28, 0x04, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76,
- 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a,
- 0x12, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e,
- 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x10, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49,
- 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64,
- 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
- 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c,
- 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74,
- 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07,
- 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
- 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67,
- 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
- 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x67, 0x67, 0x72,
- 0x65, 0x67, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x4a,
- 0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x1b,
- 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x18,
- 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x50,
- 0x61, 0x72, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x65, 0x78,
- 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28,
- 0x08, 0x52, 0x0b, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
- 0x6f, 0x6e, 0x22, 0xa7, 0x02, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a,
- 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f,
- 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f,
- 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c,
- 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xce, 0x01, 0x0a, 0x08,
- 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04,
- 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02,
- 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x04,
- 0x73, 0x70, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02,
- 0x10, 0x01, 0x52, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x12, 0x29, 0x0a, 0x10,
- 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d,
- 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f,
- 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65,
- 0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x69, 0x6c,
- 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
- 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x72, 0x61, 0x69,
- 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
- 0x12, 0x3a, 0x0a, 0x19, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f,
- 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d,
- 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52,
- 0x17, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x74, 0x61,
- 0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
- 0x22, 0xd1, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
- 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4d,
- 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f,
- 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
- 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f,
- 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x6d, 0x0a, 0x0a, 0x41, 0x6e, 0x6e,
- 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70,
- 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10,
- 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
- 0x46, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x65, 0x67, 0x69,
- 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x62, 0x65, 0x67,
- 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20,
- 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x42, 0x8f, 0x01, 0x0a,
- 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, 0x10, 0x44, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x48, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
- 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x64,
- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x3b, 0x64, 0x65,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0xf8, 0x01, 0x01, 0xa2,
- 0x02, 0x03, 0x47, 0x50, 0x42, 0xaa, 0x02, 0x1a, 0x47, 0x6f, 0x6f, 0x67,
- 0x6c, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
- 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e
-};
-unsigned int descriptor_proto_len = 7582;
diff --git a/php/ext/google/protobuf2/bundled_php.h b/php/ext/google/protobuf/bundled_php.h
similarity index 100%
rename from php/ext/google/protobuf2/bundled_php.h
rename to php/ext/google/protobuf/bundled_php.h
diff --git a/php/ext/google/protobuf/config.m4 b/php/ext/google/protobuf/config.m4
index ab032e466b..3fdcb00480 100644
--- a/php/ext/google/protobuf/config.m4
+++ b/php/ext/google/protobuf/config.m4
@@ -4,7 +4,7 @@ if test "$PHP_PROTOBUF" != "no"; then
PHP_NEW_EXTENSION(
protobuf,
- array.c def.c encode_decode.c map.c message.c protobuf.c storage.c type_check.c upb.c utf8.c,
+ arena.c array.c bundled_php.c convert.c def.c map.c message.c names.c php-upb.c protobuf.c,
$ext_shared)
fi
diff --git a/php/ext/google/protobuf2/convert.c b/php/ext/google/protobuf/convert.c
similarity index 100%
rename from php/ext/google/protobuf2/convert.c
rename to php/ext/google/protobuf/convert.c
diff --git a/php/ext/google/protobuf2/convert.h b/php/ext/google/protobuf/convert.h
similarity index 100%
rename from php/ext/google/protobuf2/convert.h
rename to php/ext/google/protobuf/convert.h
diff --git a/php/ext/google/protobuf/def.c b/php/ext/google/protobuf/def.c
index 5edcb03516..c76134d86b 100644
--- a/php/ext/google/protobuf/def.c
+++ b/php/ext/google/protobuf/def.c
@@ -28,326 +28,332 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include "def.h"
+
#include
+
+// This is not self-contained: it must be after other Zend includes.
#include
+#include "names.h"
+#include "php-upb.h"
#include "protobuf.h"
-#include "builtin_descriptors.inc"
-
-// Forward declare.
-static void descriptor_init_c_instance(Descriptor* intern TSRMLS_DC);
-static void descriptor_free_c(Descriptor* object TSRMLS_DC);
-
-static void field_descriptor_init_c_instance(FieldDescriptor* intern TSRMLS_DC);
-static void field_descriptor_free_c(FieldDescriptor* object 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_value_descriptor_init_c_instance(
- EnumValueDescriptor *intern TSRMLS_DC);
-static void enum_value_descriptor_free_c(EnumValueDescriptor *object TSRMLS_DC);
+static void CheckUpbStatus(const upb_status* status, const char* msg) {
+ if (!upb_ok(status)) {
+ zend_error(E_ERROR, "%s: %s\n", msg, upb_status_errmsg(status));
+ }
+}
-static void descriptor_pool_free_c(DescriptorPool* object TSRMLS_DC);
-static void descriptor_pool_init_c_instance(DescriptorPool* pool TSRMLS_DC);
+static void FieldDescriptor_FromFieldDef(zval *val, const upb_fielddef *f);
-static void internal_descriptor_pool_free_c(
- InternalDescriptorPool *object TSRMLS_DC);
-static void internal_descriptor_pool_init_c_instance(
- InternalDescriptorPool *pool TSRMLS_DC);
+// We use this for objects that should not be created directly from PHP.
+static zend_object *CreateHandler_ReturnNull(zend_class_entry *class_type) {
+ return NULL; // Nobody should call this.
+}
-static void oneof_descriptor_free_c(Oneof* object TSRMLS_DC);
-static void oneof_descriptor_init_c_instance(Oneof* pool TSRMLS_DC);
// -----------------------------------------------------------------------------
-// Common Utilities
+// EnumValueDescriptor
// -----------------------------------------------------------------------------
-static void check_upb_status(const upb_status* status, const char* msg) {
- if (!upb_ok(status)) {
- zend_error(E_ERROR, "%s: %s\n", msg, upb_status_errmsg(status));
- }
+typedef struct {
+ zend_object std;
+ const char *name;
+ int32_t number;
+} EnumValueDescriptor;
+
+zend_class_entry *EnumValueDescriptor_class_entry;
+static zend_object_handlers EnumValueDescriptor_object_handlers;
+
+/*
+ * EnumValueDescriptor_Make()
+ *
+ * Function to create an EnumValueDescriptor object from C.
+ */
+static void EnumValueDescriptor_Make(zval *val, const char *name,
+ int32_t number) {
+ EnumValueDescriptor *intern = emalloc(sizeof(EnumValueDescriptor));
+ zend_object_std_init(&intern->std, EnumValueDescriptor_class_entry);
+ intern->std.handlers = &EnumValueDescriptor_object_handlers;
+ intern->name = name;
+ intern->number = number;
+ // Skip object_properties_init(), we don't allow derived classes.
+ ZVAL_OBJ(val, &intern->std);
}
-// -----------------------------------------------------------------------------
-// GPBType
-// -----------------------------------------------------------------------------
+/*
+ * EnumValueDescriptor::getName()
+ *
+ * Returns the name for this enum value.
+ */
+PHP_METHOD(EnumValueDescriptor, getName) {
+ EnumValueDescriptor *intern = (EnumValueDescriptor*)Z_OBJ_P(getThis());
+ RETURN_STRING(intern->name);
+}
-zend_class_entry* gpb_type_type;
+/*
+ * EnumValueDescriptor::getNumber()
+ *
+ * Returns the number for this enum value.
+ */
+PHP_METHOD(EnumValueDescriptor, getNumber) {
+ EnumValueDescriptor *intern = (EnumValueDescriptor*)Z_OBJ_P(getThis());
+ RETURN_LONG(intern->number);
+}
-static zend_function_entry gpb_type_methods[] = {
+static zend_function_entry EnumValueDescriptor_methods[] = {
+ PHP_ME(EnumValueDescriptor, getName, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(EnumValueDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
-void gpb_type_init(TSRMLS_D) {
- zend_class_entry class_type;
- INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBType",
- gpb_type_methods);
- gpb_type_type = zend_register_internal_class(&class_type TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("DOUBLE"), 1 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("FLOAT"), 2 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("INT64"), 3 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("UINT64"), 4 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("INT32"), 5 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("FIXED64"), 6 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("FIXED32"), 7 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("BOOL"), 8 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("STRING"), 9 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("GROUP"), 10 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("MESSAGE"), 11 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("BYTES"), 12 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("UINT32"), 13 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("ENUM"), 14 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("SFIXED32"),
- 15 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("SFIXED64"),
- 16 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("SINT32"), 17 TSRMLS_CC);
- zend_declare_class_constant_long(gpb_type_type, STR("SINT64"), 18 TSRMLS_CC);
-}
-
// -----------------------------------------------------------------------------
-// Descriptor
+// EnumDescriptor
// -----------------------------------------------------------------------------
-static zend_function_entry descriptor_methods[] = {
- PHP_ME(Descriptor, getClass, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Descriptor, getFullName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Descriptor, getField, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Descriptor, getFieldCount, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Descriptor, getOneofDecl, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Descriptor, getOneofDeclCount, NULL, ZEND_ACC_PUBLIC)
- ZEND_FE_END
-};
+typedef struct {
+ zend_object std;
+ const upb_enumdef *enumdef;
+} EnumDescriptor;
-DEFINE_CLASS(Descriptor, descriptor, "Google\\Protobuf\\Descriptor");
+zend_class_entry *EnumDescriptor_class_entry;
+static zend_object_handlers EnumDescriptor_object_handlers;
-static void descriptor_free_c(Descriptor *self TSRMLS_DC) {
-}
+void EnumDescriptor_FromClassEntry(zval *val, zend_class_entry *ce) {
+ // To differentiate enums from classes, we pointer-tag the class entry.
+ void* key = (void*)((uintptr_t)ce | 1);
+ PBPHP_ASSERT(key != ce);
-static void descriptor_init_c_instance(Descriptor *desc TSRMLS_DC) {
- desc->intern = NULL;
-}
+ if (ce == NULL) {
+ ZVAL_NULL(val);
+ return;
+ }
-PHP_METHOD(Descriptor, getClass) {
- Descriptor* desc = UNBOX(Descriptor, getThis());
- DescriptorInternal* intern = desc->intern;
- register_class(intern, false TSRMLS_CC);
-#if PHP_MAJOR_VERSION < 7
- const char* classname = intern->klass->name;
-#else
- const char* classname = ZSTR_VAL(intern->klass->name);
-#endif
- PHP_PROTO_RETVAL_STRINGL(classname, strlen(classname), 1);
-}
+ if (!ObjCache_Get(key, val)) {
+ const upb_enumdef *e = NameMap_GetEnum(ce);
+ if (!e) {
+ ZVAL_NULL(val);
+ return;
+ }
+ EnumDescriptor* ret = emalloc(sizeof(EnumDescriptor));
+ zend_object_std_init(&ret->std, EnumDescriptor_class_entry);
+ ret->std.handlers = &EnumDescriptor_object_handlers;
+ ret->enumdef = e;
+ ObjCache_Add(key, &ret->std);
-PHP_METHOD(Descriptor, getFullName) {
- Descriptor* desc = UNBOX(Descriptor, getThis());
- DescriptorInternal* intern = desc->intern;
- const char* fullname = upb_msgdef_fullname(intern->msgdef);
- PHP_PROTO_RETVAL_STRINGL(fullname, strlen(fullname), 1);
-}
+ // Prevent this from ever being collected (within a request).
+ GC_ADDREF(&ret->std);
-PHP_METHOD(Descriptor, getField) {
- long index;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
- FAILURE) {
- zend_error(E_USER_ERROR, "Expect integer for index.\n");
- return;
+ ZVAL_OBJ(val, &ret->std);
}
+}
- Descriptor* desc = UNBOX(Descriptor, getThis());
- DescriptorInternal* intern = desc->intern;
- int field_num = upb_msgdef_numfields(intern->msgdef);
- if (index < 0 || index >= field_num) {
- zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
- return;
- }
+void EnumDescriptor_FromEnumDef(zval *val, const upb_enumdef *m) {
+ if (!m) {
+ ZVAL_NULL(val);
+ } else {
+ char *classname =
+ GetPhpClassname(upb_enumdef_file(m), upb_enumdef_fullname(m));
+ zend_string *str = zend_string_init(classname, strlen(classname), 0);
+ zend_class_entry *ce = zend_lookup_class(str); // May autoload the class.
- upb_msg_field_iter iter;
- int i;
- for(upb_msg_field_begin(&iter, intern->msgdef), i = 0;
- !upb_msg_field_done(&iter) && i < index;
- upb_msg_field_next(&iter), i++);
- const upb_fielddef *field = upb_msg_iter_field(&iter);
+ zend_string_release (str);
- PHP_PROTO_HASHTABLE_VALUE field_hashtable_value = get_def_obj(field);
- if (field_hashtable_value == NULL) {
-#if PHP_MAJOR_VERSION < 7
- MAKE_STD_ZVAL(field_hashtable_value);
- ZVAL_OBJ(field_hashtable_value, field_descriptor_type->create_object(
- field_descriptor_type TSRMLS_CC));
- Z_DELREF_P(field_hashtable_value);
-#else
- field_hashtable_value =
- field_descriptor_type->create_object(field_descriptor_type TSRMLS_CC);
- GC_DELREF(field_hashtable_value);
-#endif
- FieldDescriptor *field_php =
- UNBOX_HASHTABLE_VALUE(FieldDescriptor, field_hashtable_value);
- field_php->fielddef = field;
- add_def_obj(field, field_hashtable_value);
- }
+ if (!ce) {
+ zend_error(E_ERROR, "Couldn't load generated class %s", classname);
+ }
-#if PHP_MAJOR_VERSION < 7
- RETURN_ZVAL(field_hashtable_value, 1, 0);
-#else
- GC_ADDREF(field_hashtable_value);
- RETURN_OBJ(field_hashtable_value);
-#endif
+ free(classname);
+ EnumDescriptor_FromClassEntry(val, ce);
+ }
}
-PHP_METHOD(Descriptor, getFieldCount) {
- Descriptor* desc = UNBOX(Descriptor, getThis());
- DescriptorInternal* intern = desc->intern;
- RETURN_LONG(upb_msgdef_numfields(intern->msgdef));
-}
+/*
+ * EnumDescriptor::getValue()
+ *
+ * Returns an EnumValueDescriptor for this index. Note: we are not looking
+ * up by numeric enum value, but by the index in the list of enum values.
+ */
+PHP_METHOD(EnumDescriptor, getValue) {
+ EnumDescriptor *intern = (EnumDescriptor*)Z_OBJ_P(getThis());
+ zend_long index;
+ zval ret;
-PHP_METHOD(Descriptor, getOneofDecl) {
- long index;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
FAILURE) {
zend_error(E_USER_ERROR, "Expect integer for index.\n");
return;
}
- Descriptor* desc = UNBOX(Descriptor, getThis());
- DescriptorInternal* intern = desc->intern;
- int field_num = upb_msgdef_numoneofs(intern->msgdef);
+ int field_num = upb_enumdef_numvals(intern->enumdef);
if (index < 0 || index >= field_num) {
zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
return;
}
- upb_msg_oneof_iter iter;
+ upb_enum_iter iter;
int i;
- for(upb_msg_oneof_begin(&iter, intern->msgdef), i = 0;
- !upb_msg_oneof_done(&iter) && i < index;
- upb_msg_oneof_next(&iter), i++);
- const upb_oneofdef *oneof = upb_msg_iter_oneof(&iter);
+ for(upb_enum_begin(&iter, intern->enumdef), i = 0;
+ !upb_enum_done(&iter) && i < index;
+ upb_enum_next(&iter), i++);
- ZVAL_OBJ(return_value, oneof_descriptor_type->create_object(
- oneof_descriptor_type TSRMLS_CC));
- Oneof *oneof_php = UNBOX(Oneof, return_value);
- oneof_php->oneofdef = oneof;
+ EnumValueDescriptor_Make(&ret, upb_enum_iter_name(&iter),
+ upb_enum_iter_number(&iter));
+ RETURN_ZVAL(&ret, 0, 1);
}
-PHP_METHOD(Descriptor, getOneofDeclCount) {
- Descriptor* desc = UNBOX(Descriptor, getThis());
- DescriptorInternal* intern = desc->intern;
- RETURN_LONG(upb_msgdef_numoneofs(intern->msgdef));
+/*
+ * EnumDescriptor::getValueCount()
+ *
+ * Returns the number of values in this enum.
+ */
+PHP_METHOD(EnumDescriptor, getValueCount) {
+ EnumDescriptor *intern = (EnumDescriptor*)Z_OBJ_P(getThis());
+ RETURN_LONG(upb_enumdef_numvals(intern->enumdef));
}
-// -----------------------------------------------------------------------------
-// EnumDescriptor
-// -----------------------------------------------------------------------------
+/*
+ * EnumDescriptor::getPublicDescriptor()
+ *
+ * Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not
+ * have two separate EnumDescriptor classes. We use a single class for both
+ * the public and private descriptor.
+ */
+PHP_METHOD(EnumDescriptor, getPublicDescriptor) {
+ RETURN_ZVAL(getThis(), 1, 0);
+}
-static zend_function_entry enum_descriptor_methods[] = {
- PHP_ME(EnumDescriptor, getValue, NULL, ZEND_ACC_PUBLIC)
+static zend_function_entry EnumDescriptor_methods[] = {
+ PHP_ME(EnumDescriptor, getPublicDescriptor, NULL, ZEND_ACC_PUBLIC)
PHP_ME(EnumDescriptor, getValueCount, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(EnumDescriptor, getValue, NULL, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
-DEFINE_CLASS(EnumDescriptor, enum_descriptor,
- "Google\\Protobuf\\EnumDescriptor");
+// -----------------------------------------------------------------------------
+// Oneof
+// -----------------------------------------------------------------------------
+
+typedef struct {
+ zend_object std;
+ const upb_oneofdef *oneofdef;
+} OneofDescriptor;
+
+zend_class_entry *OneofDescriptor_class_entry;
+static zend_object_handlers OneofDescriptor_object_handlers;
+
+static void OneofDescriptor_FromOneofDef(zval *val, const upb_oneofdef *o) {
+ if (o == NULL) {
+ ZVAL_NULL(val);
+ return;
+ }
+
+ if (!ObjCache_Get(o, val)) {
+ OneofDescriptor* ret = emalloc(sizeof(OneofDescriptor));
+ zend_object_std_init(&ret->std, OneofDescriptor_class_entry);
+ ret->std.handlers = &OneofDescriptor_object_handlers;
+ ret->oneofdef = o;
+ ObjCache_Add(o, &ret->std);
+
+ // Prevent this from ever being collected (within a request).
+ GC_ADDREF(&ret->std);
-static void enum_descriptor_free_c(EnumDescriptor *self TSRMLS_DC) {
+ ZVAL_OBJ(val, &ret->std);
+ }
}
-static void enum_descriptor_init_c_instance(EnumDescriptor *self TSRMLS_DC) {
- self->intern = NULL;
+/*
+ * OneofDescriptor::getName()
+ *
+ * Returns the name of this oneof.
+ */
+PHP_METHOD(OneofDescriptor, getName) {
+ OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis());
+ RETURN_STRING(upb_oneofdef_name(intern->oneofdef));
}
-PHP_METHOD(EnumDescriptor, getValue) {
- long index;
+/*
+ * OneofDescriptor::getField()
+ *
+ * Returns a field from this oneof. The given index must be in the range
+ * [0, getFieldCount() - 1].
+ */
+PHP_METHOD(OneofDescriptor, getField) {
+ OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis());
+ zend_long index;
+ zval ret;
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
FAILURE) {
zend_error(E_USER_ERROR, "Expect integer for index.\n");
return;
}
- EnumDescriptor *desc = UNBOX(EnumDescriptor, getThis());
- EnumDescriptorInternal *intern = desc->intern;
- int field_num = upb_enumdef_numvals(intern->enumdef);
+ int field_num = upb_oneofdef_numfields(intern->oneofdef);
if (index < 0 || index >= field_num) {
zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
return;
}
- upb_enum_iter iter;
+ upb_oneof_iter iter;
int i;
- for(upb_enum_begin(&iter, intern->enumdef), i = 0;
- !upb_enum_done(&iter) && i < index;
- upb_enum_next(&iter), i++);
+ for(upb_oneof_begin(&iter, intern->oneofdef), i = 0;
+ !upb_oneof_done(&iter) && i < index;
+ upb_oneof_next(&iter), i++);
+ const upb_fielddef *field = upb_oneof_iter_field(&iter);
- ZVAL_OBJ(return_value, enum_value_descriptor_type->create_object(
- enum_value_descriptor_type TSRMLS_CC));
- EnumValueDescriptor *enum_value_php =
- UNBOX(EnumValueDescriptor, return_value);
- enum_value_php->name = upb_enum_iter_name(&iter);
- enum_value_php->number = upb_enum_iter_number(&iter);
+ FieldDescriptor_FromFieldDef(&ret, field);
+ RETURN_ZVAL(&ret, 1, 0);
}
-PHP_METHOD(EnumDescriptor, getValueCount) {
- EnumDescriptor *desc = UNBOX(EnumDescriptor, getThis());
- EnumDescriptorInternal *intern = desc->intern;
- RETURN_LONG(upb_enumdef_numvals(intern->enumdef));
+/*
+ * OneofDescriptor::getFieldCount()
+ *
+ * Returns the number of fields in this oneof.
+ */
+PHP_METHOD(OneofDescriptor, getFieldCount) {
+ OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis());
+ RETURN_LONG(upb_oneofdef_numfields(intern->oneofdef));
}
-// -----------------------------------------------------------------------------
-// EnumValueDescriptor
-// -----------------------------------------------------------------------------
-
-static zend_function_entry enum_value_descriptor_methods[] = {
- PHP_ME(EnumValueDescriptor, getName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(EnumValueDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC)
+static zend_function_entry OneofDescriptor_methods[] = {
+ PHP_ME(OneofDescriptor, getName, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(OneofDescriptor, getField, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(OneofDescriptor, getFieldCount, NULL, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
-DEFINE_CLASS(EnumValueDescriptor, enum_value_descriptor,
- "Google\\Protobuf\\EnumValueDescriptor");
-
-static void enum_value_descriptor_free_c(EnumValueDescriptor *self TSRMLS_DC) {
-}
-
-static void enum_value_descriptor_init_c_instance(EnumValueDescriptor *self TSRMLS_DC) {
- self->name = NULL;
- self->number = 0;
-}
-
-PHP_METHOD(EnumValueDescriptor, getName) {
- EnumValueDescriptor *intern = UNBOX(EnumValueDescriptor, getThis());
- PHP_PROTO_RETVAL_STRINGL(intern->name, strlen(intern->name), 1);
-}
-
-PHP_METHOD(EnumValueDescriptor, getNumber) {
- EnumValueDescriptor *intern = UNBOX(EnumValueDescriptor, getThis());
- RETURN_LONG(intern->number);
-}
-
// -----------------------------------------------------------------------------
// FieldDescriptor
// -----------------------------------------------------------------------------
-static zend_function_entry field_descriptor_methods[] = {
- PHP_ME(FieldDescriptor, getName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(FieldDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(FieldDescriptor, getLabel, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(FieldDescriptor, getType, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(FieldDescriptor, isMap, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(FieldDescriptor, getEnumType, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(FieldDescriptor, getMessageType, NULL, ZEND_ACC_PUBLIC)
- ZEND_FE_END
-};
+typedef struct {
+ zend_object std;
+ const upb_fielddef *fielddef;
+} FieldDescriptor;
-DEFINE_CLASS(FieldDescriptor, field_descriptor,
- "Google\\Protobuf\\FieldDescriptor");
+zend_class_entry *FieldDescriptor_class_entry;
+static zend_object_handlers FieldDescriptor_object_handlers;
-static void field_descriptor_free_c(FieldDescriptor *self TSRMLS_DC) {
-}
+static void FieldDescriptor_FromFieldDef(zval *val, const upb_fielddef *f) {
+ if (f == NULL) {
+ ZVAL_NULL(val);
+ return;
+ }
-static void field_descriptor_init_c_instance(FieldDescriptor *self TSRMLS_DC) {
- self->fielddef = NULL;
+ if (!ObjCache_Get(f, val)) {
+ FieldDescriptor* ret = emalloc(sizeof(FieldDescriptor));
+ zend_object_std_init(&ret->std, FieldDescriptor_class_entry);
+ ret->std.handlers = &FieldDescriptor_object_handlers;
+ ret->fielddef = f;
+ ObjCache_Add(f, &ret->std);
+
+ // Prevent this from ever being collected (within a request).
+ GC_ADDREF(&ret->std);
+
+ ZVAL_OBJ(val, &ret->std);
+ }
}
upb_fieldtype_t to_fieldtype(upb_descriptortype_t type) {
@@ -383,499 +389,496 @@ upb_fieldtype_t to_fieldtype(upb_descriptortype_t type) {
return 0;
}
+/*
+ * FieldDescriptor::getName()
+ *
+ * Returns the name of this field.
+ */
PHP_METHOD(FieldDescriptor, getName) {
- FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
- const char* name = upb_fielddef_name(intern->fielddef);
- PHP_PROTO_RETVAL_STRINGL(name, strlen(name), 1);
+ FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
+ RETURN_STRING(upb_fielddef_name(intern->fielddef));
}
+/*
+ * FieldDescriptor::getNumber()
+ *
+ * Returns the number of this field.
+ */
PHP_METHOD(FieldDescriptor, getNumber) {
- FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+ FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
RETURN_LONG(upb_fielddef_number(intern->fielddef));
}
+/*
+ * FieldDescriptor::getLabel()
+ *
+ * Returns the label of this field as an integer.
+ */
PHP_METHOD(FieldDescriptor, getLabel) {
- FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+ FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
RETURN_LONG(upb_fielddef_label(intern->fielddef));
}
+/*
+ * FieldDescriptor::getType()
+ *
+ * Returns the type of this field as an integer.
+ */
PHP_METHOD(FieldDescriptor, getType) {
- FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+ FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
RETURN_LONG(upb_fielddef_descriptortype(intern->fielddef));
}
+/*
+ * FieldDescriptor::isMap()
+ *
+ * Returns true if this field is a map.
+ */
PHP_METHOD(FieldDescriptor, isMap) {
- FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+ FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
RETURN_BOOL(upb_fielddef_ismap(intern->fielddef));
}
+/*
+ * FieldDescriptor::getEnumType()
+ *
+ * Returns the EnumDescriptor for this field, which must be an enum.
+ */
PHP_METHOD(FieldDescriptor, getEnumType) {
- FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
- if (upb_fielddef_type(intern->fielddef) != UPB_TYPE_ENUM) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
+ FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
+ const upb_enumdef *e = upb_fielddef_enumsubdef(intern->fielddef);
+ zval ret;
+
+ if (!e) {
+ zend_throw_exception_ex(NULL, 0,
"Cannot get enum type for non-enum field '%s'",
upb_fielddef_name(intern->fielddef));
return;
}
- const upb_enumdef *enumdef = upb_fielddef_enumsubdef(intern->fielddef);
- PHP_PROTO_HASHTABLE_VALUE desc_php = get_def_obj(enumdef);
-
- if (desc_php == NULL) {
- EnumDescriptorInternal* intern = get_enumdef_enumdesc(enumdef);
-
-#if PHP_MAJOR_VERSION < 7
- MAKE_STD_ZVAL(desc_php);
- ZVAL_OBJ(desc_php, enum_descriptor_type->create_object(
- enum_descriptor_type TSRMLS_CC));
- Z_DELREF_P(desc_php);
-#else
- desc_php =
- enum_descriptor_type->create_object(enum_descriptor_type TSRMLS_CC);
- GC_DELREF(desc_php);
-#endif
- EnumDescriptor* desc = UNBOX_HASHTABLE_VALUE(EnumDescriptor, desc_php);
- desc->intern = intern;
- add_def_obj(enumdef, desc_php);
- add_ce_obj(intern->klass, desc_php);
- }
-#if PHP_MAJOR_VERSION < 7
- RETURN_ZVAL(desc_php, 1, 0);
-#else
- GC_ADDREF(desc_php);
- RETURN_OBJ(desc_php);
-#endif
+ EnumDescriptor_FromEnumDef(&ret, e);
+ RETURN_ZVAL(&ret, 1, 0);
}
+/*
+ * FieldDescriptor::getMessageType()
+ *
+ * Returns the Descriptor for this field, which must be a message.
+ */
PHP_METHOD(FieldDescriptor, getMessageType) {
- FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
- if (upb_fielddef_type(intern->fielddef) != UPB_TYPE_MESSAGE) {
+ FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
+ Descriptor* desc = Descriptor_GetFromFieldDef(intern->fielddef);
+ zval ret;
+
+ if (!desc) {
zend_throw_exception_ex(
- NULL, 0 TSRMLS_CC, "Cannot get message type for non-message field '%s'",
+ NULL, 0, "Cannot get message type for non-message field '%s'",
upb_fielddef_name(intern->fielddef));
return;
}
- const upb_msgdef *msgdef = upb_fielddef_msgsubdef(intern->fielddef);
- PHP_PROTO_HASHTABLE_VALUE desc_php = get_def_obj(msgdef);
-
- if (desc_php == NULL) {
- DescriptorInternal* intern = get_msgdef_desc(msgdef);
-
-#if PHP_MAJOR_VERSION < 7
- MAKE_STD_ZVAL(desc_php);
- ZVAL_OBJ(desc_php, descriptor_type->create_object(
- descriptor_type TSRMLS_CC));
- Z_DELREF_P(desc_php);
-#else
- desc_php =
- descriptor_type->create_object(descriptor_type TSRMLS_CC);
- GC_DELREF(desc_php);
-#endif
- Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php);
- desc->intern = intern;
- add_def_obj(msgdef, desc_php);
- add_ce_obj(intern->klass, desc_php);
- }
-#if PHP_MAJOR_VERSION < 7
- RETURN_ZVAL(desc_php, 1, 0);
-#else
- GC_ADDREF(desc_php);
- RETURN_OBJ(desc_php);
-#endif
+ ZVAL_OBJ(&ret, &desc->std);
+ RETURN_ZVAL(&ret, 1, 0);
}
+static zend_function_entry FieldDescriptor_methods[] = {
+ PHP_ME(FieldDescriptor, getName, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(FieldDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(FieldDescriptor, getLabel, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(FieldDescriptor, getType, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(FieldDescriptor, isMap, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(FieldDescriptor, getEnumType, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(FieldDescriptor, getMessageType, NULL, ZEND_ACC_PUBLIC)
+ ZEND_FE_END
+};
+
// -----------------------------------------------------------------------------
-// Oneof
+// Descriptor
// -----------------------------------------------------------------------------
-static zend_function_entry oneof_descriptor_methods[] = {
- PHP_ME(Oneof, getName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Oneof, getField, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Oneof, getFieldCount, NULL, ZEND_ACC_PUBLIC)
- ZEND_FE_END
-};
+zend_class_entry *Descriptor_class_entry;
+static zend_object_handlers Descriptor_object_handlers;
-DEFINE_CLASS(Oneof, oneof_descriptor,
- "Google\\Protobuf\\OneofDescriptor");
+static void Descriptor_destructor(zend_object* obj) {
+ // We don't really need to do anything here, we don't allow this to be
+ // collected before the end of the request.
+}
+
+// C Functions from def.h //////////////////////////////////////////////////////
-static void oneof_descriptor_free_c(Oneof *self TSRMLS_DC) {
+// These are documented in the header file.
+
+void Descriptor_FromClassEntry(zval *val, zend_class_entry *ce) {
+ if (ce == NULL) {
+ ZVAL_NULL(val);
+ return;
+ }
+
+ if (!ObjCache_Get(ce, val)) {
+ const upb_msgdef *msgdef = NameMap_GetMessage(ce);
+ if (!msgdef) {
+ ZVAL_NULL(val);
+ return;
+ }
+ Descriptor* ret = emalloc(sizeof(Descriptor));
+ zend_object_std_init(&ret->std, Descriptor_class_entry);
+ ret->std.handlers = &Descriptor_object_handlers;
+ ret->class_entry = ce;
+ ret->msgdef = msgdef;
+ ObjCache_Add(ce, &ret->std);
+
+ // Prevent this from ever being collected (within a request).
+ GC_ADDREF(&ret->std);
+
+ ZVAL_OBJ(val, &ret->std);
+ }
}
-static void oneof_descriptor_init_c_instance(Oneof *self TSRMLS_DC) {
- self->oneofdef = NULL;
+Descriptor* Descriptor_GetFromClassEntry(zend_class_entry *ce) {
+ zval desc;
+ Descriptor_FromClassEntry(&desc, ce);
+ if (Z_TYPE_P(&desc) == IS_NULL) {
+ return NULL;
+ } else {
+ return (Descriptor*)Z_OBJ_P(&desc);
+ }
+}
+
+Descriptor* Descriptor_GetFromMessageDef(const upb_msgdef *m) {
+ if (m) {
+ if (upb_msgdef_mapentry(m)) {
+ // A bit of a hack, since map entries don't have classes.
+ Descriptor* ret = emalloc(sizeof(Descriptor));
+ zend_object_std_init(&ret->std, Descriptor_class_entry);
+ ret->std.handlers = &Descriptor_object_handlers;
+ ret->class_entry = NULL;
+ ret->msgdef = m;
+
+ // Prevent this from ever being collected (within a request).
+ GC_ADDREF(&ret->std);
+
+ return ret;
+ }
+
+ char *classname =
+ GetPhpClassname(upb_msgdef_file(m), upb_msgdef_fullname(m));
+ zend_string *str = zend_string_init(classname, strlen(classname), 0);
+ zend_class_entry *ce = zend_lookup_class(str); // May autoload the class.
+
+ zend_string_release (str);
+
+ if (!ce) {
+ zend_error(E_ERROR, "Couldn't load generated class %s", classname);
+ }
+
+ free(classname);
+ return Descriptor_GetFromClassEntry(ce);
+ } else {
+ return NULL;
+ }
}
-PHP_METHOD(Oneof, getName) {
- Oneof *intern = UNBOX(Oneof, getThis());
- const char *name = upb_oneofdef_name(intern->oneofdef);
- PHP_PROTO_RETVAL_STRINGL(name, strlen(name), 1);
+Descriptor* Descriptor_GetFromFieldDef(const upb_fielddef *f) {
+ return Descriptor_GetFromMessageDef(upb_fielddef_msgsubdef(f));
}
-PHP_METHOD(Oneof, getField) {
- long index;
+/*
+ * Descriptor::getPublicDescriptor()
+ *
+ * Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not
+ * have two separate EnumDescriptor classes. We use a single class for both
+ * the public and private descriptor.
+ */
+PHP_METHOD(Descriptor, getPublicDescriptor) {
+ RETURN_ZVAL(getThis(), 1, 0);
+}
+
+/*
+ * Descriptor::getFullName()
+ *
+ * Returns the full name for this message type.
+ */
+PHP_METHOD(Descriptor, getFullName) {
+ Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
+ RETURN_STRING(upb_msgdef_fullname(intern->msgdef));
+}
+
+/*
+ * Descriptor::getField()
+ *
+ * Returns a FieldDescriptor for the given index, which must be in the range
+ * [0, getFieldCount()-1].
+ */
+PHP_METHOD(Descriptor, getField) {
+ Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
+ int count = upb_msgdef_numfields(intern->msgdef);
+ zval ret;
+ zend_long index;
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
FAILURE) {
zend_error(E_USER_ERROR, "Expect integer for index.\n");
return;
}
- Oneof *intern = UNBOX(Oneof, getThis());
- int field_num = upb_oneofdef_numfields(intern->oneofdef);
- if (index < 0 || index >= field_num) {
+ if (index < 0 || index >= count) {
zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
return;
}
- upb_oneof_iter iter;
+ upb_msg_field_iter iter;
int i;
- for(upb_oneof_begin(&iter, intern->oneofdef), i = 0;
- !upb_oneof_done(&iter) && i < index;
- upb_oneof_next(&iter), i++);
- const upb_fielddef *field = upb_oneof_iter_field(&iter);
-
- PHP_PROTO_HASHTABLE_VALUE field_hashtable_value = get_def_obj(field);
- if (field_hashtable_value == NULL) {
-#if PHP_MAJOR_VERSION < 7
- MAKE_STD_ZVAL(field_hashtable_value);
- ZVAL_OBJ(field_hashtable_value, field_descriptor_type->create_object(
- field_descriptor_type TSRMLS_CC));
-#else
- field_hashtable_value =
- field_descriptor_type->create_object(field_descriptor_type TSRMLS_CC);
-#endif
- FieldDescriptor *field_php =
- UNBOX_HASHTABLE_VALUE(FieldDescriptor, field_hashtable_value);
- field_php->fielddef = field;
- add_def_obj(field, field_hashtable_value);
- }
+ for(upb_msg_field_begin(&iter, intern->msgdef), i = 0;
+ !upb_msg_field_done(&iter) && i < index;
+ upb_msg_field_next(&iter), i++);
+ const upb_fielddef *field = upb_msg_iter_field(&iter);
-#if PHP_MAJOR_VERSION < 7
- RETURN_ZVAL(field_hashtable_value, 1, 0);
-#else
- GC_ADDREF(field_hashtable_value);
- RETURN_OBJ(field_hashtable_value);
-#endif
+ FieldDescriptor_FromFieldDef(&ret, field);
+ RETURN_ZVAL(&ret, 1, 0);
}
-PHP_METHOD(Oneof, getFieldCount) {
- Oneof *intern = UNBOX(Oneof, getThis());
- RETURN_LONG(upb_oneofdef_numfields(intern->oneofdef));
+/*
+ * Descriptor::getFieldCount()
+ *
+ * Returns the number of fields in this message.
+ */
+PHP_METHOD(Descriptor, getFieldCount) {
+ Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
+ RETURN_LONG(upb_msgdef_numfields(intern->msgdef));
}
-// -----------------------------------------------------------------------------
-// DescriptorPool
-// -----------------------------------------------------------------------------
-
-static zend_function_entry descriptor_pool_methods[] = {
- PHP_ME(DescriptorPool, getGeneratedPool, NULL,
- ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(DescriptorPool, getDescriptorByClassName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(DescriptorPool, getEnumDescriptorByClassName, NULL, ZEND_ACC_PUBLIC)
- ZEND_FE_END
-};
+/*
+ * Descriptor::getOneofDecl()
+ *
+ * Returns a OneofDescriptor for the given index, which must be in the range
+ * [0, getOneofDeclCount()].
+ */
+PHP_METHOD(Descriptor, getOneofDecl) {
+ Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
+ zend_long index;
+ zval ret;
-static zend_function_entry internal_descriptor_pool_methods[] = {
- PHP_ME(InternalDescriptorPool, getGeneratedPool, NULL,
- ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(InternalDescriptorPool, internalAddGeneratedFile, NULL, ZEND_ACC_PUBLIC)
- ZEND_FE_END
-};
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
+ FAILURE) {
+ zend_error(E_USER_ERROR, "Expect integer for index.\n");
+ return;
+ }
-DEFINE_CLASS(DescriptorPool, descriptor_pool,
- "Google\\Protobuf\\DescriptorPool");
-DEFINE_CLASS(InternalDescriptorPool, internal_descriptor_pool,
- "Google\\Protobuf\\Internal\\DescriptorPool");
-
-// wrapper of generated pool
-#if PHP_MAJOR_VERSION < 7
-zval* generated_pool_php;
-zval* internal_generated_pool_php;
-#else
-zend_object *generated_pool_php;
-zend_object *internal_generated_pool_php;
-#endif
-InternalDescriptorPoolImpl *generated_pool;
-InternalDescriptorPoolImpl generated_pool_impl; // The actual generated pool
-
-void init_generated_pool_once(TSRMLS_D) {
- if (generated_pool == NULL) {
-#if PHP_MAJOR_VERSION < 7
- MAKE_STD_ZVAL(generated_pool_php);
- MAKE_STD_ZVAL(internal_generated_pool_php);
- ZVAL_OBJ(internal_generated_pool_php,
- internal_descriptor_pool_type->create_object(
- internal_descriptor_pool_type TSRMLS_CC));
- ZVAL_OBJ(generated_pool_php, descriptor_pool_type->create_object(
- descriptor_pool_type TSRMLS_CC));
-#else
- internal_generated_pool_php = internal_descriptor_pool_type->create_object(
- internal_descriptor_pool_type TSRMLS_CC);
- generated_pool_php =
- descriptor_pool_type->create_object(descriptor_pool_type TSRMLS_CC);
-#endif
- generated_pool = &generated_pool_impl;
+ int field_num = upb_msgdef_numoneofs(intern->msgdef);
+ if (index < 0 || index >= field_num) {
+ zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
+ return;
}
-}
-static void internal_descriptor_pool_init_c_instance(
- InternalDescriptorPool *pool TSRMLS_DC) {
- pool->intern = &generated_pool_impl;
-}
+ upb_msg_oneof_iter iter;
+ int i;
+ for(upb_msg_oneof_begin(&iter, intern->msgdef), i = 0;
+ !upb_msg_oneof_done(&iter) && i < index;
+ upb_msg_oneof_next(&iter), i++);
+ const upb_oneofdef *oneof = upb_msg_iter_oneof(&iter);
-static void internal_descriptor_pool_free_c(
- InternalDescriptorPool *pool TSRMLS_DC) {
+ OneofDescriptor_FromOneofDef(&ret, oneof);
+ RETURN_ZVAL(&ret, 1, 0);
}
-void internal_descriptor_pool_impl_init(
- InternalDescriptorPoolImpl *pool TSRMLS_DC) {
- pool->symtab = upb_symtab_new();
- pool->fill_handler_cache =
- upb_handlercache_new(add_handlers_for_message, NULL);
- pool->pb_serialize_handler_cache = upb_pb_encoder_newcache();
- pool->json_serialize_handler_cache = upb_json_printer_newcache(false);
- pool->json_serialize_handler_preserve_cache = upb_json_printer_newcache(true);
- pool->fill_method_cache = upb_pbcodecache_new(pool->fill_handler_cache);
- pool->json_fill_method_cache = upb_json_codecache_new();
+/*
+ * Descriptor::getOneofDeclCount()
+ *
+ * Returns the number of oneofs in this message.
+ */
+PHP_METHOD(Descriptor, getOneofDeclCount) {
+ Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
+ RETURN_LONG(upb_msgdef_numoneofs(intern->msgdef));
}
-void internal_descriptor_pool_impl_destroy(
- InternalDescriptorPoolImpl *pool TSRMLS_DC) {
- upb_symtab_free(pool->symtab);
- upb_handlercache_free(pool->fill_handler_cache);
- upb_handlercache_free(pool->pb_serialize_handler_cache);
- upb_handlercache_free(pool->json_serialize_handler_cache);
- upb_handlercache_free(pool->json_serialize_handler_preserve_cache);
- upb_pbcodecache_free(pool->fill_method_cache);
- upb_json_codecache_free(pool->json_fill_method_cache);
+/*
+ * Descriptor::getClass()
+ *
+ * Returns the name of the PHP class for this message.
+ */
+PHP_METHOD(Descriptor, getClass) {
+ Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
+ const char* classname = ZSTR_VAL(intern->class_entry->name);
+ RETURN_STRING(classname);
}
-static void descriptor_pool_init_c_instance(DescriptorPool *pool TSRMLS_DC) {
- assert(generated_pool != NULL);
- pool->intern = generated_pool;
-}
-static void descriptor_pool_free_c(DescriptorPool *pool TSRMLS_DC) {
-}
+static zend_function_entry Descriptor_methods[] = {
+ PHP_ME(Descriptor, getClass, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Descriptor, getFullName, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Descriptor, getField, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Descriptor, getFieldCount, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Descriptor, getOneofDecl, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Descriptor, getOneofDeclCount, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Descriptor, getPublicDescriptor, NULL, ZEND_ACC_PUBLIC)
+ ZEND_FE_END
+};
-PHP_METHOD(DescriptorPool, getGeneratedPool) {
- init_generated_pool_once(TSRMLS_C);
-#if PHP_MAJOR_VERSION < 7
- RETURN_ZVAL(generated_pool_php, 1, 0);
-#else
- GC_ADDREF(generated_pool_php);
- RETURN_OBJ(generated_pool_php);
-#endif
+// -----------------------------------------------------------------------------
+// DescriptorPool
+// -----------------------------------------------------------------------------
+
+typedef struct DescriptorPool {
+ zend_object std;
+ upb_symtab *symtab;
+} DescriptorPool;
+
+zend_class_entry *DescriptorPool_class_entry;
+static zend_object_handlers DescriptorPool_object_handlers;
+
+static DescriptorPool *GetPool(const zval* this_ptr) {
+ return (DescriptorPool*)Z_OBJ_P(this_ptr);
}
-PHP_METHOD(InternalDescriptorPool, getGeneratedPool) {
- init_generated_pool_once(TSRMLS_C);
-#if PHP_MAJOR_VERSION < 7
- RETURN_ZVAL(internal_generated_pool_php, 1, 0);
-#else
- GC_ADDREF(internal_generated_pool_php);
- RETURN_OBJ(internal_generated_pool_php);
-#endif
+/**
+ * Object handler to create an DescriptorPool.
+ */
+static zend_object* DescriptorPool_create(zend_class_entry *class_type) {
+ DescriptorPool *intern = emalloc(sizeof(DescriptorPool));
+ zend_object_std_init(&intern->std, class_type);
+ intern->std.handlers = &DescriptorPool_object_handlers;
+ intern->symtab = upb_symtab_new();
+ // Skip object_properties_init(), we don't allow derived classes.
+ return &intern->std;
}
-static bool is_reserved(const char *segment, int length) {
- bool result;
- char* lower = ALLOC_N(char, length + 1);
- memset(lower, 0, length + 1);
- memcpy(lower, segment, length);
- int i = 0;
- while(lower[i]) {
- lower[i] = (char)tolower(lower[i]);
- i++;
+/**
+ * Object handler to free an DescriptorPool.
+ */
+static void DescriptorPool_destructor(zend_object* obj) {
+ DescriptorPool* intern = (DescriptorPool*)obj;
+ if (intern->symtab) {
+ upb_symtab_free(intern->symtab);
}
- lower[length] = 0;
- result = is_reserved_name(lower);
- FREE(lower);
- return result;
+ intern->symtab = NULL;
+ zend_object_std_dtor(&intern->std);
}
-static void fill_prefix(const char *segment, int length,
- const char *prefix_given,
- const char *package_name,
- stringsink *classname) {
- if (prefix_given != NULL && strcmp(prefix_given, "") != 0) {
- stringsink_string(classname, NULL, prefix_given,
- strlen(prefix_given), NULL);
- } else {
- if (is_reserved(segment, length)) {
- if (package_name != NULL &&
- strcmp("google.protobuf", package_name) == 0) {
- stringsink_string(classname, NULL, "GPB", 3, NULL);
- } else {
- stringsink_string(classname, NULL, "PB", 2, NULL);
- }
- }
+void DescriptorPool_CreateWithSymbolTable(zval *zv, upb_symtab *symtab) {
+ ZVAL_OBJ(zv, DescriptorPool_create(DescriptorPool_class_entry));
+
+ if (symtab) {
+ DescriptorPool *intern = GetPool(zv);
+ upb_symtab_free(intern->symtab);
+ intern->symtab = symtab;
}
}
-static void fill_segment(const char *segment, int length,
- stringsink *classname, bool use_camel) {
- if (use_camel && (segment[0] < 'A' || segment[0] > 'Z')) {
- char first = segment[0] + ('A' - 'a');
- stringsink_string(classname, NULL, &first, 1, NULL);
- stringsink_string(classname, NULL, segment + 1, length - 1, NULL);
- } else {
- stringsink_string(classname, NULL, segment, length, NULL);
- }
+upb_symtab *DescriptorPool_Steal(zval *zv) {
+ DescriptorPool *intern = GetPool(zv);
+ upb_symtab *ret = intern->symtab;
+ intern->symtab = NULL;
+ return ret;
}
-static void fill_namespace(const char *package, const char *php_namespace,
- stringsink *classname) {
- if (php_namespace != NULL) {
- if (strlen(php_namespace) != 0) {
- stringsink_string(classname, NULL, php_namespace, strlen(php_namespace),
- NULL);
- stringsink_string(classname, NULL, "\\", 1, NULL);
- }
- } else if (package != NULL) {
- int i = 0, j = 0;
- size_t package_len = strlen(package);
- while (i < package_len) {
- j = i;
- while (j < package_len && package[j] != '.') {
- j++;
- }
- fill_prefix(package + i, j - i, "", package, classname);
- fill_segment(package + i, j - i, classname, true);
- stringsink_string(classname, NULL, "\\", 1, NULL);
- i = j + 1;
- }
- }
+upb_symtab *DescriptorPool_GetSymbolTable() {
+ DescriptorPool *intern = GetPool(get_generated_pool());
+ return intern->symtab;
}
-static void fill_classname(const char *fullname,
- const char *package,
- const char *prefix,
- stringsink *classname,
- bool use_nested_submsg) {
- int classname_start = 0;
- if (package != NULL) {
- size_t package_len = strlen(package);
- classname_start = package_len == 0 ? 0 : package_len + 1;
- }
- size_t fullname_len = strlen(fullname);
- bool is_first_segment = true;
-
- int i = classname_start, j;
- while (i < fullname_len) {
- j = i;
- while (j < fullname_len && fullname[j] != '.') {
- j++;
- }
- if (use_nested_submsg || (is_first_segment && j == fullname_len)) {
- fill_prefix(fullname + i, j - i, prefix, package, classname);
- }
- is_first_segment = false;
- fill_segment(fullname + i, j - i, classname, false);
- if (j != fullname_len) {
- if (use_nested_submsg) {
- stringsink_string(classname, NULL, "\\", 1, NULL);
- } else {
- stringsink_string(classname, NULL, "_", 1, NULL);
- }
- }
- i = j + 1;
- }
+/*
+ * DescriptorPool::getGeneratedPool()
+ *
+ * Returns the generated DescriptorPool.
+ */
+PHP_METHOD(DescriptorPool, getGeneratedPool) {
+ zval ret;
+ ZVAL_COPY(&ret, get_generated_pool());
+ RETURN_ZVAL(&ret, 0, 1);
}
-static void fill_classname_for_desc(void *desc, bool is_enum) {
- const upb_filedef *file;
- const char *fullname;
- bool use_nested_submsg;
+/*
+ * DescriptorPool::getDescriptorByClassName()
+ *
+ * Returns a Descriptor object for the given PHP class name.
+ */
+PHP_METHOD(DescriptorPool, getDescriptorByClassName) {
+ char *classname = NULL;
+ zend_long classname_len;
+ zend_class_entry *ce;
+ zend_string *str;
+ zval ret;
- if (is_enum) {
- EnumDescriptorInternal* enumdesc = desc;
- file = upb_enumdef_file(enumdesc->enumdef);
- fullname = upb_enumdef_fullname(enumdesc->enumdef);
- use_nested_submsg = enumdesc->use_nested_submsg;
- } else {
- DescriptorInternal* msgdesc = desc;
- file = upb_msgdef_file(msgdesc->msgdef);
- fullname = upb_msgdef_fullname(msgdesc->msgdef);
- use_nested_submsg = msgdesc->use_nested_submsg;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname,
+ &classname_len) == FAILURE) {
+ return;
}
- // 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 *package = upb_filedef_package(file);
- const char *php_namespace = upb_filedef_phpnamespace(file);
- const char *prefix = upb_filedef_phpprefix(file);
- stringsink namesink;
- stringsink_init(&namesink);
-
- fill_namespace(package, php_namespace, &namesink);
- fill_classname(fullname, package, prefix, &namesink, use_nested_submsg);
- stringsink_string(&namesink, NULL, "\0", 1, NULL);
-
- if (is_enum) {
- EnumDescriptorInternal* enumdesc = desc;
- enumdesc->classname = strdup(namesink.ptr);
- } else {
- DescriptorInternal* msgdesc = desc;
- msgdesc->classname = strdup(namesink.ptr);
+ str = zend_string_init(classname, strlen(classname), 0);
+ ce = zend_lookup_class(str); // May autoload the class.
+ zend_string_release (str);
+
+ if (!ce) {
+ RETURN_NULL();
}
- stringsink_uninit(&namesink);
+ Descriptor_FromClassEntry(&ret, ce);
+ RETURN_ZVAL(&ret, 1, 0);
}
-void register_class(void *desc, bool is_enum TSRMLS_DC) {
- const char *classname;
- const char *fullname;
- zend_class_entry* ret;
+/*
+ * DescriptorPool::getEnumDescriptorByClassName()
+ *
+ * Returns a EnumDescriptor object for the given PHP class name.
+ */
+PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) {
+ char *classname = NULL;
+ zend_long classname_len;
+ zend_class_entry *ce;
+ zend_string *str;
+ zval ret;
- if (is_enum) {
- EnumDescriptorInternal* enumdesc = desc;
- if (enumdesc->klass) {
- return;
- }
- classname = enumdesc->classname;
- fullname = upb_enumdef_fullname(enumdesc->enumdef);
- } else {
- DescriptorInternal* msgdesc = desc;
- if (msgdesc->klass) {
- return;
- }
- if (!msgdesc->classname) {
- return;
- }
- classname = msgdesc->classname;
- fullname = upb_msgdef_fullname(msgdesc->msgdef);
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname,
+ &classname_len) == FAILURE) {
+ return;
}
- 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 (%s)",
- classname, fullname);
+ str = zend_string_init(classname, strlen(classname), 0);
+ ce = zend_lookup_class(str); // May autoload the class.
+ zend_string_release (str);
+
+ if (!ce) {
+ RETURN_NULL();
+ }
+
+ EnumDescriptor_FromClassEntry(&ret, ce);
+ RETURN_ZVAL(&ret, 1, 0);
+}
+
+/*
+ * DescriptorPool::getEnumDescriptorByProtoName()
+ *
+ * Returns a Descriptor object for the given protobuf message name.
+ */
+PHP_METHOD(DescriptorPool, getDescriptorByProtoName) {
+ DescriptorPool *intern = GetPool(getThis());
+ char *protoname = NULL;
+ zend_long protoname_len;
+ const upb_msgdef *m;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &protoname,
+ &protoname_len) == FAILURE) {
return;
}
- ret = PHP_PROTO_CE_UNREF(pce);
- if (is_enum) {
- EnumDescriptorInternal* enumdesc = desc;
- add_ce_enumdesc(ret, desc);
- enumdesc->klass = ret;
+
+ if (*protoname == '.') protoname++;
+
+ m = upb_symtab_lookupmsg(intern->symtab, protoname);
+
+ if (m) {
+ zval ret;
+ ZVAL_OBJ(&ret, &Descriptor_GetFromMessageDef(m)->std);
+ RETURN_ZVAL(&ret, 1, 0);
} else {
- DescriptorInternal* msgdesc = desc;
- add_ce_desc(ret, desc);
- msgdesc->klass = ret;
- // Map entries don't have existing php class.
- if (!upb_msgdef_mapentry(msgdesc->msgdef)) {
- if (msgdesc->layout == NULL) {
- MessageLayout* layout = create_layout(msgdesc->msgdef);
- msgdesc->layout = layout;
- }
- }
+ RETURN_NULL();
}
}
+/*
+ * depends_on_descriptor()
+ *
+ * Returns true if this FileDescriptorProto depends on descriptor.proto.
+ */
bool depends_on_descriptor(const google_protobuf_FileDescriptorProto* file) {
const upb_strview *deps;
upb_strview name = upb_strview_makez("google/protobuf/descriptor.proto");
@@ -891,247 +894,192 @@ bool depends_on_descriptor(const google_protobuf_FileDescriptorProto* file) {
return false;
}
-static void internal_add_single_generated_file(
- const upb_filedef* file,
- InternalDescriptorPoolImpl* pool,
- bool use_nested_submsg TSRMLS_DC) {
+/*
+ * add_name_mappings()
+ *
+ * Adds the messages and enums in this file to the NameMap.
+ */
+static void add_name_mappings(const upb_filedef *file) {
size_t i;
- // For 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_msgcount(file); i++) {
- const upb_msgdef *msgdef = upb_filedef_msg(file, i);
- CREATE_HASHTABLE_VALUE(desc, desc_php, Descriptor, descriptor_type);
- desc->intern = SYS_MALLOC(DescriptorInternal);
- desc->intern->msgdef = msgdef;
- desc->intern->pool = pool;
- desc->intern->layout = NULL;
- desc->intern->klass = NULL;
- desc->intern->use_nested_submsg = use_nested_submsg;
- desc->intern->classname = NULL;
-
- add_def_obj(desc->intern->msgdef, desc_php);
- add_msgdef_desc(desc->intern->msgdef, desc->intern);
-
- // Unlike other messages, MapEntry is shared by all map fields and doesn't
- // have generated PHP class.
- if (upb_msgdef_mapentry(msgdef)) {
- continue;
- }
-
- fill_classname_for_desc(desc->intern, false);
- add_class_desc(desc->intern->classname, desc->intern);
- add_proto_desc(upb_msgdef_fullname(desc->intern->msgdef), desc->intern);
+ NameMap_AddMessage(upb_filedef_msg(file, i));
}
for (i = 0; i < upb_filedef_enumcount(file); i++) {
- const upb_enumdef *enumdef = upb_filedef_enum(file, i);
- CREATE_HASHTABLE_VALUE(desc, desc_php, EnumDescriptor, enum_descriptor_type);
- desc->intern = SYS_MALLOC(EnumDescriptorInternal);
- desc->intern->enumdef = enumdef;
- desc->intern->klass = NULL;
- desc->intern->use_nested_submsg = use_nested_submsg;
- desc->intern->classname = NULL;
-
- add_def_obj(desc->intern->enumdef, desc_php);
- add_enumdef_enumdesc(desc->intern->enumdef, desc->intern);
- fill_classname_for_desc(desc->intern, true);
- add_class_enumdesc(desc->intern->classname, desc->intern);
+ NameMap_AddEnum(upb_filedef_enum(file, i));
}
}
-const bool parse_and_add_descriptor(const char *data,
- PHP_PROTO_SIZE data_len,
- InternalDescriptorPoolImpl *pool,
- upb_arena *arena,
- bool use_nested_submsg TSRMLS_DC) {
+/*
+ * add_name_mappings()
+ *
+ * Adds the given descriptor data to this DescriptorPool.
+ */
+static void add_descriptor(DescriptorPool *pool, const char *data,
+ int data_len, upb_arena *arena) {
size_t i, n;
google_protobuf_FileDescriptorSet *set;
const google_protobuf_FileDescriptorProto* const* files;
- const upb_filedef* file;
- upb_status status;
- set = google_protobuf_FileDescriptorSet_parse(
- data, data_len, arena);
+ set = google_protobuf_FileDescriptorSet_parse(data, data_len, arena);
if (!set) {
zend_error(E_ERROR, "Failed to parse binary descriptor\n");
- return false;
+ return;
}
files = google_protobuf_FileDescriptorSet_file(set, &n);
for (i = 0; i < n; i++) {
- // Check whether file has already been added.
- upb_strview name = google_protobuf_FileDescriptorProto_name(files[i]);
- // TODO(teboring): Needs another look up method which takes data and length.
- file = upb_symtab_lookupfile2(pool->symtab, name.data, name.size);
- if (file != NULL) {
+ const google_protobuf_FileDescriptorProto* file = files[i];
+ upb_strview name = google_protobuf_FileDescriptorProto_name(file);
+ upb_status status;
+ const upb_filedef *file_def;
+ upb_status_clear(&status);
+
+ if (upb_symtab_lookupfile2(pool->symtab, name.data, name.size)) {
+ // Already added.
continue;
}
// The PHP code generator currently special-cases descriptor.proto. It
// doesn't add it as a dependency even if the proto file actually does
// depend on it.
- if (depends_on_descriptor(files[i]) &&
- upb_symtab_lookupfile(
- pool->symtab, "google/protobuf/descriptor.proto") ==
- NULL) {
- if (!parse_and_add_descriptor((char *)descriptor_proto,
- descriptor_proto_len, pool, arena,
- use_nested_submsg TSRMLS_CC)) {
- return false;
- }
+ if (depends_on_descriptor(file)) {
+ google_protobuf_FileDescriptorProto_getmsgdef(pool->symtab);
}
- upb_status_clear(&status);
- file = upb_symtab_addfile(pool->symtab, files[i], &status);
- check_upb_status(&status, "Unable to load descriptor");
-
- internal_add_single_generated_file(file, pool, use_nested_submsg TSRMLS_CC);
+ file_def = upb_symtab_addfile(pool->symtab, file, &status);
+ CheckUpbStatus(&status, "Unable to load descriptor");
+ add_name_mappings(file_def);
}
-
- return true;
-}
-
-void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
- InternalDescriptorPoolImpl *pool,
- bool use_nested_submsg TSRMLS_DC) {
- int i;
- upb_arena *arena;
-
- arena = upb_arena_new();
- parse_and_add_descriptor(data, data_len, pool, arena,
- use_nested_submsg TSRMLS_CC);
- upb_arena_free(arena);
- return;
}
-PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) {
+/*
+ * DescriptorPool::internalAddGeneratedFile()
+ *
+ * Adds the given descriptor data to this DescriptorPool.
+ */
+PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {
+ DescriptorPool *intern = GetPool(getThis());
char *data = NULL;
- PHP_PROTO_SIZE data_len;
+ zend_long data_len;
zend_bool use_nested_submsg = false;
+ upb_arena *arena;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b",
- &data, &data_len, &use_nested_submsg) ==
- FAILURE) {
- return;
- }
-
- InternalDescriptorPool *pool = UNBOX(InternalDescriptorPool, getThis());
- internal_add_generated_file(data, data_len, pool->intern,
- use_nested_submsg TSRMLS_CC);
-}
-
-PHP_METHOD(DescriptorPool, getDescriptorByClassName) {
- char *classname = NULL;
- PHP_PROTO_SIZE classname_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname,
- &classname_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &data, &data_len,
+ &use_nested_submsg) != SUCCESS) {
return;
}
- PHP_PROTO_CE_DECLARE pce;
- if (php_proto_zend_lookup_class(classname, classname_len, &pce) ==
- FAILURE) {
- RETURN_NULL();
- }
-
- PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(PHP_PROTO_CE_UNREF(pce));
- if (desc_php == NULL) {
- DescriptorInternal* intern = get_ce_desc(PHP_PROTO_CE_UNREF(pce));
- if (intern == NULL) {
- RETURN_NULL();
- }
-
-#if PHP_MAJOR_VERSION < 7
- MAKE_STD_ZVAL(desc_php);
- ZVAL_OBJ(desc_php, descriptor_type->create_object(
- descriptor_type TSRMLS_CC));
- Z_DELREF_P(desc_php);
-#else
- desc_php =
- descriptor_type->create_object(descriptor_type TSRMLS_CC);
- GC_DELREF(desc_php);
-#endif
- Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php);
- desc->intern = intern;
- add_def_obj(intern->msgdef, desc_php);
- add_ce_obj(PHP_PROTO_CE_UNREF(pce), desc_php);
- }
-
- zend_class_entry* instance_ce = HASHTABLE_VALUE_CE(desc_php);
-
- if (!instanceof_function(instance_ce, descriptor_type TSRMLS_CC)) {
- RETURN_NULL();
- }
-
-#if PHP_MAJOR_VERSION < 7
- RETURN_ZVAL(desc_php, 1, 0);
-#else
- GC_ADDREF(desc_php);
- RETURN_OBJ(desc_php);
-#endif
+ arena = upb_arena_new();
+ add_descriptor(intern, data, data_len, arena);
+ upb_arena_free(arena);
}
-PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) {
- char *classname = NULL;
- PHP_PROTO_SIZE classname_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname,
- &classname_len) == FAILURE) {
- return;
- }
-
- PHP_PROTO_CE_DECLARE pce;
- if (php_proto_zend_lookup_class(classname, classname_len, &pce) ==
- FAILURE) {
- RETURN_NULL();
- }
-
- zend_class_entry* ce = PHP_PROTO_CE_UNREF(pce);
-
- PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(ce);
- if (desc_php == NULL) {
-#if PHP_MAJOR_VERSION < 7
- EnumDescriptorInternal* intern = get_class_enumdesc(ce->name);
-#else
- EnumDescriptorInternal* intern = get_class_enumdesc(ZSTR_VAL(ce->name));
-#endif
- register_class(intern, true TSRMLS_CC);
+static zend_function_entry DescriptorPool_methods[] = {
+ PHP_ME(DescriptorPool, getGeneratedPool, NULL,
+ ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ PHP_ME(DescriptorPool, getDescriptorByClassName, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(DescriptorPool, getDescriptorByProtoName, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(DescriptorPool, getEnumDescriptorByClassName, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(DescriptorPool, internalAddGeneratedFile, NULL, ZEND_ACC_PUBLIC)
+ ZEND_FE_END
+};
- if (intern == NULL) {
- RETURN_NULL();
- }
+// -----------------------------------------------------------------------------
+// GPBType
+// -----------------------------------------------------------------------------
-#if PHP_MAJOR_VERSION < 7
- MAKE_STD_ZVAL(desc_php);
- ZVAL_OBJ(desc_php, enum_descriptor_type->create_object(
- enum_descriptor_type TSRMLS_CC));
- Z_DELREF_P(desc_php);
-#else
- desc_php =
- enum_descriptor_type->create_object(enum_descriptor_type TSRMLS_CC);
- GC_DELREF(desc_php);
-#endif
- EnumDescriptor* desc = UNBOX_HASHTABLE_VALUE(EnumDescriptor, desc_php);
- desc->intern = intern;
- add_def_obj(intern->enumdef, desc_php);
- add_ce_obj(ce, desc_php);
- }
+zend_class_entry* gpb_type_type;
- zend_class_entry* instance_ce = HASHTABLE_VALUE_CE(desc_php);
+static zend_function_entry gpb_type_methods[] = {
+ ZEND_FE_END
+};
- if (!instanceof_function(instance_ce, enum_descriptor_type TSRMLS_CC)) {
- RETURN_NULL();
- }
+// -----------------------------------------------------------------------------
+// Module Init
+// -----------------------------------------------------------------------------
-#if PHP_MAJOR_VERSION < 7
- RETURN_ZVAL(desc_php, 1, 0);
-#else
- GC_ADDREF(desc_php);
- RETURN_OBJ(desc_php);
-#endif
+void Def_ModuleInit() {
+ zend_class_entry tmp_ce;
+ zend_object_handlers *h;
+
+ INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\OneofDescriptor",
+ OneofDescriptor_methods);
+ OneofDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
+ OneofDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
+ OneofDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
+ h = &OneofDescriptor_object_handlers;
+ memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+
+ INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumValueDescriptor",
+ EnumValueDescriptor_methods);
+ EnumValueDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
+ EnumValueDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
+ EnumValueDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
+ h = &EnumValueDescriptor_object_handlers;
+ memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+
+
+ INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumDescriptor",
+ EnumDescriptor_methods);
+ EnumDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
+ EnumDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
+ EnumDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
+ h = &EnumDescriptor_object_handlers;
+ memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+
+ INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Descriptor",
+ Descriptor_methods);
+
+ Descriptor_class_entry = zend_register_internal_class(&tmp_ce);
+ Descriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
+ Descriptor_class_entry->create_object = CreateHandler_ReturnNull;
+ h = &Descriptor_object_handlers;
+ memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+ h->dtor_obj = Descriptor_destructor;
+
+ INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\FieldDescriptor",
+ FieldDescriptor_methods);
+ FieldDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
+ FieldDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
+ FieldDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
+ h = &FieldDescriptor_object_handlers;
+ memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+
+ INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\DescriptorPool",
+ DescriptorPool_methods);
+ DescriptorPool_class_entry = zend_register_internal_class(&tmp_ce);
+ DescriptorPool_class_entry->ce_flags |= ZEND_ACC_FINAL;
+ DescriptorPool_class_entry->create_object = DescriptorPool_create;
+ h = &DescriptorPool_object_handlers;
+ memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+ h->dtor_obj = DescriptorPool_destructor;
+
+ // GPBType.
+#define STR(str) (str), strlen(str)
+ zend_class_entry class_type;
+ INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBType",
+ gpb_type_methods);
+ gpb_type_type = zend_register_internal_class(&class_type);
+ zend_declare_class_constant_long(gpb_type_type, STR("DOUBLE"), 1);
+ zend_declare_class_constant_long(gpb_type_type, STR("FLOAT"), 2);
+ zend_declare_class_constant_long(gpb_type_type, STR("INT64"), 3);
+ zend_declare_class_constant_long(gpb_type_type, STR("UINT64"), 4);
+ zend_declare_class_constant_long(gpb_type_type, STR("INT32"), 5);
+ zend_declare_class_constant_long(gpb_type_type, STR("FIXED64"), 6);
+ zend_declare_class_constant_long(gpb_type_type, STR("FIXED32"), 7);
+ zend_declare_class_constant_long(gpb_type_type, STR("BOOL"), 8);
+ zend_declare_class_constant_long(gpb_type_type, STR("STRING"), 9);
+ zend_declare_class_constant_long(gpb_type_type, STR("GROUP"), 10);
+ zend_declare_class_constant_long(gpb_type_type, STR("MESSAGE"), 11);
+ zend_declare_class_constant_long(gpb_type_type, STR("BYTES"), 12);
+ zend_declare_class_constant_long(gpb_type_type, STR("UINT32"), 13);
+ zend_declare_class_constant_long(gpb_type_type, STR("ENUM"), 14);
+ zend_declare_class_constant_long(gpb_type_type, STR("SFIXED32"), 15);
+ zend_declare_class_constant_long(gpb_type_type, STR("SFIXED64"), 16);
+ zend_declare_class_constant_long(gpb_type_type, STR("SINT32"), 17);
+ zend_declare_class_constant_long(gpb_type_type, STR("SINT64"), 18);
+#undef STR
}
diff --git a/php/ext/google/protobuf2/def.h b/php/ext/google/protobuf/def.h
similarity index 100%
rename from php/ext/google/protobuf2/def.h
rename to php/ext/google/protobuf/def.h
diff --git a/php/ext/google/protobuf/encode_decode.c b/php/ext/google/protobuf/encode_decode.c
deleted file mode 100644
index 8eaa5d22ee..0000000000
--- a/php/ext/google/protobuf/encode_decode.c
+++ /dev/null
@@ -1,2283 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-#include
-#include
-
-#include "protobuf.h"
-#include "utf8.h"
-
-/* stringsink *****************************************************************/
-
-static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
- stringsink *sink = _sink;
- sink->len = 0;
- return sink;
-}
-
-size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
- size_t len, const upb_bufhandle *handle) {
- stringsink *sink = _sink;
- size_t new_size = sink->size;
-
- PHP_PROTO_UNUSED(hd);
- PHP_PROTO_UNUSED(handle);
-
- while (sink->len + len > new_size) {
- new_size *= 2;
- }
-
- if (new_size != sink->size) {
- sink->ptr = realloc(sink->ptr, new_size);
- sink->size = new_size;
- }
-
- memcpy(sink->ptr + sink->len, ptr, len);
- sink->len += len;
-
- return len;
-}
-
-void stringsink_init(stringsink *sink) {
- upb_byteshandler_init(&sink->handler);
- upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
- upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
-
- upb_bytessink_reset(&sink->sink, &sink->handler, sink);
-
- sink->size = 32;
- sink->ptr = malloc(sink->size);
- PHP_PROTO_ASSERT(sink->ptr != NULL);
- sink->len = 0;
-}
-
-void stringsink_uninit(stringsink *sink) { free(sink->ptr); }
-
-void stringsink_uninit_opaque(void *sink) { stringsink_uninit(sink); }
-
-/* stackenv *****************************************************************/
-
-// Stack-allocated context during an encode/decode operation. Contains the upb
-// environment and its stack-based allocator, an initial buffer for allocations
-// to avoid malloc() when possible, and a template for PHP exception messages
-// if any error occurs.
-#define STACK_ENV_STACKBYTES 4096
-typedef struct {
- upb_arena *arena;
- upb_status status;
- const char *php_error_template;
- char allocbuf[STACK_ENV_STACKBYTES];
-} stackenv;
-
-
-static void stackenv_init(stackenv* se, const char* errmsg);
-static void stackenv_uninit(stackenv* se);
-
-static void stackenv_init(stackenv* se, const char* errmsg) {
- se->php_error_template = errmsg;
- se->arena = upb_arena_new();
- upb_status_clear(&se->status);
-}
-
-static void stackenv_uninit(stackenv* se) {
- upb_arena_free(se->arena);
-
- if (!upb_ok(&se->status)) {
- // TODO(teboring): have a way to verify that this is actually a parse error,
- // instead of just throwing "parse error" unconditionally.
- TSRMLS_FETCH();
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC, se->php_error_template,
- upb_status_errmsg(&se->status));
- }
-}
-
-// -----------------------------------------------------------------------------
-// Parsing.
-// -----------------------------------------------------------------------------
-
-bool is_wrapper_msg(const upb_msgdef* m) {
- switch (upb_msgdef_wellknowntype(m)) {
- case UPB_WELLKNOWN_DOUBLEVALUE:
- case UPB_WELLKNOWN_FLOATVALUE:
- case UPB_WELLKNOWN_INT64VALUE:
- case UPB_WELLKNOWN_UINT64VALUE:
- case UPB_WELLKNOWN_INT32VALUE:
- case UPB_WELLKNOWN_UINT32VALUE:
- case UPB_WELLKNOWN_STRINGVALUE:
- case UPB_WELLKNOWN_BYTESVALUE:
- case UPB_WELLKNOWN_BOOLVALUE:
- return true;
- default:
- return false;
- }
-}
-
-typedef struct {
- void* closure;
- void* submsg;
- bool is_msg;
-} wrapperfields_parseframe_t;
-
-#define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs)
-
-// Creates a handlerdata that simply contains the offset for this field.
-static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) {
- size_t* hd_ofs = (size_t*)malloc(sizeof(size_t));
- PHP_PROTO_ASSERT(hd_ofs != NULL);
- *hd_ofs = ofs;
- upb_handlers_addcleanup(h, hd_ofs, free);
- return hd_ofs;
-}
-
-static const void* newhandlerfielddata(
- upb_handlers* h, const upb_fielddef* field) {
- const void** hd_field = malloc(sizeof(void*));
- PHP_PROTO_ASSERT(hd_field != NULL);
- *hd_field = field;
- upb_handlers_addcleanup(h, hd_field, free);
- return hd_field;
-}
-
-typedef struct {
- void* closure;
- stringsink sink;
-} stringfields_parseframe_t;
-
-typedef size_t (*encodeunknown_handlerfunc)(void* _sink, const void* hd,
- const char* ptr, size_t len,
- const upb_bufhandle* handle);
-
-typedef struct {
- encodeunknown_handlerfunc handler;
-} unknownfields_handlerdata_t;
-
-// Creates a handlerdata for unknown fields.
-static const void *newunknownfieldshandlerdata(upb_handlers* h) {
- unknownfields_handlerdata_t* hd =
- (unknownfields_handlerdata_t*)malloc(sizeof(unknownfields_handlerdata_t));
- PHP_PROTO_ASSERT(hd != NULL);
- hd->handler = stringsink_string;
- upb_handlers_addcleanup(h, hd, free);
- return hd;
-}
-
-typedef struct {
- const upb_fielddef *fd;
- size_t ofs;
- const upb_msgdef *md;
-} submsg_handlerdata_t;
-
-// Creates a handlerdata that contains field and submessage type information.
-static const void *newsubmsghandlerdata(upb_handlers* h, uint32_t ofs,
- const upb_fielddef* f) {
- submsg_handlerdata_t* hd =
- (submsg_handlerdata_t*)malloc(sizeof(submsg_handlerdata_t));
- PHP_PROTO_ASSERT(hd != NULL);
- hd->fd = f;
- hd->ofs = ofs;
- hd->md = upb_fielddef_msgsubdef(f);
- upb_handlers_addcleanup(h, hd, free);
- return hd;
-}
-
-typedef struct {
- size_t ofs; // union data slot
- size_t case_ofs; // oneof_case field
- int property_ofs; // properties table cache
- uint32_t oneof_case_num; // oneof-case number to place in oneof_case field
- const upb_msgdef *md; // msgdef, for oneof submessage handler
- const upb_msgdef *parent_md; // msgdef, for parent submessage
-} oneof_handlerdata_t;
-
-static const void *newoneofhandlerdata(upb_handlers *h,
- uint32_t ofs,
- uint32_t case_ofs,
- int property_ofs,
- const upb_msgdef *m,
- const upb_fielddef *f) {
- oneof_handlerdata_t* hd =
- (oneof_handlerdata_t*)malloc(sizeof(oneof_handlerdata_t));
- PHP_PROTO_ASSERT(hd != NULL);
- hd->ofs = ofs;
- hd->case_ofs = case_ofs;
- hd->property_ofs = property_ofs;
- hd->parent_md = m;
- // We reuse the field tag number as a oneof union discriminant tag. Note that
- // we don't expose these numbers to the user, so the only requirement is that
- // we have some unique ID for each union case/possibility. The field tag
- // numbers are already present and are easy to use so there's no reason to
- // create a separate ID space. In addition, using the field tag number here
- // lets us easily look up the field in the oneof accessor.
- hd->oneof_case_num = upb_fielddef_number(f);
- if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) {
- hd->md = upb_fielddef_msgsubdef(f);
- } else {
- hd->md = NULL;
- }
- upb_handlers_addcleanup(h, hd, free);
- return hd;
-}
-
-// A handler that starts a repeated field. Gets the Repeated*Field instance for
-// this field (such an instance always exists even in an empty message).
-static void *startseq_handler(void* closure, const void* hd) {
- MessageHeader* msg = closure;
- const upb_fielddef** field = (const upb_fielddef**) hd;
- CACHED_VALUE* cache = find_zval_property(msg, *field);
- TSRMLS_FETCH();
- repeated_field_ensure_created(*field, cache PHP_PROTO_TSRMLS_CC);
- return CACHED_PTR_TO_ZVAL_PTR(cache);
-}
-
-// 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_APPEND_HANDLER(bool, bool)
-DEFINE_APPEND_HANDLER(int32, int32_t)
-DEFINE_APPEND_HANDLER(uint32, uint32_t)
-DEFINE_APPEND_HANDLER(float, float)
-DEFINE_APPEND_HANDLER(int64, int64_t)
-DEFINE_APPEND_HANDLER(uint64, uint64_t)
-DEFINE_APPEND_HANDLER(double, double)
-
-// Appends a string or 'bytes' string to a repeated field.
-static void* appendstr_handler(void *closure,
- const void *hd,
- size_t size_hint) {
- PHP_PROTO_UNUSED(hd);
-
- stringfields_parseframe_t* frame =
- (stringfields_parseframe_t*)malloc(sizeof(stringfields_parseframe_t));
- PHP_PROTO_ASSERT(frame != NULL);
- frame->closure = closure;
- stringsink_init(&frame->sink);
-
- return frame;
-}
-
-static bool appendstr_end_handler(void *closure, const void *hd) {
- stringfields_parseframe_t* frame = closure;
-
- zval* array = (zval*)frame->closure;
- TSRMLS_FETCH();
- RepeatedField* intern = UNBOX(RepeatedField, array);
-
-#if PHP_MAJOR_VERSION < 7
- zval* str;
- MAKE_STD_ZVAL(str);
- PHP_PROTO_ZVAL_STRINGL(str, frame->sink.ptr, frame->sink.len, 1);
- repeated_field_push_native(intern, &str);
-#else
- zend_string* str = zend_string_init(frame->sink.ptr, frame->sink.len, 1);
- repeated_field_push_native(intern, &str);
-#endif
-
- stringsink_uninit(&frame->sink);
- free(frame);
-
- return true;
-}
-
-// 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 new_php_string(zval** value_ptr, const char* str, size_t len) {
- SEPARATE_ZVAL_IF_NOT_REF(value_ptr);
- if (Z_TYPE_PP(value_ptr) == IS_STRING &&
- !IS_INTERNED(Z_STRVAL_PP(value_ptr))) {
- FREE(Z_STRVAL_PP(value_ptr));
- }
- ZVAL_STRINGL(*value_ptr, str, len, 1);
-}
-#else
-static void new_php_string(zval* value_ptr, const char* str, size_t len) {
- if (Z_TYPE_P(value_ptr) == IS_STRING) {
- zend_string_release(Z_STR_P(value_ptr));
- }
- ZVAL_NEW_STR(value_ptr, zend_string_init(str, len, 0));
-}
-#endif
-
-// Sets a non-repeated string/bytes field in a message.
-static void* str_handler(void *closure,
- const void *hd,
- size_t size_hint) {
- PHP_PROTO_UNUSED(hd);
-
- stringfields_parseframe_t* frame =
- (stringfields_parseframe_t*)malloc(sizeof(stringfields_parseframe_t));
- PHP_PROTO_ASSERT(frame != NULL);
- frame->closure = closure;
- stringsink_init(&frame->sink);
-
- return frame;
-}
-
-static bool str_end_handler(void *closure, const void *hd) {
- stringfields_parseframe_t* frame = closure;
- const upb_fielddef **field = (const upb_fielddef **) hd;
- MessageHeader* msg = (MessageHeader*)frame->closure;
-
- CACHED_VALUE* cached = find_zval_property(msg, *field);
-
- new_php_string(cached, frame->sink.ptr, frame->sink.len);
-
- stringsink_uninit(&frame->sink);
- free(frame);
-
- return true;
-}
-
-static bool map_str_end_handler(void *closure, const void *hd) {
- stringfields_parseframe_t* frame = closure;
- const size_t *ofs = hd;
- MessageHeader* msg = (MessageHeader*)frame->closure;
-
- new_php_string(DEREF(message_data(msg), *ofs, CACHED_VALUE*),
- frame->sink.ptr, frame->sink.len);
-
- stringsink_uninit(&frame->sink);
- free(frame);
-
- return true;
-}
-
-static size_t stringdata_handler(void* closure, const void* hd,
- const char* str, size_t len,
- const upb_bufhandle* handle) {
- stringfields_parseframe_t* frame = closure;
- return stringsink_string(&frame->sink, hd, str, len, handle);
-}
-
-// 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);
-
- const submsg_handlerdata_t *submsgdata = hd;
- DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
- register_class(subdesc, false 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);
-
- return submsg;
-}
-
-// Appends a wrapper submessage to a repeated field.
-static void *appendwrappersubmsg_handler(void *closure, const void *hd) {
- zval* array = (zval*)closure;
- TSRMLS_FETCH();
- RepeatedField* intern = UNBOX(RepeatedField, array);
-
- const submsg_handlerdata_t *submsgdata = hd;
- DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
- register_class(subdesc, false TSRMLS_CC);
- zend_class_entry* subklass = subdesc->klass;
- MessageHeader* submsg;
- wrapperfields_parseframe_t* frame =
- (wrapperfields_parseframe_t*)malloc(sizeof(wrapperfields_parseframe_t));
-
-#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);
-
- frame->closure = closure;
- frame->submsg = submsg;
- frame->is_msg = true;
-
- return frame;
-}
-
-// Sets a non-repeated submessage field in a message.
-static void *submsg_handler(void *closure, const void *hd) {
- MessageHeader* msg = closure;
- const submsg_handlerdata_t* submsgdata = hd;
- TSRMLS_FETCH();
- DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
- register_class(subdesc, false TSRMLS_CC);
- zend_class_entry* subklass = subdesc->klass;
- zval* submsg_php;
- MessageHeader* submsg;
-
- CACHED_VALUE* cached = find_zval_property(msg, submsgdata->fd);
-
- if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_NULL) {
-#if PHP_MAJOR_VERSION < 7
- 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);
- REPLACE_ZVAL_VALUE(cached, &val, 1);
- zval_dtor(&val);
-#else
- zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
- ZVAL_OBJ(cached, obj);
- MessageHeader* intern = UNBOX_HASHTABLE_VALUE(MessageHeader, obj);
- custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
-#endif
- }
-
- submsg_php = CACHED_PTR_TO_ZVAL_PTR(cached);
-
- submsg = UNBOX(MessageHeader, submsg_php);
- return submsg;
-}
-
-static void *map_submsg_handler(void *closure, const void *hd) {
- MessageHeader* msg = closure;
- const submsg_handlerdata_t* submsgdata = hd;
- TSRMLS_FETCH();
- DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
- register_class(subdesc, false TSRMLS_CC);
- zend_class_entry* subklass = subdesc->klass;
- zval* submsg_php;
- MessageHeader* submsg;
-
- CACHED_VALUE* cached =
- DEREF(message_data(msg), submsgdata->ofs, CACHED_VALUE*);
-
- if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_NULL) {
-#if PHP_MAJOR_VERSION < 7
- 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);
- REPLACE_ZVAL_VALUE(cached, &val, 1);
- zval_dtor(&val);
-#else
- zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
- ZVAL_OBJ(cached, obj);
- MessageHeader* intern = UNBOX_HASHTABLE_VALUE(MessageHeader, obj);
- custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
-#endif
- }
-
- submsg_php = CACHED_PTR_TO_ZVAL_PTR(cached);
-
- submsg = UNBOX(MessageHeader, submsg_php);
- return submsg;
-}
-
-static void *map_wrapper_submsg_handler(void *closure, const void *hd) {
- MessageHeader* msg = closure;
- const submsg_handlerdata_t* submsgdata = hd;
- TSRMLS_FETCH();
- DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
- register_class(subdesc, false TSRMLS_CC);
- zend_class_entry* subklass = subdesc->klass;
- zval* submsg_php;
- MessageHeader* submsg;
- wrapperfields_parseframe_t* frame =
- (wrapperfields_parseframe_t*)malloc(sizeof(wrapperfields_parseframe_t));
-
- CACHED_VALUE* cached =
- DEREF(message_data(msg), submsgdata->ofs, CACHED_VALUE*);
-
- if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_NULL) {
-#if PHP_MAJOR_VERSION < 7
- 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);
- REPLACE_ZVAL_VALUE(cached, &val, 1);
- zval_dtor(&val);
-#else
- zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
- ZVAL_OBJ(cached, obj);
- MessageHeader* intern = UNBOX_HASHTABLE_VALUE(MessageHeader, obj);
- custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
-#endif
- }
-
- submsg_php = CACHED_PTR_TO_ZVAL_PTR(cached);
-
- submsg = UNBOX(MessageHeader, submsg_php);
- frame->closure = closure;
- frame->submsg = submsg;
- frame->is_msg = true;
- return frame;
-}
-
-// Handler data for startmap/endmap handlers.
-typedef struct {
- const upb_fielddef* fd;
- const upb_msgdef* value_md;
- upb_fieldtype_t key_field_type;
- upb_fieldtype_t value_field_type;
-} map_handlerdata_t;
-
-// Temporary frame for map parsing: at the beginning of a map entry message, a
-// submsg handler allocates a frame to hold (i) a reference to the Map object
-// into which this message will be inserted and (ii) storage slots to
-// temporarily hold the key and value for this map entry until the end of the
-// submessage. When the submessage ends, another handler is called to insert the
-// value into the map.
-typedef struct {
- char key_storage[NATIVE_SLOT_MAX_SIZE];
- char value_storage[NATIVE_SLOT_MAX_SIZE];
-} map_parse_frame_data_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,
- const upb_msgdef* value_msg PHP_PROTO_TSRMLS_DC) {
- 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***)memory = holder;
- zval* tmp;
- MAKE_STD_ZVAL(tmp);
- PHP_PROTO_ZVAL_STRINGL(tmp, "", 0, 1);
- *holder = tmp;
-#else
- *(zval**)memory = cache;
- PHP_PROTO_ZVAL_STRINGL(*(zval**)memory, "", 0, 1);
-#endif
- break;
- }
- case UPB_TYPE_MESSAGE: {
- DescriptorInternal* subdesc = get_msgdef_desc(value_msg);
- register_class(subdesc, false TSRMLS_CC);
- zend_class_entry* subklass = subdesc->klass;
- MessageHeader* submsg;
-#if PHP_MAJOR_VERSION < 7
- zval** holder = ALLOC(zval*);
- zval* tmp;
- MAKE_STD_ZVAL(tmp);
- ZVAL_OBJ(tmp, subklass->create_object(subklass TSRMLS_CC));
- submsg = UNBOX(MessageHeader, tmp);
- custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
- *holder = tmp;
- *(zval***)memory = holder;
-#else
- *(zval**)memory = cache;
- ZVAL_OBJ(*(zval**)memory, subklass->create_object(subklass TSRMLS_CC));
- submsg = UNBOX(MessageHeader, cache);
- custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
-#endif
- break;
- }
- default:
- native_slot_init(type, memory, NULL);
- }
-}
-
-static void map_slot_uninit(void* memory, upb_fieldtype_t type) {
- switch (type) {
- case UPB_TYPE_MESSAGE:
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES: {
-#if PHP_MAJOR_VERSION < 7
- zval** holder = *(zval***)memory;
- zval_ptr_dtor(holder);
- FREE(holder);
-#else
- php_proto_zval_ptr_dtor(*(zval**)memory);
-#endif
- break;
- }
- default:
- break;
- }
-}
-
-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 {
- *keyval = from;
- *length = native_slot_size(type);
- }
-}
-
-static void map_slot_value(upb_fieldtype_t type, const void* from,
- upb_value* v) {
- size_t len;
- void* to = upb_value_memory(v);
-#ifndef NDEBUG
- v->ctype = UPB_CTYPE_UINT64;
-#endif
-
- memset(to, 0, native_slot_size(type));
-
- switch (type) {
-#if PHP_MAJOR_VERSION < 7
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES:
- case UPB_TYPE_MESSAGE: {
- *(zval**)to = **(zval***)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:
- if (!ZVAL_IS_NULL(*(zval**)from)) {
- *(zend_object**)to = Z_OBJ_P(*(zval**)from);
- GC_ADDREF(*(zend_object**)to);
- }
- break;
-#endif
- default:
- len = native_slot_size(type);
- memcpy(to, from, len);
- }
-}
-
-// Handler to begin a map entry: allocates a temporary frame. This is the
-// 'startsubmsg' handler on the msgdef that contains the map field.
-static void *startmapentry_handler(void *closure, const void *hd) {
- MessageHeader* msg = closure;
- const map_handlerdata_t* mapdata = hd;
- CACHED_VALUE* cache = find_zval_property(msg, mapdata->fd);
- TSRMLS_FETCH();
- map_field_ensure_created(mapdata->fd, cache PHP_PROTO_TSRMLS_CC);
- zval* map = CACHED_PTR_TO_ZVAL_PTR(cache);
-
- 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, NULL PHP_PROTO_TSRMLS_CC);
- map_slot_init(&frame->data->value_storage, mapdata->value_field_type,
- &frame->value_zval, mapdata->value_md PHP_PROTO_TSRMLS_CC);
-
- return frame;
-}
-
-// Handler to end a map entry: inserts the value defined during the message into
-// the map. This is the 'endmsg' handler on the map entry msgdef.
-static bool endmap_handler(void* closure, const void* hd, upb_status* s) {
- map_parse_frame_t* frame = closure;
- const map_handlerdata_t* mapdata = hd;
-
- TSRMLS_FETCH();
- Map *map = UNBOX(Map, frame->map);
-
- 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_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);
- FREE(frame);
-
- return true;
-}
-
-// Allocates a new map_handlerdata_t given the map entry message definition. If
-// the offset of the field within the parent message is also given, that is
-// added to the handler data as well. Note that this is called *twice* per map
-// field: once in the parent message handler setup when setting the startsubmsg
-// handler and once in the map entry message handler setup when setting the
-// key/value and endmsg handlers. The reason is that there is no easy way to
-// pass the handlerdata down to the sub-message handler setup.
-static map_handlerdata_t* new_map_handlerdata(
- const upb_fielddef* field,
- const upb_msgdef* mapentry_def) {
- const upb_fielddef* key_field;
- const upb_fielddef* value_field;
- // TODO(teboring): Use emalloc and efree.
- map_handlerdata_t* hd =
- (map_handlerdata_t*)malloc(sizeof(map_handlerdata_t));
- PHP_PROTO_ASSERT(hd != NULL);
- hd->fd = field;
- key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD);
- PHP_PROTO_ASSERT(key_field != NULL);
- hd->key_field_type = upb_fielddef_type(key_field);
- value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD);
- PHP_PROTO_ASSERT(value_field != NULL);
- hd->value_field_type = upb_fielddef_type(value_field);
- if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE) {
- hd->value_md = upb_fielddef_msgsubdef(value_field);
- } else {
- hd->value_md = NULL;
- }
-
- return hd;
-}
-
-// Handlers that set primitive values in oneofs.
-#define DEFINE_ONEOF_HANDLER(type, ctype) \
- static bool oneof##type##_handler(void* closure, const void* hd, \
- ctype val) { \
- const oneof_handlerdata_t* oneofdata = hd; \
- DEREF(message_data(closure), oneofdata->case_ofs, uint32_t) = \
- oneofdata->oneof_case_num; \
- DEREF(message_data(closure), oneofdata->ofs, ctype) = val; \
- return true; \
- }
-
-DEFINE_ONEOF_HANDLER(bool, bool)
-DEFINE_ONEOF_HANDLER(int32, int32_t)
-DEFINE_ONEOF_HANDLER(uint32, uint32_t)
-DEFINE_ONEOF_HANDLER(float, float)
-DEFINE_ONEOF_HANDLER(int64, int64_t)
-DEFINE_ONEOF_HANDLER(uint64, uint64_t)
-DEFINE_ONEOF_HANDLER(double, double)
-
-#undef DEFINE_ONEOF_HANDLER
-
-static void oneof_cleanup(MessageHeader* msg,
- const oneof_handlerdata_t* oneofdata) {
- uint32_t old_case_num =
- DEREF(message_data(msg), oneofdata->case_ofs, uint32_t);
- if (old_case_num == 0) {
- return;
- }
-
- const upb_fielddef* old_field =
- upb_msgdef_itof(oneofdata->parent_md, old_case_num);
- bool need_clean = false;
-
- switch (upb_fielddef_type(old_field)) {
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES:
- need_clean = true;
- break;
- case UPB_TYPE_MESSAGE:
- if (oneofdata->oneof_case_num != old_case_num) {
- need_clean = true;
- }
- break;
- default:
- break;
- }
-
- if (need_clean) {
-#if PHP_MAJOR_VERSION < 7
- SEPARATE_ZVAL_IF_NOT_REF(
- DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
- php_proto_zval_ptr_dtor(
- *DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
- MAKE_STD_ZVAL(*DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
- ZVAL_NULL(*DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
-#endif
- }
-}
-
-// Handlers for string/bytes in a oneof.
-static bool oneofstr_end_handler(void *closure, const void *hd) {
- stringfields_parseframe_t* frame = closure;
- MessageHeader* msg = (MessageHeader*)frame->closure;
- const oneof_handlerdata_t *oneofdata = hd;
-
- oneof_cleanup(msg, oneofdata);
-
- DEREF(message_data(msg), oneofdata->case_ofs, uint32_t) =
- oneofdata->oneof_case_num;
- DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) =
- OBJ_PROP(&msg->std, oneofdata->property_ofs);
-
- new_php_string(DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*),
- frame->sink.ptr, frame->sink.len);
-
- stringsink_uninit(&frame->sink);
- free(frame);
-
- return true;
-}
-
-static void *oneofstr_handler(void *closure,
- const void *hd,
- size_t size_hint) {
- PHP_PROTO_UNUSED(hd);
-
- stringfields_parseframe_t* frame =
- (stringfields_parseframe_t*)malloc(sizeof(stringfields_parseframe_t));
- PHP_PROTO_ASSERT(frame != NULL);
- frame->closure = closure;
- stringsink_init(&frame->sink);
-
- return frame;
-}
-
-// 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);
- TSRMLS_FETCH();
- DescriptorInternal* subdesc = get_msgdef_desc(oneofdata->md);
- register_class(subdesc, false TSRMLS_CC);
- zend_class_entry* subklass = subdesc->klass;
- zval* submsg_php;
- MessageHeader* submsg;
-
- if (oldcase != oneofdata->oneof_case_num) {
- oneof_cleanup(msg, oneofdata);
-
- // Create new message.
- DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) =
- OBJ_PROP(&msg->std, oneofdata->property_ofs);
-#if PHP_MAJOR_VERSION < 7
- zval val;
- ZVAL_OBJ(&val, subklass->create_object(subklass TSRMLS_CC));
- REPLACE_ZVAL_VALUE(DEREF(message_data(msg), oneofdata->ofs, zval**),
- &val, 1);
- zval_dtor(&val);
-#else
- zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
- ZVAL_OBJ(DEREF(message_data(msg), oneofdata->ofs, zval*), obj);
-#endif
- }
-
- DEREF(message_data(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);
- return submsg;
-}
-
-// Sets a non-repeated wrapper submessage field in a message.
-static void* wrapper_submsg_handler(void* closure, const void* hd) {
- MessageHeader* msg = closure;
- const submsg_handlerdata_t* submsgdata = hd;
- TSRMLS_FETCH();
- DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
- register_class(subdesc, false TSRMLS_CC);
- zval* submsg_php;
- MessageHeader* submsg;
- wrapperfields_parseframe_t* frame =
- (wrapperfields_parseframe_t*)malloc(sizeof(wrapperfields_parseframe_t));
-
- CACHED_VALUE* cached = find_zval_property(msg, submsgdata->fd);
- submsg_php = CACHED_PTR_TO_ZVAL_PTR(cached);
- frame->closure = closure;
-
- if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_OBJECT) {
- submsg = UNBOX(MessageHeader, submsg_php);
- frame->submsg = submsg;
- frame->is_msg = true;
- } else {
- if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_NULL) {
- // Needs to initiate the wrapper message
- const upb_msgdef* msgdef = subdesc->msgdef;
- const upb_fielddef* f = upb_msgdef_itof(msgdef, 1);
- native_slot_get_default(upb_fielddef_type(f), cached TSRMLS_CC);
- }
- // In this case, wrapper message hasn't been created and value will be
- // stored in cache directly.
- frame->submsg = cached;
- frame->is_msg = false;
- }
-
- return frame;
-}
-
-// Handler for a wrapper submessage field in a oneof.
-static void* wrapper_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);
- TSRMLS_FETCH();
- DescriptorInternal* subdesc = get_msgdef_desc(oneofdata->md);
- register_class(subdesc, false TSRMLS_CC);
- wrapperfields_parseframe_t* frame =
- (wrapperfields_parseframe_t*)malloc(sizeof(wrapperfields_parseframe_t));
- CACHED_VALUE* cached = OBJ_PROP(&msg->std, oneofdata->property_ofs);
- MessageHeader* submsg;
-
- if (oldcase != oneofdata->oneof_case_num) {
- oneof_cleanup(msg, oneofdata);
- if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_NULL) {
- // Needs to initiate the wrapper message
- const upb_msgdef* msgdef = subdesc->msgdef;
- const upb_fielddef* f = upb_msgdef_itof(msgdef, 1);
- native_slot_get_default(upb_fielddef_type(f), cached TSRMLS_CC);
- }
- frame->submsg = cached;
- frame->is_msg = false;
- } else if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_OBJECT) {
- submsg = UNBOX(MessageHeader, CACHED_PTR_TO_ZVAL_PTR(cached));
- frame->submsg = submsg;
- frame->is_msg = true;
- } else {
- // In this case, wrapper message hasn't been created and value will be
- // stored in cache directly.
- frame->submsg = cached;
- frame->is_msg = false;
- }
-
- DEREF(message_data(msg), oneofdata->case_ofs, uint32_t) =
- oneofdata->oneof_case_num;
-
- return frame;
-}
-
-static bool wrapper_submsg_end_handler(void *closure, const void *hd) {
- wrapperfields_parseframe_t* frame = closure;
- free(frame);
- return true;
-}
-
-// Set up handlers for a repeated field.
-static void add_handlers_for_repeated_field(upb_handlers *h,
- const upb_fielddef *f,
- size_t offset) {
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
- attr.handler_data = newhandlerfielddata(h, f);
- upb_handlers_setstartseq(h, f, startseq_handler, &attr);
-
- switch (upb_fielddef_type(f)) {
-
-#define SET_HANDLER(utype, ltype) \
- case utype: \
- upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \
- break;
-
- SET_HANDLER(UPB_TYPE_BOOL, bool);
- SET_HANDLER(UPB_TYPE_INT32, int32);
- SET_HANDLER(UPB_TYPE_UINT32, uint32);
- SET_HANDLER(UPB_TYPE_ENUM, int32);
- SET_HANDLER(UPB_TYPE_FLOAT, float);
- SET_HANDLER(UPB_TYPE_INT64, int64);
- SET_HANDLER(UPB_TYPE_UINT64, uint64);
- SET_HANDLER(UPB_TYPE_DOUBLE, double);
-
-#undef SET_HANDLER
-
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES: {
- upb_handlers_setstartstr(h, f, appendstr_handler, NULL);
- upb_handlers_setstring(h, f, stringdata_handler, NULL);
- upb_handlers_setendstr(h, f, appendstr_end_handler, &attr);
- break;
- }
- case UPB_TYPE_MESSAGE: {
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
- attr.handler_data = newsubmsghandlerdata(h, 0, f);
- if (is_wrapper_msg(upb_fielddef_msgsubdef(f))) {
- upb_handlers_setstartsubmsg(h, f, appendwrappersubmsg_handler, &attr);
- upb_handlers_setendsubmsg(h, f, wrapper_submsg_end_handler, &attr);
- } else {
- upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
- }
- break;
- }
- }
-}
-
-// Set up handlers for a singular field.
-static void add_handlers_for_singular_field(upb_handlers *h,
- const upb_fielddef *f,
- size_t offset, bool is_map) {
- switch (upb_fielddef_type(f)) {
-#define SET_HANDLER(utype, ltype) \
- case utype: { \
- upb_handlerattr attr = UPB_HANDLERATTR_INIT; \
- attr.handler_data = 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_STRING:
- case UPB_TYPE_BYTES: {
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
- if (is_map) {
- attr.handler_data = newhandlerdata(h, offset);
- } else {
- attr.handler_data = newhandlerfielddata(h, f);
- }
- upb_handlers_setstartstr(h, f, str_handler, &attr);
- upb_handlers_setstring(h, f, stringdata_handler, &attr);
- if (is_map) {
- upb_handlers_setendstr(h, f, map_str_end_handler, &attr);
- } else {
- upb_handlers_setendstr(h, f, str_end_handler, &attr);
- }
- break;
- }
- case UPB_TYPE_MESSAGE: {
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
- if (is_map) {
- attr.handler_data = newsubmsghandlerdata(h, offset, f);
- if (is_wrapper_msg(upb_fielddef_msgsubdef(f))) {
- upb_handlers_setstartsubmsg(h, f, map_wrapper_submsg_handler, &attr);
- upb_handlers_setendsubmsg(h, f, wrapper_submsg_end_handler, &attr);
- } else {
- upb_handlers_setstartsubmsg(h, f, map_submsg_handler, &attr);
- }
- } else if (is_wrapper_msg(upb_fielddef_msgsubdef(f))) {
- attr.handler_data = newsubmsghandlerdata(h, 0, f);
- upb_handlers_setstartsubmsg(h, f, wrapper_submsg_handler, &attr);
- upb_handlers_setendsubmsg(h, f, wrapper_submsg_end_handler, &attr);
- } else {
- attr.handler_data = newsubmsghandlerdata(h, 0, f);
- upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
- }
- break;
- }
- }
-}
-
-// Adds handlers to a map field.
-static void add_handlers_for_mapfield(upb_handlers* h,
- const upb_fielddef* fielddef,
- size_t offset) {
- const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef);
- map_handlerdata_t* hd = new_map_handlerdata(fielddef, map_msgdef);
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-
- upb_handlers_addcleanup(h, hd, free);
- attr.handler_data = hd;
- upb_handlers_setstartsubmsg(h, fielddef, startmapentry_handler, &attr);
-}
-
-// Adds handlers to a map-entry msgdef.
-static void add_handlers_for_mapentry(
- const upb_msgdef* msgdef, upb_handlers* h) {
- const upb_fielddef* key_field = map_entry_key(msgdef);
- const upb_fielddef* value_field = map_entry_value(msgdef);
- map_handlerdata_t* hd = new_map_handlerdata(0, msgdef);
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-
- upb_handlers_addcleanup(h, hd, free);
- attr.handler_data = hd;
- upb_handlers_setendmsg(h, endmap_handler, &attr);
-
- add_handlers_for_singular_field(h, key_field,
- offsetof(map_parse_frame_data_t,
- key_storage), true);
- add_handlers_for_singular_field(h, value_field,
- offsetof(map_parse_frame_data_t,
- value_storage), true);
-}
-
-// Set up handlers for a oneof field.
-static void add_handlers_for_oneof_field(upb_handlers *h,
- const upb_msgdef *m,
- const upb_fielddef *f,
- size_t offset,
- size_t oneof_case_offset,
- int property_cache_offset) {
-
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
- attr.handler_data = newoneofhandlerdata(h, offset, oneof_case_offset,
- property_cache_offset, m, f);
-
- switch (upb_fielddef_type(f)) {
-
-#define SET_HANDLER(utype, ltype) \
- case utype: \
- upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \
- break;
-
- SET_HANDLER(UPB_TYPE_BOOL, bool);
- SET_HANDLER(UPB_TYPE_INT32, int32);
- SET_HANDLER(UPB_TYPE_UINT32, uint32);
- SET_HANDLER(UPB_TYPE_ENUM, int32);
- SET_HANDLER(UPB_TYPE_FLOAT, float);
- SET_HANDLER(UPB_TYPE_INT64, int64);
- SET_HANDLER(UPB_TYPE_UINT64, uint64);
- SET_HANDLER(UPB_TYPE_DOUBLE, double);
-
-#undef SET_HANDLER
-
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES: {
- upb_handlers_setstartstr(h, f, oneofstr_handler, &attr);
- upb_handlers_setstring(h, f, stringdata_handler, NULL);
- upb_handlers_setendstr(h, f, oneofstr_end_handler, &attr);
- break;
- }
- case UPB_TYPE_MESSAGE: {
- if (is_wrapper_msg(upb_fielddef_msgsubdef(f))) {
- upb_handlers_setstartsubmsg(h, f, wrapper_oneofsubmsg_handler, &attr);
- upb_handlers_setendsubmsg(h, f, wrapper_submsg_end_handler, &attr);
- } else {
- upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr);
- }
- break;
- }
- }
-}
-
-#define DEFINE_WRAPPER_HANDLER(utype, type, ctype) \
- static bool type##wrapper_handler( \
- void* closure, const void* hd, ctype val) { \
- wrapperfields_parseframe_t* frame = closure; \
- if (frame->is_msg) { \
- MessageHeader* msg = frame->submsg; \
- const size_t *ofs = hd; \
- DEREF(message_data(msg), *ofs, ctype) = val; \
- } else { \
- TSRMLS_FETCH(); \
- native_slot_get(utype, &val, frame->submsg TSRMLS_CC); \
- } \
- return true; \
- }
-
-DEFINE_WRAPPER_HANDLER(UPB_TYPE_BOOL, bool, bool)
-DEFINE_WRAPPER_HANDLER(UPB_TYPE_INT32, int32, int32_t)
-DEFINE_WRAPPER_HANDLER(UPB_TYPE_UINT32, uint32, uint32_t)
-DEFINE_WRAPPER_HANDLER(UPB_TYPE_FLOAT, float, float)
-DEFINE_WRAPPER_HANDLER(UPB_TYPE_INT64, int64, int64_t)
-DEFINE_WRAPPER_HANDLER(UPB_TYPE_UINT64, uint64, uint64_t)
-DEFINE_WRAPPER_HANDLER(UPB_TYPE_DOUBLE, double, double)
-
-#undef DEFINE_WRAPPER_HANDLER
-
-static bool strwrapper_end_handler(void *closure, const void *hd) {
- stringfields_parseframe_t* frame = closure;
- const upb_fielddef **field = (const upb_fielddef **) hd;
- wrapperfields_parseframe_t* wrapper_frame = frame->closure;
- MessageHeader* msg;
- CACHED_VALUE* cached;
-
- if (wrapper_frame->is_msg) {
- msg = wrapper_frame->submsg;
- cached = find_zval_property(msg, *field);
- } else {
- cached = wrapper_frame->submsg;
- }
-
- new_php_string(cached, frame->sink.ptr, frame->sink.len);
-
- stringsink_uninit(&frame->sink);
- free(frame);
-
- return true;
-}
-
-static void add_handlers_for_wrapper(const upb_msgdef* msgdef,
- upb_handlers* h) {
- const upb_fielddef* f = upb_msgdef_itof(msgdef, 1);
- DescriptorInternal* desc;
- size_t offset;
-
- TSRMLS_FETCH();
- desc = get_msgdef_desc(msgdef);
- offset = desc->layout->fields[upb_fielddef_index(f)].offset;
-
- switch (upb_msgdef_wellknowntype(msgdef)) {
-#define SET_HANDLER(utype, ltype) \
- case utype: { \
- upb_handlerattr attr = UPB_HANDLERATTR_INIT; \
- attr.handler_data = newhandlerdata(h, offset); \
- upb_handlers_set##ltype(h, f, ltype##wrapper_handler, &attr); \
- break; \
- }
-
- SET_HANDLER(UPB_WELLKNOWN_BOOLVALUE, bool);
- SET_HANDLER(UPB_WELLKNOWN_INT32VALUE, int32);
- SET_HANDLER(UPB_WELLKNOWN_UINT32VALUE, uint32);
- SET_HANDLER(UPB_WELLKNOWN_FLOATVALUE, float);
- SET_HANDLER(UPB_WELLKNOWN_INT64VALUE, int64);
- SET_HANDLER(UPB_WELLKNOWN_UINT64VALUE, uint64);
- SET_HANDLER(UPB_WELLKNOWN_DOUBLEVALUE, double);
-
-#undef SET_HANDLER
-
- case UPB_WELLKNOWN_STRINGVALUE:
- case UPB_WELLKNOWN_BYTESVALUE: {
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
- attr.handler_data = newhandlerfielddata(h, f);
-
- upb_handlers_setstartstr(h, f, str_handler, &attr);
- upb_handlers_setstring(h, f, stringdata_handler, &attr);
- upb_handlers_setendstr(h, f, strwrapper_end_handler, &attr);
- break;
- }
- default:
- // Cannot reach here.
- break;
- }
-}
-
-static bool add_unknown_handler(void* closure, const void* hd, const char* buf,
- size_t size) {
- encodeunknown_handlerfunc handler =
- ((unknownfields_handlerdata_t*)hd)->handler;
-
- MessageHeader* msg = (MessageHeader*)closure;
- stringsink* unknown = DEREF(message_data(msg), 0, stringsink*);
- if (unknown == NULL) {
- DEREF(message_data(msg), 0, stringsink*) = ALLOC(stringsink);
- unknown = DEREF(message_data(msg), 0, stringsink*);
- stringsink_init(unknown);
- }
-
- handler(unknown, NULL, buf, size, NULL);
-
- return true;
-}
-
-void add_handlers_for_message(const void* closure, upb_handlers* h) {
- const upb_msgdef* msgdef = upb_handlers_msgdef(h);
- TSRMLS_FETCH();
- DescriptorInternal* desc = get_msgdef_desc(msgdef);
- register_class(desc, false TSRMLS_CC);
- upb_msg_field_iter i;
-
- // If this is a mapentry message type, set up a special set of handlers and
- // bail out of the normal (user-defined) message type handling.
- if (upb_msgdef_mapentry(msgdef)) {
- add_handlers_for_mapentry(msgdef, h);
- return;
- }
-
- // If this is a wrapper message type, set up a special set of handlers and
- // bail out of the normal (user-defined) message type handling.
- if (is_wrapper_msg(msgdef)) {
- add_handlers_for_wrapper(msgdef, h);
- return;
- }
-
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
- attr.handler_data = newunknownfieldshandlerdata(h);
- upb_handlers_setunknown(h, add_unknown_handler, &attr);
-
- for (upb_msg_field_begin(&i, desc->msgdef);
- !upb_msg_field_done(&i);
- upb_msg_field_next(&i)) {
- const upb_fielddef *f = upb_msg_iter_field(&i);
- size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset;
-
- if (upb_fielddef_containingoneof(f)) {
- size_t oneof_case_offset =
- desc->layout->fields[upb_fielddef_index(f)].case_offset;
- int property_cache_index =
- desc->layout->fields[upb_fielddef_index(f)].cache_index;
- add_handlers_for_oneof_field(h, desc->msgdef, f, offset,
- oneof_case_offset, property_cache_index);
- } else if (is_map_field(f)) {
- add_handlers_for_mapfield(h, f, offset);
- } else if (upb_fielddef_isseq(f)) {
- add_handlers_for_repeated_field(h, f, offset);
- } else {
- add_handlers_for_singular_field(h, f, offset, false);
- }
- }
-}
-
-// Constructs the handlers for filling a message's data into an in-memory
-// object.
-const upb_handlers* get_fill_handlers(DescriptorInternal* desc) {
- return upb_handlercache_get(desc->pool->fill_handler_cache, desc->msgdef);
-}
-
-static const upb_pbdecodermethod *msgdef_decodermethod(DescriptorInternal* desc) {
- return upb_pbcodecache_get(desc->pool->fill_method_cache, desc->msgdef);
-}
-
-static const upb_json_parsermethod *msgdef_jsonparsermethod(DescriptorInternal* desc) {
- return upb_json_codecache_get(desc->pool->json_fill_method_cache, desc->msgdef);
-}
-
-// -----------------------------------------------------------------------------
-// Serializing.
-// -----------------------------------------------------------------------------
-
-static void putmsg(zval* msg, const DescriptorInternal* desc, upb_sink sink,
- int depth, bool is_json TSRMLS_DC);
-static void putrawmsg(MessageHeader* msg, const DescriptorInternal* desc,
- upb_sink sink, int depth, bool is_json,
- bool open_msg TSRMLS_DC);
-static void putwrappervalue(
- zval* value, const upb_fielddef* f,
- upb_sink sink, int depth, bool is_json TSRMLS_DC);
-static void putjsonany(MessageHeader* msg, const DescriptorInternal* desc,
- upb_sink sink, int depth TSRMLS_DC);
-static void putjsonlistvalue(
- MessageHeader* msg, const DescriptorInternal* desc,
- upb_sink sink, int depth TSRMLS_DC);
-static void putjsonstruct(
- MessageHeader* msg, const DescriptorInternal* desc,
- upb_sink sink, int depth TSRMLS_DC);
-
-static void putstr(zval* str, const upb_fielddef* f, upb_sink sink,
- bool force_default);
-
-static void putrawstr(const char* str, int len, const upb_fielddef* f,
- upb_sink sink, bool force_default);
-
-static void putsubmsg(zval* submsg, const upb_fielddef* f, upb_sink sink,
- int depth, bool is_json TSRMLS_DC);
-static void putrawsubmsg(MessageHeader* submsg, const upb_fielddef* f,
- upb_sink sink, int depth, bool is_json TSRMLS_DC);
-
-static void putarray(zval* array, const upb_fielddef* f, upb_sink sink,
- int depth, bool is_json TSRMLS_DC);
-static void putmap(zval* map, const upb_fielddef* f, upb_sink sink,
- int depth, bool is_json TSRMLS_DC);
-
-static upb_selector_t getsel(const upb_fielddef* f, upb_handlertype_t type) {
- upb_selector_t ret;
- bool ok = upb_handlers_getselector(f, type, &ret);
- PHP_PROTO_ASSERT(ok);
- return ret;
-}
-
-static void put_optional_value(const void* memory, int len,
- const upb_fielddef* f,
- int depth, upb_sink sink,
- bool is_json TSRMLS_DC) {
- PHP_PROTO_ASSERT(upb_fielddef_label(f) == UPB_LABEL_OPTIONAL);
-
- switch (upb_fielddef_type(f)) {
-#define T(upbtypeconst, upbtype, ctype, default_value) \
- case upbtypeconst: { \
- ctype value = DEREF(memory, 0, ctype); \
- if (is_json || value != default_value) { \
- upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); \
- upb_sink_put##upbtype(sink, sel, value); \
- } \
- } break;
-
- T(UPB_TYPE_FLOAT, float, float, 0.0)
- T(UPB_TYPE_DOUBLE, double, double, 0.0)
- T(UPB_TYPE_BOOL, bool, uint8_t, 0)
- T(UPB_TYPE_ENUM, int32, int32_t, 0)
- T(UPB_TYPE_INT32, int32, int32_t, 0)
- T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
- T(UPB_TYPE_INT64, int64, int64_t, 0)
- T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
-
-#undef T
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES:
- putrawstr(memory, len, f, sink, is_json);
- 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, is_json TSRMLS_CC);
- break;
- }
- default:
- PHP_PROTO_ASSERT(false);
- }
-}
-
-// Only string/bytes fields are stored as zval.
-static const char* raw_value(void* memory, const upb_fielddef* f) {
- switch (upb_fielddef_type(f)) {
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES:
-#if PHP_MAJOR_VERSION < 7
- return Z_STRVAL_PP((zval**)memory);
-#else
- return ZSTR_VAL(*(zend_string**)memory);
-#endif
- break;
- default:
- return memory;
- }
-}
-
-static int raw_value_len(void* memory, int len, const upb_fielddef* f) {
- switch (upb_fielddef_type(f)) {
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES:
-#if PHP_MAJOR_VERSION < 7
- return Z_STRLEN_PP((zval**)memory);
-#else
- return ZSTR_LEN(*(zend_string**)memory);
-#endif
- default:
- return len;
- }
-}
-
-static void putmap(zval* map, const upb_fielddef* f, upb_sink sink,
- int depth, bool is_json TSRMLS_DC) {
- upb_sink subsink;
- const upb_fielddef* key_field;
- const upb_fielddef* value_field;
- MapIter it;
- int len, size;
-
- PHP_PROTO_ASSERT(map != NULL);
- Map* intern = UNBOX(Map, map);
- size = upb_strtable_count(&intern->table);
- if (size == 0) return;
-
- upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
-
- PHP_PROTO_ASSERT(upb_fielddef_type(f) == UPB_TYPE_MESSAGE);
- key_field = map_field_key(f);
- value_field = map_field_value(f);
-
- for (map_begin(map, &it TSRMLS_CC); !map_done(&it); map_next(&it)) {
- upb_status status;
-
- upb_sink entry_sink;
- upb_sink_startsubmsg(subsink, getsel(f, UPB_HANDLER_STARTSUBMSG),
- &entry_sink);
- upb_sink_startmsg(entry_sink);
-
- // Serialize key.
- const char *key = map_iter_key(&it, &len);
- put_optional_value(key, len, key_field, depth + 1,
- entry_sink, is_json TSRMLS_CC);
-
- // Serialize value.
- upb_value value = map_iter_value(&it, &len);
- put_optional_value(raw_value(upb_value_memory(&value), value_field),
- raw_value_len(upb_value_memory(&value), len, value_field),
- value_field, depth + 1, entry_sink, is_json TSRMLS_CC);
-
- upb_sink_endmsg(entry_sink, &status);
- upb_sink_endsubmsg(subsink, entry_sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
- }
-
- upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
-}
-
-static void putmsg(zval* msg_php, const DescriptorInternal* desc, upb_sink sink,
- int depth, bool is_json TSRMLS_DC) {
- MessageHeader* msg = UNBOX(MessageHeader, msg_php);
- putrawmsg(msg, desc, sink, depth, is_json, true TSRMLS_CC);
-}
-
-static const upb_handlers* msgdef_json_serialize_handlers(
- DescriptorInternal* desc, bool preserve_proto_fieldnames);
-
-static void putjsonany(MessageHeader* msg, const DescriptorInternal* desc,
- upb_sink sink, int depth TSRMLS_DC) {
- upb_status status;
- const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE);
- const upb_fielddef* value_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_VALUE);
-
- zval* type_url_php_str;
- const upb_msgdef *payload_type = NULL;
-
- upb_sink_startmsg(sink);
-
- /* Handle type url */
- type_url_php_str = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, type_field));
- if (Z_STRLEN_P(type_url_php_str) > 0) {
- putstr(type_url_php_str, type_field, sink, false);
- }
-
- {
- const char* type_url_str = Z_STRVAL_P(type_url_php_str);
- size_t type_url_len = Z_STRLEN_P(type_url_php_str);
- if (type_url_len <= 20 ||
- strncmp(type_url_str, "type.googleapis.com/", 20) != 0) {
- zend_error(E_ERROR, "Invalid type url: %s", type_url_str);
- }
-
- /* Resolve type url */
- type_url_str += 20;
- type_url_len -= 20;
-
- payload_type = upb_symtab_lookupmsg2(
- generated_pool->symtab, type_url_str, type_url_len);
- if (payload_type == NULL) {
- zend_error(E_ERROR, "Unknown type: %s", type_url_str);
- return;
- }
- }
-
- {
- zval* value_php_str;
- const char* value_str;
- size_t value_len;
-
- value_php_str = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, value_field));
- value_str = Z_STRVAL_P(value_php_str);
- value_len = Z_STRLEN_P(value_php_str);
-
- if (value_len > 0) {
- DescriptorInternal* payload_desc = get_msgdef_desc(payload_type);
- register_class(payload_desc, false TSRMLS_CC);
- zend_class_entry* payload_klass = payload_desc->klass;
- zval val;
- upb_sink subsink;
- bool is_wellknown;
-
- /* Create message of the payload type. */
- ZVAL_OBJ(&val, payload_klass->create_object(payload_klass TSRMLS_CC));
- MessageHeader* intern = UNBOX(MessageHeader, &val);
- custom_data_init(payload_klass, intern PHP_PROTO_TSRMLS_CC);
-
- merge_from_string(value_str, value_len, payload_desc, intern);
-
- is_wellknown =
- upb_msgdef_wellknowntype(payload_desc->msgdef) !=
- UPB_WELLKNOWN_UNSPECIFIED;
- if (is_wellknown) {
- upb_sink_startstr(sink, getsel(value_field, UPB_HANDLER_STARTSTR), 0,
- &subsink);
- }
-
- subsink.handlers =
- msgdef_json_serialize_handlers(payload_desc, true);
- subsink.closure = sink.closure;
- putrawmsg(intern, payload_desc, subsink, depth, true,
- is_wellknown TSRMLS_CC);
-
- zval_dtor(&val);
- }
- }
-
- upb_sink_endmsg(sink, &status);
-}
-
-static void putjsonlistvalue(
- MessageHeader* msg, const DescriptorInternal* desc,
- upb_sink sink, int depth TSRMLS_DC) {
- upb_status status;
- upb_sink subsink;
- const upb_fielddef* f = upb_msgdef_itof(desc->msgdef, 1);
- zval* array;
- RepeatedField* intern;
- HashTable *ht;
- int size;
-
- upb_sink_startmsg(sink);
-
- array = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
- if (ZVAL_IS_NULL(array)) {
- upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
- upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
- } else {
- intern = UNBOX(RepeatedField, array);
- ht = PHP_PROTO_HASH_OF(intern->array);
- size = zend_hash_num_elements(ht);
-
- if (size == 0) {
- upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
- upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
- } else {
- putarray(array, f, sink, depth, true TSRMLS_CC);
- }
- }
-
- upb_sink_endmsg(sink, &status);
-}
-
-static void putjsonstruct(
- MessageHeader* msg, const DescriptorInternal* desc,
- upb_sink sink, int depth TSRMLS_DC) {
- upb_status status;
- upb_sink subsink;
- const upb_fielddef* f = upb_msgdef_itof(desc->msgdef, 1);
- zval* map;
- Map* intern;
- int size;
-
- upb_sink_startmsg(sink);
-
- map = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
- if (ZVAL_IS_NULL(map)) {
- upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
- upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
- } else {
- intern = UNBOX(Map, map);
- size = upb_strtable_count(&intern->table);
-
- if (size == 0) {
- upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
- upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
- } else {
- putmap(map, f, sink, depth, true TSRMLS_CC);
- }
- }
-
- upb_sink_endmsg(sink, &status);
-}
-
-static void putrawmsg(MessageHeader* msg, const DescriptorInternal* desc,
- upb_sink sink, int depth, bool is_json,
- bool open_msg TSRMLS_DC) {
- upb_msg_field_iter i;
- upb_status status;
-
- if (is_json &&
- upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_ANY) {
- putjsonany(msg, desc, sink, depth TSRMLS_CC);
- return;
- }
-
- if (is_json &&
- upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_LISTVALUE) {
- putjsonlistvalue(msg, desc, sink, depth TSRMLS_CC);
- return;
- }
-
- if (is_json &&
- upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_STRUCT) {
- putjsonstruct(msg, desc, sink, depth TSRMLS_CC);
- return;
- }
-
- if (open_msg) {
- upb_sink_startmsg(sink);
- }
-
- // Protect against cycles (possible because users may freely reassign message
- // and repeated fields) by imposing a maximum recursion depth.
- if (depth > ENCODE_MAX_NESTING) {
- zend_error(E_ERROR,
- "Maximum recursion depth exceeded during encoding.");
- }
-
- 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;
- bool containing_oneof = false;
-
- if (upb_fielddef_containingoneof(f)) {
- uint32_t oneof_case_offset =
- desc->layout->fields[upb_fielddef_index(f)].case_offset;
- // 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)) {
- continue;
- }
- // Otherwise, fall through to the appropriate singular-field handler
- // below.
- containing_oneof = true;
- }
-
- if (is_map_field(f)) {
- zval* map = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
- if (!ZVAL_IS_NULL(map)) {
- putmap(map, f, sink, depth, is_json TSRMLS_CC);
- }
- } else if (upb_fielddef_isseq(f)) {
- zval* array = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
- if (!ZVAL_IS_NULL(array)) {
- putarray(array, f, sink, depth, is_json TSRMLS_CC);
- }
- } else if (upb_fielddef_isstring(f)) {
- zval* str = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
- if (containing_oneof || (is_json && is_wrapper_msg(desc->msgdef)) ||
- Z_STRLEN_P(str) > 0) {
- putstr(str, f, sink, is_json && is_wrapper_msg(desc->msgdef));
- }
- } else if (upb_fielddef_issubmsg(f)) {
- zval* submsg = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
- if (is_wrapper_msg(upb_fielddef_msgsubdef(f)) &&
- Z_TYPE_P(submsg) != IS_NULL && Z_TYPE_P(submsg) != IS_OBJECT) {
- putwrappervalue(submsg, f, sink, depth, is_json TSRMLS_CC);
- } else {
- putsubmsg(submsg, f, sink, depth, is_json 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 (containing_oneof || \
- (is_json && is_wrapper_msg(desc->msgdef)) || \
- value != default_value) { \
- upb_sink_put##upbtype(sink, sel, value); \
- } \
- } break;
-
- switch (upb_fielddef_type(f)) {
- T(UPB_TYPE_FLOAT, float, float, 0.0)
- T(UPB_TYPE_DOUBLE, double, double, 0.0)
- T(UPB_TYPE_BOOL, bool, uint8_t, 0)
- case UPB_TYPE_ENUM:
- T(UPB_TYPE_INT32, int32, int32_t, 0)
- T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
- T(UPB_TYPE_INT64, int64, int64_t, 0)
- T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
-
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES:
- case UPB_TYPE_MESSAGE:
- zend_error(E_ERROR, "Internal error.");
- }
-
-#undef T
- }
- }
-
- stringsink* unknown = DEREF(message_data(msg), 0, stringsink*);
- if (unknown != NULL) {
- upb_sink_putunknown(sink, unknown->ptr, unknown->len);
- }
-
- if (open_msg) {
- upb_sink_endmsg(sink, &status);
- }
-}
-
-static void putstr(zval* str, const upb_fielddef *f,
- upb_sink sink, bool force_default) {
- upb_sink subsink;
-
- if (ZVAL_IS_NULL(str)) return;
-
- PHP_PROTO_ASSERT(Z_TYPE_P(str) == IS_STRING);
-
- upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), Z_STRLEN_P(str),
- &subsink);
-
- // For oneof string field, we may get here with string length is zero.
- if (Z_STRLEN_P(str) > 0 || force_default) {
- // Ensure that the string has the correct encoding. We also check at
- // field-set time, but the user may have mutated the string object since
- // then.
- if (upb_fielddef_type(f) == UPB_TYPE_STRING &&
- !is_structurally_valid_utf8(Z_STRVAL_P(str), Z_STRLEN_P(str))) {
- zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
- return;
- }
- upb_sink_putstring(subsink, getsel(f, UPB_HANDLER_STRING), Z_STRVAL_P(str),
- Z_STRLEN_P(str), NULL);
- }
-
- upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
-}
-
-static void putrawstr(const char* str, int len, const upb_fielddef* f,
- upb_sink sink, bool force_default) {
- upb_sink subsink;
-
- if (len == 0 && !force_default) return;
-
- // Ensure that the string has the correct encoding. We also check at field-set
- // time, but the user may have mutated the string object since then.
- if (upb_fielddef_type(f) == UPB_TYPE_STRING &&
- !is_structurally_valid_utf8(str, len)) {
- zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
- return;
- }
-
- upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), len, &subsink);
- upb_sink_putstring(subsink, getsel(f, UPB_HANDLER_STRING), str, len, NULL);
- upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
-}
-
-static void putsubmsg(zval* submsg_php, const upb_fielddef* f, upb_sink sink,
- int depth, bool is_json TSRMLS_DC) {
- if (Z_TYPE_P(submsg_php) == IS_NULL) return;
-
- MessageHeader *submsg = UNBOX(MessageHeader, submsg_php);
- putrawsubmsg(submsg, f, sink, depth, is_json TSRMLS_CC);
-}
-
-static void putwrappervalue(
- zval* value, const upb_fielddef* f,
- upb_sink sink, int depth, bool is_json TSRMLS_DC) {
- upb_sink subsink;
- const upb_msgdef* msgdef = upb_fielddef_msgsubdef(f);
- const upb_fielddef* value_field = upb_msgdef_itof(msgdef, 1);
- upb_selector_t sel =
- getsel(value_field, upb_handlers_getprimitivehandlertype(value_field));
-
- upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
-
-#define T(upbtypeconst, upbtype, ctype, default_value) \
- case upbtypeconst: { \
- ctype value_raw; \
- native_slot_set(upb_fielddef_type(value_field), NULL, \
- &value_raw, value PHP_PROTO_TSRMLS_CC); \
- if ((is_json && is_wrapper_msg(msgdef)) || \
- value_raw != default_value) { \
- upb_sink_put##upbtype(subsink, sel, value_raw); \
- } \
- } break;
-
- switch (upb_fielddef_type(value_field)) {
- T(UPB_TYPE_FLOAT, float, float, 0.0)
- T(UPB_TYPE_DOUBLE, double, double, 0.0)
- T(UPB_TYPE_BOOL, bool, uint8_t, 0)
- T(UPB_TYPE_INT32, int32, int32_t, 0)
- T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
- T(UPB_TYPE_INT64, int64, int64_t, 0)
- T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES: {
- if ((is_json && is_wrapper_msg(msgdef)) ||
- Z_STRLEN_P(value) > 0) {
- putstr(value, value_field, subsink, is_json && is_wrapper_msg(msgdef));
- }
- break;
- }
- case UPB_TYPE_ENUM:
- case UPB_TYPE_MESSAGE:
- zend_error(E_ERROR, "Internal error.");
- }
-
-#undef T
-
- upb_sink_endsubmsg(sink, subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
-}
-
-static void putrawsubmsg(MessageHeader* submsg, const upb_fielddef* f,
- upb_sink sink, int depth, bool is_json TSRMLS_DC) {
- upb_sink subsink;
-
- const upb_msgdef* m = upb_fielddef_msgsubdef(f);
- DescriptorInternal* subdesc = get_msgdef_desc(m);
-
- upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
- putrawmsg(submsg, subdesc, subsink, depth + 1, is_json, true TSRMLS_CC);
- upb_sink_endsubmsg(sink, subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
-}
-
-static void putarray(zval* array, const upb_fielddef* f, upb_sink sink,
- int depth, bool is_json TSRMLS_DC) {
- upb_sink subsink;
- upb_fieldtype_t type = upb_fielddef_type(f);
- upb_selector_t sel = 0;
- int size, i;
-
- PHP_PROTO_ASSERT(array != NULL);
- RepeatedField* intern = UNBOX(RepeatedField, array);
- HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
- size = zend_hash_num_elements(ht);
- if (size == 0) return;
-
- upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
-
- if (upb_fielddef_isprimitive(f)) {
- sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
- }
-
- for (i = 0; i < size; i++) {
- void* memory = repeated_field_index_native(intern, i TSRMLS_CC);
- switch (type) {
-#define T(upbtypeconst, upbtype, ctype) \
- case upbtypeconst: \
- upb_sink_put##upbtype(subsink, sel, *((ctype*)memory)); \
- break;
-
- T(UPB_TYPE_FLOAT, float, float)
- T(UPB_TYPE_DOUBLE, double, double)
- T(UPB_TYPE_BOOL, bool, int8_t)
- case UPB_TYPE_ENUM:
- T(UPB_TYPE_INT32, int32, int32_t)
- T(UPB_TYPE_UINT32, uint32, uint32_t)
- T(UPB_TYPE_INT64, int64, int64_t)
- T(UPB_TYPE_UINT64, uint64, uint64_t)
-
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES: {
-#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,
- is_json && is_wrapper_msg(upb_fielddef_containingtype(f)));
- break;
- }
- case UPB_TYPE_MESSAGE: {
-#if PHP_MAJOR_VERSION < 7
- MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
-#else
- MessageHeader *submsg =
- (MessageHeader*)((char*)(Z_OBJ_P((zval*)memory)) -
- XtOffsetOf(MessageHeader, std));
-#endif
- putrawsubmsg(submsg, f, subsink, depth, is_json TSRMLS_CC);
- break;
- }
-
-#undef T
- }
- }
- upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
-}
-
-static const upb_handlers* msgdef_pb_serialize_handlers(DescriptorInternal* desc) {
- return upb_handlercache_get(desc->pool->pb_serialize_handler_cache,
- desc->msgdef);
-}
-
-static const upb_handlers* msgdef_json_serialize_handlers(
- DescriptorInternal* desc, bool preserve_proto_fieldnames) {
- if (preserve_proto_fieldnames) {
- return upb_handlercache_get(
- desc->pool->json_serialize_handler_preserve_cache, desc->msgdef);
- } else {
- return upb_handlercache_get(desc->pool->json_serialize_handler_cache,
- desc->msgdef);
- }
-}
-
-// -----------------------------------------------------------------------------
-// PHP encode/decode methods
-// -----------------------------------------------------------------------------
-
-void serialize_to_string(zval* val, zval* return_value TSRMLS_DC) {
- DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(val));
-
- stringsink sink;
- stringsink_init(&sink);
-
- {
- const upb_handlers* serialize_handlers = msgdef_pb_serialize_handlers(desc);
-
- stackenv se;
- upb_pb_encoder* encoder;
-
- stackenv_init(&se, "Error occurred during encoding: %s");
- encoder = upb_pb_encoder_create(se.arena, serialize_handlers, sink.sink);
-
- putmsg(val, desc, upb_pb_encoder_input(encoder), 0, false TSRMLS_CC);
-
- PHP_PROTO_RETVAL_STRINGL(sink.ptr, sink.len, 1);
-
- stackenv_uninit(&se);
- stringsink_uninit(&sink);
- }
-}
-
-PHP_METHOD(Message, serializeToString) {
- serialize_to_string(getThis(), return_value TSRMLS_CC);
-}
-
-void merge_from_string(const char* data, int data_len, DescriptorInternal* desc,
- MessageHeader* msg) {
- const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
- const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
- stackenv se;
- upb_sink sink;
- upb_pbdecoder* decoder;
- void* closure;
- stackenv_init(&se, "Error occurred during parsing: %s");
-
- if (is_wrapper_msg(desc->msgdef)) {
- wrapperfields_parseframe_t* frame =
- (wrapperfields_parseframe_t*)malloc(
- sizeof(wrapperfields_parseframe_t));
- frame->submsg = msg;
- frame->is_msg = true;
- closure = frame;
- } else {
- closure = msg;
- }
-
- upb_sink_reset(&sink, h, closure);
- decoder = upb_pbdecoder_create(se.arena, method, sink, &se.status);
- upb_bufsrc_putbuf(data, data_len, upb_pbdecoder_input(decoder));
-
- if (is_wrapper_msg(desc->msgdef)) {
- free((wrapperfields_parseframe_t*)closure);
- }
-
- stackenv_uninit(&se);
-}
-
-PHP_METHOD(Message, mergeFromString) {
- DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(getThis()));
- MessageHeader* msg = UNBOX(MessageHeader, getThis());
-
- char *data = NULL;
- PHP_PROTO_SIZE data_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) ==
- FAILURE) {
- return;
- }
-
- merge_from_string(data, data_len, desc, msg);
-}
-
-PHP_METHOD(Message, serializeToJsonString) {
- DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(getThis()));
-
- zend_bool preserve_proto_fieldnames = false;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b",
- &preserve_proto_fieldnames) == FAILURE) {
- return;
- }
-
- stringsink sink;
- stringsink_init(&sink);
-
- {
- const upb_handlers* serialize_handlers =
- msgdef_json_serialize_handlers(desc, preserve_proto_fieldnames);
- upb_json_printer* printer;
- stackenv se;
-
- stackenv_init(&se, "Error occurred during encoding: %s");
- printer = upb_json_printer_create(se.arena, serialize_handlers, sink.sink);
-
- putmsg(getThis(), desc, upb_json_printer_input(printer), 0, true TSRMLS_CC);
-
- PHP_PROTO_RETVAL_STRINGL(sink.ptr, sink.len, 1);
-
- stackenv_uninit(&se);
- stringsink_uninit(&sink);
- }
-}
-
-PHP_METHOD(Message, mergeFromJsonString) {
- DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(getThis()));
- MessageHeader* msg = UNBOX(MessageHeader, getThis());
-
- char *data = NULL;
- PHP_PROTO_SIZE data_len;
- zend_bool ignore_json_unknown = false;
-
- if (zend_parse_parameters(
- ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &data, &data_len,
- &ignore_json_unknown) ==
- FAILURE) {
- return;
- }
-
- // TODO(teboring): Check and respect string encoding. If not UTF-8, we need to
- // convert, because string handlers pass data directly to message string
- // fields.
-
- // TODO(teboring): Clear message.
-
- {
- const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc);
- stackenv se;
- upb_sink sink;
- upb_json_parser* parser;
- void* closure;
- stackenv_init(&se, "Error occurred during parsing: %s");
-
- if (is_wrapper_msg(desc->msgdef)) {
- wrapperfields_parseframe_t* frame =
- (wrapperfields_parseframe_t*)malloc(
- sizeof(wrapperfields_parseframe_t));
- frame->submsg = msg;
- frame->is_msg = true;
- closure = frame;
- } else {
- closure = msg;
- }
-
- upb_sink_reset(&sink, get_fill_handlers(desc), closure);
- parser = upb_json_parser_create(se.arena, method, generated_pool->symtab,
- sink, &se.status, ignore_json_unknown);
- upb_bufsrc_putbuf(data, data_len, upb_json_parser_input(parser));
-
- if (is_wrapper_msg(desc->msgdef)) {
- free((wrapperfields_parseframe_t*)closure);
- }
- stackenv_uninit(&se);
- }
-}
-
-// TODO(teboring): refactoring with putrawmsg
-static void discard_unknown_fields(MessageHeader* msg) {
- upb_msg_field_iter it;
-
- stringsink* unknown = DEREF(message_data(msg), 0, stringsink*);
- if (unknown != NULL) {
- stringsink_uninit(unknown);
- FREE(unknown);
- DEREF(message_data(msg), 0, stringsink*) = NULL;
- }
-
- // Recursively discard unknown fields of submessages.
- DescriptorInternal* desc = msg->descriptor;
- TSRMLS_FETCH();
- for (upb_msg_field_begin(&it, desc->msgdef);
- !upb_msg_field_done(&it);
- upb_msg_field_next(&it)) {
- upb_fielddef* f = upb_msg_iter_field(&it);
-
- if (upb_fielddef_containingoneof(f)) {
- uint32_t oneof_case_offset =
- desc->layout->fields[upb_fielddef_index(f)].case_offset;
- // 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)) {
- continue;
- }
- // Otherwise, fall through to the appropriate singular-field handler
- // below.
- }
-
- if (is_map_field(f)) {
- MapIter map_it;
- int len;
- const upb_fielddef* value_field;
-
- value_field = map_field_value(f);
- if (!upb_fielddef_issubmsg(value_field)) continue;
-
- zval* map_php = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
- if (ZVAL_IS_NULL(map_php)) continue;
-
- for (map_begin(map_php, &map_it TSRMLS_CC);
- !map_done(&map_it); map_next(&map_it)) {
- upb_value value = map_iter_value(&map_it, &len);
- const void* memory = raw_value(upb_value_memory(&value), value_field);
-#if PHP_MAJOR_VERSION < 7
- MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
-#else
- MessageHeader *submsg =
- (MessageHeader*)((char*)(Z_OBJ_P((zval*)memory)) -
- XtOffsetOf(MessageHeader, std));
-#endif
- discard_unknown_fields(submsg);
- }
- } else if (upb_fielddef_isseq(f)) {
- if (!upb_fielddef_issubmsg(f)) continue;
-
- zval* array_php = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
- if (ZVAL_IS_NULL(array_php)) continue;
-
- int size, i;
- RepeatedField* intern = UNBOX(RepeatedField, array_php);
- HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
- size = zend_hash_num_elements(ht);
- if (size == 0) continue;
-
- for (i = 0; i < size; i++) {
- void* memory = repeated_field_index_native(intern, i TSRMLS_CC);
-#if PHP_MAJOR_VERSION < 7
- MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
-#else
- MessageHeader *submsg =
- (MessageHeader*)((char*)(Z_OBJ_P((zval*)memory)) -
- XtOffsetOf(MessageHeader, std));
-#endif
- discard_unknown_fields(submsg);
- }
- } else if (upb_fielddef_issubmsg(f)) {
- zval* submsg_php = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
- if (Z_TYPE_P(submsg_php) == IS_NULL) continue;
- MessageHeader* submsg = UNBOX(MessageHeader, submsg_php);
- discard_unknown_fields(submsg);
- }
- }
-}
-
-PHP_METHOD(Message, discardUnknownFields) {
- MessageHeader* msg = UNBOX(MessageHeader, getThis());
- discard_unknown_fields(msg);
-}
diff --git a/php/ext/google/protobuf2/make-preload.php b/php/ext/google/protobuf/make-preload.php
similarity index 97%
rename from php/ext/google/protobuf2/make-preload.php
rename to php/ext/google/protobuf/make-preload.php
index c6043e2891..4b1ce7f676 100644
--- a/php/ext/google/protobuf2/make-preload.php
+++ b/php/ext/google/protobuf/make-preload.php
@@ -8,7 +8,7 @@ $handle = popen($cmd, 'r');
$filenames = explode("\n", stream_get_contents($handle));
array_pop($filenames); // empty string after last '\n'
$filenames[] = "Google/Protobuf/DescriptorPool.php";
-$output = "../ext/google/protobuf2/bundled_php.c";
+$output = "../ext/google/protobuf/bundled_php.c";
function stripSuffix($str, $suffix) {
return substr($str, 0, strlen($str) - strlen($suffix));
diff --git a/php/ext/google/protobuf/map.c b/php/ext/google/protobuf/map.c
index 2dded9224e..0217c6491e 100644
--- a/php/ext/google/protobuf/map.c
+++ b/php/ext/google/protobuf/map.c
@@ -28,390 +28,187 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include
+#include "map.h"
+
#include
#include
-#include "protobuf.h"
-#include "utf8.h"
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
- ZEND_ARG_INFO(0, index)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2)
- ZEND_ARG_INFO(0, index)
- ZEND_ARG_INFO(0, newval)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
-ZEND_END_ARG_INFO()
+#include
-// Utilities
+#include "arena.h"
+#include "convert.h"
+#include "php-upb.h"
+#include "protobuf.h"
-void* upb_value_memory(upb_value* v) {
- return (void*)(&v->val);
-}
+static void MapFieldIter_make(zval *val, zval *map_field);
// -----------------------------------------------------------------------------
-// Basic map operations on top of upb's strtable.
-//
-// Note that we roll our own `Map` container here because, as for
-// `RepeatedField`, we want a strongly-typed container. This is so that any user
-// errors due to incorrect map key or value types are raised as close as
-// possible to the error site, rather than at some deferred point (e.g.,
-// serialization).
-//
-// We build our `Map` on top of upb_strtable so that we're able to take
-// advantage of the native_slot storage abstraction, as RepeatedField does.
-// (This is not quite a perfect mapping -- see the key conversions below -- but
-// gives us full support and error-checking for all value types for free.)
+// MapField
// -----------------------------------------------------------------------------
-// Map values are stored using the native_slot abstraction (as with repeated
-// field values), but keys are a bit special. Since we use a strtable, we need
-// to store keys as sequences of bytes such that equality of those bytes maps
-// one-to-one to equality of keys. We store strings directly (i.e., they map to
-// their own bytes) and integers as native integers (using the native_slot
-// abstraction).
-
-// Note that there is another tradeoff here in keeping string keys as native
-// strings rather than PHP strings: traversing the Map requires conversion to
-// PHP string values on every traversal, potentially creating more garbage. We
-// should consider ways to cache a PHP version of the key if this becomes an
-// issue later.
-
-// Forms a key to use with the underlying strtable from a PHP key value. |buf|
-// must point to TABLE_KEY_BUF_LENGTH bytes of temporary space, used to
-// construct a key byte sequence if needed. |out_key| and |out_length| provide
-// the resulting key data/length.
-#define TABLE_KEY_BUF_LENGTH 8 // sizeof(uint64_t)
-static bool table_key(Map* self, zval* key,
- char* buf,
- const char** out_key,
- size_t* out_length TSRMLS_DC) {
- switch (self->key_type) {
- case UPB_TYPE_STRING:
- if (!protobuf_convert_to_string(key)) {
- return false;
- }
- if (!is_structurally_valid_utf8(Z_STRVAL_P(key), Z_STRLEN_P(key))) {
- zend_error(E_USER_ERROR, "Given key is not UTF8 encoded.");
- return false;
- }
- *out_key = Z_STRVAL_P(key);
- *out_length = Z_STRLEN_P(key);
- break;
-
-#define CASE_TYPE(upb_type, type, c_type, php_type) \
- case UPB_TYPE_##upb_type: { \
- c_type type##_value; \
- if (!protobuf_convert_to_##type(key, &type##_value)) { \
- return false; \
- } \
- native_slot_set_by_array(self->key_type, NULL, buf, key TSRMLS_CC); \
- *out_key = buf; \
- *out_length = native_slot_size(self->key_type); \
- break; \
+typedef struct {
+ zend_object std;
+ zval arena;
+ upb_map *map;
+ upb_fieldtype_t key_type;
+ upb_fieldtype_t val_type;
+ const Descriptor* desc; // When values are messages.
+} MapField;
+
+zend_class_entry *MapField_class_entry;
+static zend_object_handlers MapField_object_handlers;
+
+// PHP Object Handlers /////////////////////////////////////////////////////////
+
+/**
+ * MapField_create()
+ *
+ * PHP class entry function to allocate and initialize a new MapField
+ * object.
+ */
+static zend_object* MapField_create(zend_class_entry *class_type) {
+ MapField *intern = emalloc(sizeof(MapField));
+ zend_object_std_init(&intern->std, class_type);
+ intern->std.handlers = &MapField_object_handlers;
+ Arena_Init(&intern->arena);
+ intern->map = NULL;
+ // Skip object_properties_init(), we don't allow derived classes.
+ return &intern->std;
+}
+
+/**
+ * MapField_dtor()
+ *
+ * Object handler to destroy a MapField. This releases all resources
+ * associated with the message. Note that it is possible to access a destroyed
+ * object from PHP in rare cases.
+ */
+static void MapField_destructor(zend_object* obj) {
+ MapField* intern = (MapField*)obj;
+ ObjCache_Delete(intern->map);
+ zval_ptr_dtor(&intern->arena);
+ zend_object_std_dtor(&intern->std);
+}
+
+static zval *Map_GetPropertyPtrPtr(zval *object, zval *member, int type,
+ void **cache_slot) {
+ return NULL; // We don't offer direct references to our properties.
+}
+
+static HashTable *map_get_properties(zval *object TSRMLS_DC) {
+ return NULL; // We do not have a properties table.
+}
+
+// C Functions from map.h //////////////////////////////////////////////////////
+
+// These are documented in the header file.
+
+void MapField_GetPhpWrapper(zval *val, upb_map *map, const upb_fielddef *f,
+ zval *arena) {
+ if (!map) {
+ ZVAL_NULL(val);
+ return;
}
- CASE_TYPE(BOOL, bool, int8_t, BOOL)
- CASE_TYPE(INT32, int32, int32_t, LONG)
- CASE_TYPE(INT64, int64, int64_t, LONG)
- CASE_TYPE(UINT32, uint32, uint32_t, LONG)
- CASE_TYPE(UINT64, uint64, uint64_t, LONG)
-#undef CASE_TYPE
-
- default:
- // Map constructor should not allow a Map with another key type to be
- // constructed.
- assert(false);
- break;
+ if (!ObjCache_Get(map, val)) {
+ const upb_msgdef *ent = upb_fielddef_msgsubdef(f);
+ const upb_fielddef *key_f = upb_msgdef_itof(ent, 1);
+ const upb_fielddef *val_f = upb_msgdef_itof(ent, 2);
+ MapField *intern = emalloc(sizeof(MapField));
+ zend_object_std_init(&intern->std, MapField_class_entry);
+ intern->std.handlers = &MapField_object_handlers;
+ ZVAL_COPY(&intern->arena, arena);
+ intern->map = map;
+ intern->key_type = upb_fielddef_type(key_f);
+ intern->val_type = upb_fielddef_type(val_f);
+ intern->desc = Descriptor_GetFromFieldDef(val_f);
+ // Skip object_properties_init(), we don't allow derived classes.
+ ObjCache_Add(intern->map, &intern->std);
+ ZVAL_OBJ(val, &intern->std);
}
-
- return true;
-}
-
-// -----------------------------------------------------------------------------
-// MapField methods
-// -----------------------------------------------------------------------------
-
-static zend_function_entry map_field_methods[] = {
- PHP_ME(MapField, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(MapField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
- PHP_ME(MapField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC)
- PHP_ME(MapField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC)
- PHP_ME(MapField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC)
- PHP_ME(MapField, count, arginfo_void, ZEND_ACC_PUBLIC)
- PHP_ME(MapField, getIterator, arginfo_void, ZEND_ACC_PUBLIC)
- ZEND_FE_END
-};
-
-// Forward declare static functions.
-
-static void map_field_write_dimension(zval *object, zval *key,
- zval *value TSRMLS_DC);
-
-// -----------------------------------------------------------------------------
-// MapField creation/destruction
-// -----------------------------------------------------------------------------
-
-zend_class_entry* map_field_type;
-zend_class_entry* map_field_iter_type;
-
-zend_object_handlers* map_field_handlers;
-zend_object_handlers* map_field_iter_handlers;
-
-static void map_begin_internal(Map *map, MapIter *iter) {
- iter->self = map;
- upb_strtable_begin(&iter->it, &map->table);
-}
-
-static HashTable *map_field_get_gc(zval *object, CACHED_VALUE **table,
- int *n TSRMLS_DC) {
- // TODO(teboring): Unfortunately, zend engine does not support garbage
- // collection for custom array. We have to use zend engine's native array
- // instead.
- *table = NULL;
- *n = 0;
- return NULL;
}
-// 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);
-}
+upb_map *MapField_GetUpbMap(zval *val, const upb_fielddef *f, upb_arena *arena) {
+ const upb_msgdef *ent = upb_fielddef_msgsubdef(f);
+ const upb_fielddef *key_f = upb_msgdef_itof(ent, 1);
+ const upb_fielddef *val_f = upb_msgdef_itof(ent, 2);
+ upb_fieldtype_t key_type = upb_fielddef_type(key_f);
+ upb_fieldtype_t val_type = upb_fielddef_type(val_f);
+ const Descriptor *desc = Descriptor_GetFromFieldDef(val_f);
-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;
- GC_DELREF(object);
- if(GC_REFCOUNT(object) == 0) {
- zend_objects_store_del(object);
- }
-}
-#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) {
- 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);
- break;
- default:
- break;
- }
-}
-upb_strtable_uninit(&intern->table);
-PHP_PROTO_OBJECT_FREE_END
-
-PHP_PROTO_OBJECT_EMPTY_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, 3, spl_ce_ArrayAccess,
- zend_ce_aggregate, 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_ensure_created(const upb_fielddef *field,
- CACHED_VALUE *map_field PHP_PROTO_TSRMLS_DC) {
- if (ZVAL_IS_NULL(CACHED_PTR_TO_ZVAL_PTR(map_field))) {
- zval_ptr_dtor(map_field);
-#if PHP_MAJOR_VERSION < 7
- MAKE_STD_ZVAL(CACHED_PTR_TO_ZVAL_PTR(map_field));
-#endif
- map_field_create_with_field(map_field_type, field,
- map_field PHP_PROTO_TSRMLS_CC);
+ if (Z_ISREF_P(val)) {
+ ZVAL_DEREF(val);
}
-}
-void map_field_create_with_field(const zend_class_entry *ce,
- const upb_fielddef *field,
- CACHED_VALUE *map_field PHP_PROTO_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);
-}
+ if (Z_TYPE_P(val) == IS_ARRAY) {
+ upb_map *map = upb_map_new(arena, key_type, val_type);
+ HashTable *table = HASH_OF(val);
+ HashPosition pos;
-void map_field_create_with_type(const 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));
- intern->key_type = key_type;
- intern->value_type = value_type;
- intern->msg_ce = msg_ce;
-}
+ zend_hash_internal_pointer_reset_ex(table, &pos);
-// -----------------------------------------------------------------------------
-// MapField Handlers
-// -----------------------------------------------------------------------------
+ while (true) {
+ zval php_key;
+ zval *php_val;
+ upb_msgval upb_key;
+ upb_msgval upb_val;
-static bool map_field_read_dimension(zval *object, zval *key, int type,
- CACHED_VALUE *retval TSRMLS_DC) {
- Map *intern = UNBOX(Map, object);
-
- char keybuf[TABLE_KEY_BUF_LENGTH];
- const char* keyval = NULL;
- size_t length = 0;
- upb_value v;
-#ifndef NDEBUG
- v.ctype = UPB_CTYPE_UINT64;
-#endif
- if (!table_key(intern, key, keybuf, &keyval, &length TSRMLS_CC)) {
- return false;
- }
+ zend_hash_get_current_key_zval_ex(table, &php_key, &pos);
+ php_val = zend_hash_get_current_data_ex(table, &pos);
- if (upb_strtable_lookup2(&intern->table, keyval, length, &v)) {
- void* mem = upb_value_memory(&v);
- native_slot_get_by_map_value(intern->value_type, mem, retval TSRMLS_CC);
- return true;
- } else {
- zend_error(E_USER_ERROR, "Given key doesn't exist.");
- return false;
- }
-}
+ if (!php_val) return map;
-static void map_index_unset(Map *intern, const char* keyval, int length) {
- upb_value old_value;
- if (upb_strtable_remove2(&intern->table, keyval, length, &old_value)) {
- switch (intern->value_type) {
- case UPB_TYPE_MESSAGE: {
-#if PHP_MAJOR_VERSION < 7
- zval_ptr_dtor(upb_value_memory(&old_value));
-#else
- zend_object* object = *(zend_object**)upb_value_memory(&old_value);
- GC_DELREF(object);
- if(GC_REFCOUNT(object) == 0) {
- zend_objects_store_del(object);
- }
-#endif
- break;
- }
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES: {
-#if PHP_MAJOR_VERSION < 7
- zval_ptr_dtor(upb_value_memory(&old_value));
-#else
- zend_string* object = *(zend_string**)upb_value_memory(&old_value);
- zend_string_release(object);
-#endif
- break;
+ if (!Convert_PhpToUpb(&php_key, &upb_key, key_type, NULL, arena) ||
+ !Convert_PhpToUpbAutoWrap(php_val, &upb_val, val_type, desc, arena)) {
+ return NULL;
}
- default:
- break;
- }
- }
-}
-
-bool map_index_set(Map *intern, const char* keyval, int length, upb_value v) {
- // Replace any existing value by issuing a 'remove' operation first.
- map_index_unset(intern, keyval, length);
-
- if (!upb_strtable_insert2(&intern->table, keyval, length, v)) {
- zend_error(E_USER_ERROR, "Could not insert into table");
- return false;
- }
-
- return true;
-}
-
-static void map_field_write_dimension(zval *object, zval *key,
- zval *value TSRMLS_DC) {
- Map *intern = UNBOX(Map, object);
-
- char keybuf[TABLE_KEY_BUF_LENGTH];
- const char* keyval = NULL;
- size_t length = 0;
- upb_value v;
- void* mem;
- if (!table_key(intern, key, keybuf, &keyval, &length TSRMLS_CC)) {
- return;
- }
-
- mem = upb_value_memory(&v);
- memset(mem, 0, native_slot_size(intern->value_type));
- if (!native_slot_set_by_map(intern->value_type, intern->msg_ce, mem,
- value TSRMLS_CC)) {
- return;
- }
-#ifndef NDEBUG
- v.ctype = UPB_CTYPE_UINT64;
-#endif
-
- map_index_set(intern, keyval, length, v);
-}
-static bool map_field_unset_dimension(zval *object, zval *key TSRMLS_DC) {
- Map *intern = UNBOX(Map, object);
+ upb_map_set(map, upb_key, upb_val, arena);
+ zend_hash_move_forward_ex(table, &pos);
+ zval_dtor(&php_key);
+ }
+ } else if (Z_TYPE_P(val) == IS_OBJECT &&
+ Z_OBJCE_P(val) == MapField_class_entry) {
+ MapField *intern = (MapField*)Z_OBJ_P(val);
+
+ if (intern->key_type != key_type || intern->val_type != val_type ||
+ intern->desc != desc) {
+ php_error_docref(NULL, E_USER_ERROR, "Wrong type for this map field.");
+ return NULL;
+ }
- char keybuf[TABLE_KEY_BUF_LENGTH];
- const char* keyval = NULL;
- size_t length = 0;
- if (!table_key(intern, key, keybuf, &keyval, &length TSRMLS_CC)) {
- return false;
+ upb_arena_fuse(arena, Arena_Get(&intern->arena));
+ return intern->map;
+ } else {
+ php_error_docref(NULL, E_USER_ERROR, "Must be a map");
+ return NULL;
}
-#ifndef NDEBUG
- v.ctype = UPB_CTYPE_UINT64;
-#endif
-
- map_index_unset(intern, keyval, length);
-
- return true;
}
-// -----------------------------------------------------------------------------
-// PHP MapField Methods
-// -----------------------------------------------------------------------------
+// MapField PHP methods ////////////////////////////////////////////////////////
+/**
+ * MapField::__construct()
+ *
+ * Constructs an instance of MapField.
+ * @param long Key type.
+ * @param long Value type.
+ * @param string Message/Enum class (message/enum value types only).
+ */
PHP_METHOD(MapField, __construct) {
- long key_type, value_type;
+ MapField *intern = (MapField*)Z_OBJ_P(getThis());
+ upb_arena *arena = Arena_Get(&intern->arena);
+ zend_long key_type, val_type;
zend_class_entry* klass = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|C", &key_type,
- &value_type, &klass) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|C", &key_type, &val_type,
+ &klass) != SUCCESS) {
return;
}
- Map *intern = UNBOX(Map, getThis());
- intern->key_type = to_fieldtype(key_type);
- intern->value_type = to_fieldtype(value_type);
- intern->msg_ce = klass;
+ intern->key_type = pbphp_dtype_to_type(key_type);
+ intern->val_type = pbphp_dtype_to_type(val_type);
+ intern->desc = Descriptor_GetFromClassEntry(klass);
// Check that the key type is an allowed type.
switch (intern->key_type) {
@@ -427,107 +224,319 @@ PHP_METHOD(MapField, __construct) {
default:
zend_error(E_USER_ERROR, "Invalid key type for map.");
}
-}
+ if (intern->val_type == UPB_TYPE_MESSAGE && klass == NULL) {
+ php_error_docref(NULL, E_USER_ERROR,
+ "Message/enum type must have concrete class.");
+ return;
+ }
+
+ intern->map = upb_map_new(arena, intern->key_type, intern->val_type);
+ ObjCache_Add(intern->map, &intern->std);
+}
+
+/**
+ * MapField::offsetExists()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ * isset($map[$idx]);
+ * empty($map[$idx]);
+ *
+ * @param long The index to be checked.
+ * @return bool True if the element at the given index exists.
+ */
PHP_METHOD(MapField, offsetExists) {
+ MapField *intern = (MapField*)Z_OBJ_P(getThis());
zval *key;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) ==
- FAILURE) {
+ upb_msgval upb_key;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
+ !Convert_PhpToUpb(key, &upb_key, intern->key_type, intern->desc, NULL)) {
return;
}
- Map *intern = UNBOX(Map, getThis());
-
- char keybuf[TABLE_KEY_BUF_LENGTH];
- const char* keyval = NULL;
- size_t length = 0;
- upb_value v;
-#ifndef NDEBUG
- v.ctype = UPB_CTYPE_UINT64;
-#endif
- if (!table_key(intern, key, keybuf, &keyval, &length TSRMLS_CC)) {
- RETURN_BOOL(false);
- }
+ RETURN_BOOL(upb_map_get(intern->map, upb_key, NULL));
+}
+
+/**
+ * MapField::offsetGet()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ * $x = $map[$idx];
+ *
+ * @param long The index of the element to be fetched.
+ * @return object The stored element at given index.
+ * @exception Invalid type for index.
+ * @exception Non-existing index.
+ */
+PHP_METHOD(MapField, offsetGet) {
+ MapField *intern = (MapField*)Z_OBJ_P(getThis());
+ zval *key;
+ zval ret;
+ upb_msgval upb_key, upb_val;
- RETURN_BOOL(upb_strtable_lookup2(&intern->table, keyval, length, &v));
-}
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
+ !Convert_PhpToUpb(key, &upb_key, intern->key_type, intern->desc, NULL)) {
+ return;
+ }
-PHP_METHOD(MapField, offsetGet) {
- zval *index;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) ==
- FAILURE) {
+ if (!upb_map_get(intern->map, upb_key, &upb_val)) {
+ zend_error(E_USER_ERROR, "Given key doesn't exist.");
return;
}
- map_field_read_dimension(getThis(), index, BP_VAR_R,
- ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
-}
+ Convert_UpbToPhp(upb_val, &ret, intern->val_type, intern->desc, &intern->arena);
+ RETURN_ZVAL(&ret, 0, 1);
+}
+
+/**
+ * MapField::offsetSet()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ * $map[$idx] = $x;
+ *
+ * @param long The index of the element to be assigned.
+ * @param object The element to be assigned.
+ * @exception Invalid type for index.
+ * @exception Non-existing index.
+ * @exception Incorrect type of the element.
+ */
PHP_METHOD(MapField, offsetSet) {
- zval *index, *value;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &index, &value) ==
- FAILURE) {
+ MapField *intern = (MapField*)Z_OBJ_P(getThis());
+ upb_arena *arena = Arena_Get(&intern->arena);
+ zval *key, *val;
+ upb_msgval upb_key, upb_val;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &key, &val) != SUCCESS ||
+ !Convert_PhpToUpb(key, &upb_key, intern->key_type, NULL, NULL) ||
+ !Convert_PhpToUpb(val, &upb_val, intern->val_type, intern->desc, arena)) {
return;
}
- map_field_write_dimension(getThis(), index, value TSRMLS_CC);
+
+ upb_map_set(intern->map, upb_key, upb_val, arena);
}
+/**
+ * MapField::offsetUnset()
+ *
+ * Implements the ArrayAccess interface. Invoked when PHP code calls:
+ *
+ * unset($map[$idx]);
+ *
+ * @param long The index of the element to be removed.
+ * @exception Invalid type for index.
+ * @exception The element to be removed is not at the end of the MapField.
+ */
PHP_METHOD(MapField, offsetUnset) {
- zval *index;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) ==
- FAILURE) {
+ MapField *intern = (MapField*)Z_OBJ_P(getThis());
+ zval *key;
+ upb_msgval upb_key;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
+ !Convert_PhpToUpb(key, &upb_key, intern->key_type, NULL, NULL)) {
return;
}
- map_field_unset_dimension(getThis(), index TSRMLS_CC);
+
+ upb_map_delete(intern->map, upb_key);
}
+/**
+ * MapField::count()
+ *
+ * Implements the Countable interface. Invoked when PHP code calls:
+ *
+ * $len = count($map);
+ * Return the number of stored elements.
+ * This will also be called for: count($map)
+ * @return long The number of stored elements.
+ */
PHP_METHOD(MapField, count) {
- Map *intern = UNBOX(Map, getThis());
+ MapField *intern = (MapField*)Z_OBJ_P(getThis());
if (zend_parse_parameters_none() == FAILURE) {
return;
}
- RETURN_LONG(upb_strtable_count(&intern->table));
+ RETURN_LONG(upb_map_size(intern->map));
}
+/**
+ * MapField::getIterator()
+ *
+ * Implements the IteratorAggregate interface. Invoked when PHP code calls:
+ *
+ * foreach ($arr) {}
+ *
+ * @return object Beginning iterator.
+ */
PHP_METHOD(MapField, getIterator) {
- CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(return_value,
- map_field_iter_type);
-
- MapIter *iter = UNBOX(MapIter, return_value);
- map_begin(getThis(), iter TSRMLS_CC);
+ zval ret;
+ MapFieldIter_make(&ret, getThis());
+ RETURN_ZVAL(&ret, 0, 1);
}
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
+ ZEND_ARG_INFO(0, index)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, newval)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
+ZEND_END_ARG_INFO()
+
+static zend_function_entry MapField_methods[] = {
+ PHP_ME(MapField, __construct, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(MapField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC)
+ PHP_ME(MapField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC)
+ PHP_ME(MapField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC)
+ PHP_ME(MapField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC)
+ PHP_ME(MapField, count, arginfo_void, ZEND_ACC_PUBLIC)
+ PHP_ME(MapField, getIterator, arginfo_void, ZEND_ACC_PUBLIC)
+ ZEND_FE_END
+};
+
// -----------------------------------------------------------------------------
-// Map Iterator
+// MapFieldIter
// -----------------------------------------------------------------------------
-void map_begin(zval *map_php, MapIter *iter TSRMLS_DC) {
- Map *self = UNBOX(Map, map_php);
- map_begin_internal(self, iter);
+typedef struct {
+ zend_object std;
+ zval map_field;
+ size_t position;
+} MapFieldIter;
+
+zend_class_entry *MapFieldIter_class_entry;
+static zend_object_handlers MapFieldIter_object_handlers;
+
+/**
+ * MapFieldIter_create()
+ *
+ * PHP class entry function to allocate and initialize a new MapFieldIter
+ * object.
+ */
+zend_object* MapFieldIter_create(zend_class_entry *class_type) {
+ MapFieldIter *intern = emalloc(sizeof(MapFieldIter));
+ zend_object_std_init(&intern->std, class_type);
+ intern->std.handlers = &MapFieldIter_object_handlers;
+ ZVAL_NULL(&intern->map_field);
+ intern->position = 0;
+ // Skip object_properties_init(), we don't allow derived classes.
+ return &intern->std;
+}
+
+/**
+ * MapFieldIter_dtor()
+ *
+ * Object handler to destroy a MapFieldIter. This releases all resources
+ * associated with the message. Note that it is possible to access a destroyed
+ * object from PHP in rare cases.
+ */
+static void map_field_iter_dtor(zend_object* obj) {
+ MapFieldIter* intern = (MapFieldIter*)obj;
+ zval_ptr_dtor(&intern->map_field);
+ zend_object_std_dtor(&intern->std);
+}
+
+/**
+ * MapFieldIter_make()
+ *
+ * Function to create a MapFieldIter directly from C.
+ */
+static void MapFieldIter_make(zval *val, zval *map_field) {
+ MapFieldIter *iter;
+ ZVAL_OBJ(val,
+ MapFieldIter_class_entry->create_object(MapFieldIter_class_entry));
+ iter = (MapFieldIter*)Z_OBJ_P(val);
+ ZVAL_COPY(&iter->map_field, map_field);
}
-void map_next(MapIter *iter) {
- upb_strtable_next(&iter->it);
-}
+// -----------------------------------------------------------------------------
+// PHP MapFieldIter Methods
+// -----------------------------------------------------------------------------
-bool map_done(MapIter *iter) {
- return upb_strtable_done(&iter->it);
+/*
+ * When a user writes:
+ *
+ * foreach($arr as $key => $val) {}
+ *
+ * PHP translates this into:
+ *
+ * $iter = $arr->getIterator();
+ * for ($iter->rewind(); $iter->valid(); $iter->next()) {
+ * $key = $iter->key();
+ * $val = $iter->current();
+ * }
+ */
+
+/**
+ * MapFieldIter::rewind()
+ *
+ * Implements the Iterator interface. Sets the iterator to the first element.
+ */
+PHP_METHOD(MapFieldIter, rewind) {
+ MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
+ MapField *map_field = (MapField*)Z_OBJ_P(&intern->map_field);
+ intern->position = UPB_MAP_BEGIN;
+ upb_mapiter_next(map_field->map, &intern->position);
}
-const char *map_iter_key(MapIter *iter, int *len) {
- *len = upb_strtable_iter_key(&iter->it).size;
- return upb_strtable_iter_key(&iter->it).data;
+/**
+ * MapFieldIter::current()
+ *
+ * Implements the Iterator interface. Returns the current value.
+ */
+PHP_METHOD(MapFieldIter, current) {
+ MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
+ MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
+ upb_msgval upb_val = upb_mapiter_value(field->map, intern->position);
+ zval ret;
+ Convert_UpbToPhp(upb_val, &ret, field->val_type, field->desc, &field->arena);
+ RETURN_ZVAL(&ret, 0, 1);
+}
+
+/**
+ * MapFieldIter::key()
+ *
+ * Implements the Iterator interface. Returns the current key.
+ */
+PHP_METHOD(MapFieldIter, key) {
+ MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
+ MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
+ upb_msgval upb_key = upb_mapiter_key(field->map, intern->position);
+ zval ret;
+ Convert_UpbToPhp(upb_key, &ret, field->key_type, NULL, NULL);
+ RETURN_ZVAL(&ret, 0, 1);
+}
+
+/**
+ * MapFieldIter::next()
+ *
+ * Implements the Iterator interface. Advances to the next element.
+ */
+PHP_METHOD(MapFieldIter, next) {
+ MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
+ MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
+ upb_mapiter_next(field->map, &intern->position);
}
-upb_value map_iter_value(MapIter *iter, int *len) {
- *len = native_slot_size(iter->self->value_type);
- return upb_strtable_iter_value(&iter->it);
+/**
+ * MapFieldIter::valid()
+ *
+ * Implements the Iterator interface. Returns true if this is a valid element.
+ */
+PHP_METHOD(MapFieldIter, valid) {
+ MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
+ MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
+ bool done = upb_mapiter_done(field->map, intern->position);
+ RETURN_BOOL(!done);
}
-// -----------------------------------------------------------------------------
-// MapFieldIter methods
-// -----------------------------------------------------------------------------
static zend_function_entry map_field_iter_methods[] = {
PHP_ME(MapFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC)
PHP_ME(MapFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC)
@@ -538,65 +547,44 @@ static zend_function_entry map_field_iter_methods[] = {
};
// -----------------------------------------------------------------------------
-// MapFieldIter creation/destruction
+// Module init.
// -----------------------------------------------------------------------------
-// Define object free method.
-PHP_PROTO_OBJECT_EMPTY_FREE_START(MapIter, map_field_iter)
-PHP_PROTO_OBJECT_FREE_END
-
-PHP_PROTO_OBJECT_EMPTY_DTOR_START(MapIter, map_field_iter)
-PHP_PROTO_OBJECT_DTOR_END
-
-// Define object create method.
-PHP_PROTO_OBJECT_CREATE_START(MapIter, map_field_iter)
-intern->self = NULL;
-PHP_PROTO_OBJECT_CREATE_END(MapIter, map_field_iter)
-
-// Init class entry.
-PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\MapFieldIter",
- MapIter, map_field_iter)
-zend_class_implements(map_field_iter_type TSRMLS_CC, 1, zend_ce_iterator);
-PHP_PROTO_INIT_CLASS_END
-
-// -----------------------------------------------------------------------------
-// PHP MapFieldIter Methods
-// -----------------------------------------------------------------------------
-
-PHP_METHOD(MapFieldIter, rewind) {
- MapIter *intern = UNBOX(MapIter, getThis());
- map_begin_internal(intern->self, intern);
-}
-
-PHP_METHOD(MapFieldIter, current) {
- MapIter *intern = UNBOX(MapIter, getThis());
- Map *map_field = intern->self;
-
- int value_length = 0;
- upb_value value = map_iter_value(intern, &value_length);
-
- void* mem = upb_value_memory(&value);
- native_slot_get_by_map_value(map_field->value_type, mem,
- ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
-}
-
-PHP_METHOD(MapFieldIter, key) {
- MapIter *intern = UNBOX(MapIter, getThis());
- Map *map_field = intern->self;
-
- int key_length = 0;
- const char* key = map_iter_key(intern, &key_length);
-
- native_slot_get_by_map_key(map_field->key_type, key, key_length,
- ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
-}
-
-PHP_METHOD(MapFieldIter, next) {
- MapIter *intern = UNBOX(MapIter, getThis());
- map_next(intern);
-}
-
-PHP_METHOD(MapFieldIter, valid) {
- MapIter *intern = UNBOX(MapIter, getThis());
- RETURN_BOOL(!map_done(intern));
+/**
+ * Map_ModuleInit()
+ *
+ * Called when the C extension is loaded to register all types.
+ */
+
+void Map_ModuleInit() {
+ zend_class_entry tmp_ce;
+ zend_object_handlers *h;
+
+ INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapField",
+ MapField_methods);
+
+ MapField_class_entry = zend_register_internal_class(&tmp_ce);
+ zend_class_implements(MapField_class_entry, 3, spl_ce_ArrayAccess,
+ zend_ce_aggregate, spl_ce_Countable);
+ MapField_class_entry->ce_flags |= ZEND_ACC_FINAL;
+ MapField_class_entry->create_object = MapField_create;
+
+ h = &MapField_object_handlers;
+ memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+ h->dtor_obj = MapField_destructor;
+ h->get_properties = map_get_properties;
+ h->get_property_ptr_ptr = Map_GetPropertyPtrPtr;
+
+ INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapFieldIter",
+ map_field_iter_methods);
+
+ MapFieldIter_class_entry = zend_register_internal_class(&tmp_ce);
+ zend_class_implements(MapFieldIter_class_entry, 1, zend_ce_iterator);
+ MapFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL;
+ MapFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL;
+ MapFieldIter_class_entry->create_object = MapFieldIter_create;
+
+ h = &MapFieldIter_object_handlers;
+ memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+ h->dtor_obj = map_field_iter_dtor;
}
diff --git a/php/ext/google/protobuf2/map.h b/php/ext/google/protobuf/map.h
similarity index 100%
rename from php/ext/google/protobuf2/map.h
rename to php/ext/google/protobuf/map.h
diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c
index 036633781d..20dd37a76e 100644
--- a/php/ext/google/protobuf/message.c
+++ b/php/ext/google/protobuf/message.c
@@ -28,2707 +28,814 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include "message.h"
+
+#include
#include
-#include
#include
-#include
-#if PHP_MAJOR_VERSION < 7
-#include
-#else
-#include
-#endif
+// This is not self-contained: it must be after other Zend includes.
+#include
+#include "arena.h"
+#include "array.h"
+#include "convert.h"
+#include "def.h"
+#include "map.h"
+#include "php-upb.h"
#include "protobuf.h"
-#include "utf8.h"
-
-zend_class_entry* message_type;
-zend_object_handlers* message_handlers;
-static const char TYPE_URL_PREFIX[] = "type.googleapis.com/";
-static void hex_to_binary(const char* hex, char** binary, int* binary_len);
-
-static zend_function_entry message_methods[] = {
- PHP_ME(Message, clear, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Message, discardUnknownFields, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Message, serializeToString, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Message, mergeFromString, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Message, serializeToJsonString, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Message, mergeFromJsonString, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Message, mergeFrom, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Message, readWrapperValue, NULL, ZEND_ACC_PROTECTED)
- PHP_ME(Message, writeWrapperValue, NULL, ZEND_ACC_PROTECTED)
- PHP_ME(Message, readOneof, NULL, ZEND_ACC_PROTECTED)
- PHP_ME(Message, writeOneof, NULL, ZEND_ACC_PROTECTED)
- PHP_ME(Message, whichOneof, NULL, ZEND_ACC_PROTECTED)
- PHP_ME(Message, __construct, NULL, ZEND_ACC_PROTECTED)
- {NULL, NULL, NULL}
-};
-
-// 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);
-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
-#if PHP_VERSION_ID < 70400
-static void message_set_property(zval* object, zval* member, zval* value,
- void** cache_slot);
-#else
-static zval* message_set_property(zval* object, zval* member, zval* value,
- void** cache_slot);
-#endif
-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
-static HashTable* message_get_properties(zval* object TSRMLS_DC);
// -----------------------------------------------------------------------------
-// PHP Message Handlers
-// -----------------------------------------------------------------------------
-
-// Define object free method.
-PHP_PROTO_OBJECT_FREE_START(MessageHeader, message)
- if (intern->data) {
- if (*(void**)intern->data != NULL) {
- stringsink_uninit_opaque(*(void**)intern->data);
- FREE(*(void**)intern->data);
- }
- FREE(intern->data);
- }
-PHP_PROTO_OBJECT_FREE_END
-
-PHP_PROTO_OBJECT_EMPTY_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 descriptor of this class
-// hasn't been added to descriptor 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->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
-
-static void message_set_property_internal(zval* object, zval* member,
- zval* value TSRMLS_DC) {
- const upb_fielddef* field;
-
- MessageHeader* self = UNBOX(MessageHeader, object);
-
- field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member));
- if (field == NULL) {
- zend_error(E_USER_ERROR, "Unknown field: %s", Z_STRVAL_P(member));
+// Message
+// -----------------------------------------------------------------------------
+
+typedef struct {
+ zend_object std;
+ zval arena;
+ const Descriptor* desc;
+ upb_msg *msg;
+} Message;
+
+zend_class_entry *message_ce;
+static zend_object_handlers message_object_handlers;
+
+// PHP Object Handlers /////////////////////////////////////////////////////////
+
+/**
+ * Message_create()
+ *
+ * PHP class entry function to allocate and initialize a new Message object.
+ */
+static zend_object* Message_create(zend_class_entry *class_type) {
+ Message *intern = emalloc(sizeof(Message));
+ // XXX(haberman): verify whether we actually want to take this route.
+ class_type->default_properties_count = 0;
+ zend_object_std_init(&intern->std, class_type);
+ intern->std.handlers = &message_object_handlers;
+ Arena_Init(&intern->arena);
+ return &intern->std;
+}
+
+/**
+ * Message_dtor()
+ *
+ * Object handler to destroy a Message. This releases all resources associated
+ * with the message. Note that it is possible to access a destroyed object from
+ * PHP in rare cases.
+ */
+static void Message_dtor(zend_object* obj) {
+ Message* intern = (Message*)obj;
+ ObjCache_Delete(intern->msg);
+ zval_dtor(&intern->arena);
+ zend_object_std_dtor(&intern->std);
+}
+
+/**
+ * get_field()
+ *
+ * Helper function to look up a field given a member name (as a string).
+ */
+static const upb_fielddef *get_field(Message *msg, zval *member) {
+ const upb_msgdef *m = msg->desc->msgdef;
+ const upb_fielddef *f =
+ upb_msgdef_ntof(m, Z_STRVAL_P(member), Z_STRLEN_P(member));
+
+ if (!f) {
+ zend_throw_exception_ex(NULL, 0, "No such property %s.",
+ ZSTR_VAL(msg->desc->class_entry->name));
+ }
+
+ return f;
+}
+
+/**
+ * Message_read_property()
+ *
+ * Object handler for reading a property in PHP. Called when PHP code does:
+ *
+ * $x = $message->foobar;
+ *
+ * Note that all properties of generated messages are private, so this should
+ * only be possible to invoke from generated code, which has accessors like:
+ *
+ * public function getOptionalInt32()
+ * {
+ * return $this->optional_int32;
+ * }
+ *
+ * We lookup the field and return the scalar, RepeatedField, or MapField for
+ * this field.
+ */
+static zval *Message_read_property(zval *obj, zval *member, int type,
+ void **cache_slot, zval *rv) {
+ Message* intern = (Message*)Z_OBJ_P(obj);
+ const upb_fielddef *f = get_field(intern, member);
+ upb_arena *arena = Arena_Get(&intern->arena);
+
+ if (!f) return NULL;
+
+ if (upb_fielddef_ismap(f)) {
+ upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena);
+ MapField_GetPhpWrapper(rv, msgval.map, f, &intern->arena);
+ } else if (upb_fielddef_isseq(f)) {
+ upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena);
+ RepeatedField_GetPhpWrapper(rv, msgval.array, f, &intern->arena);
+ } else {
+ upb_msgval msgval = upb_msg_get(intern->msg, f);
+ const Descriptor *subdesc = Descriptor_GetFromFieldDef(f);
+ Convert_UpbToPhp(msgval, rv, upb_fielddef_type(f), subdesc, &intern->arena);
+ }
+
+ return rv;
+}
+
+/**
+ * Message_write_property()
+ *
+ * Object handler for writing a property in PHP. Called when PHP code does:
+ *
+ * $message->foobar = $x;
+ *
+ * Note that all properties of generated messages are private, so this should
+ * only be possible to invoke from generated code, which has accessors like:
+ *
+ * public function setOptionalInt32($var)
+ * {
+ * GPBUtil::checkInt32($var);
+ * $this->optional_int32 = $var;
+ *
+ * return $this;
+ * }
+ *
+ * The C extension version of checkInt32() doesn't actually check anything, so
+ * we perform all checking and conversion in this function.
+ */
+static void Message_write_property(zval *obj, zval *member, zval *val,
+ void **cache_slot) {
+ Message* intern = (Message*)Z_OBJ_P(obj);
+ const upb_fielddef *f = get_field(intern, member);
+ upb_arena *arena = Arena_Get(&intern->arena);
+ upb_msgval msgval;
+
+ if (!f) return;
+
+ if (upb_fielddef_ismap(f)) {
+ msgval.map_val = MapField_GetUpbMap(val, f, arena);
+ if (!msgval.map_val) return;
+ } else if (upb_fielddef_isseq(f)) {
+ msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
+ if (!msgval.array_val) return;
+ } else {
+ upb_fieldtype_t type = upb_fielddef_type(f);
+ const Descriptor *subdesc = Descriptor_GetFromFieldDef(f);
+ bool ok = Convert_PhpToUpb(val, &msgval, type, subdesc, arena);
+ if (!ok) return;
}
- layout_set(self->descriptor->layout, self, field, value TSRMLS_CC);
+ upb_msg_set(intern->msg, f, msgval, arena);
}
-#if PHP_MAJOR_VERSION < 7
-static void message_set_property(zval* object, zval* member, zval* value,
- php_proto_zend_literal key TSRMLS_DC) {
-#elif PHP_VERSION_ID < 70400
-static void message_set_property(zval* object, zval* member, zval* value,
- void** cache_slot) {
-#else
-static zval* message_set_property(zval* object, zval* member, zval* value,
- void** cache_slot) {
-#endif
- if (Z_TYPE_P(member) != IS_STRING) {
- zend_error(E_USER_ERROR, "Unexpected type for field name");
-#if PHP_VERSION_ID < 70400
- return;
-#else
- return value;
-#endif
- }
-
-#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
- if (Z_OBJCE_P(object) != EG(scope)) {
-#else
- if (Z_OBJCE_P(object) != zend_get_executed_scope()) {
-#endif
- // User cannot set property directly (e.g., $m->a = 1)
- zend_error(E_USER_ERROR, "Cannot access private property.");
-#if PHP_VERSION_ID < 70400
- return;
-#else
- return value;
-#endif
- }
+/**
+ * Message_get_property_ptr_ptr()
+ *
+ * Object handler for the get_property_ptr_ptr event in PHP. This returns a
+ * reference to our internal properties. We don't support this, so we return
+ * NULL.
+ */
+static zval *Message_get_property_ptr_ptr(zval *object, zval *member, int type,
+ void **cache_slot) {
+ return NULL; // We do not have a properties table.
+}
- message_set_property_internal(object, member, value TSRMLS_CC);
-#if PHP_VERSION_ID >= 70400
- return value;
-#endif
+/**
+ * Message_get_properties()
+ *
+ * Object handler for the get_properties event in PHP. This returns a HashTable
+ * of our internal properties. We don't support this, so we return NULL.
+ */
+static HashTable* Message_get_properties(zval* object TSRMLS_DC) {
+ return NULL; // We don't offer direct references to our properties.
}
-static zval* message_get_property_internal(zval* object,
- zval* member TSRMLS_DC) {
- MessageHeader* self = UNBOX(MessageHeader, object);
- const upb_fielddef* field;
- field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member));
- if (field == NULL) {
- return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL;
- }
+// C Functions from message.h. /////////////////////////////////////////////////
- zend_property_info* property_info;
-#if PHP_MAJOR_VERSION < 7
- property_info =
- zend_get_property_info(Z_OBJCE_P(object), member, true TSRMLS_CC);
-#else
- property_info =
- zend_get_property_info(Z_OBJCE_P(object), Z_STR_P(member), true);
-#endif
- return layout_get(
- self->descriptor->layout, self, field,
- OBJ_PROP(Z_OBJ_P(object), property_info->offset) TSRMLS_CC);
-}
+// These are documented in the header file.
-static void message_get_oneof_property_internal(zval* object, zval* member,
- zval* return_value TSRMLS_DC) {
- MessageHeader* self = UNBOX(MessageHeader, object);
- const upb_fielddef* field;
- field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member));
- if (field == NULL) {
+void Message_GetPhpWrapper(zval *val, const Descriptor *desc, upb_msg *msg,
+ zval *arena) {
+ if (!msg) {
+ ZVAL_NULL(val);
return;
}
- layout_get(self->descriptor->layout, self, field,
- ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
+ if (!ObjCache_Get(msg, val)) {
+ Message *intern = emalloc(sizeof(Message));
+ // XXX(haberman): verify whether we actually want to take this route.
+ desc->class_entry->default_properties_count = 0;
+ zend_object_std_init(&intern->std, desc->class_entry);
+ intern->std.handlers = &message_object_handlers;
+ ZVAL_COPY(&intern->arena, arena);
+ intern->desc = desc;
+ intern->msg = msg;
+ ZVAL_OBJ(val, &intern->std);
+ ObjCache_Add(intern->msg, &intern->std);
+ }
}
-#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;
- }
+bool Message_GetUpbMessage(zval *val, const Descriptor *desc, upb_arena *arena,
+ upb_msg **msg) {
+ PBPHP_ASSERT(desc);
-#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
- if (Z_OBJCE_P(object) != EG(scope)) {
-#else
- if (Z_OBJCE_P(object) != zend_get_executed_scope()) {
-#endif
- // 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;
+ if (Z_ISREF_P(val)) {
+ ZVAL_DEREF(val);
}
- return message_get_property_internal(object, member TSRMLS_CC);
-}
-
-#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
- return NULL;
-}
-
-static HashTable* message_get_properties(zval* object TSRMLS_DC) {
- return NULL;
-}
+ if (Z_TYPE_P(val) == IS_NULL) {
+ *msg = NULL;
+ return true;
+ }
-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;
-}
+ if (Z_TYPE_P(val) == IS_OBJECT &&
+ instanceof_function(Z_OBJCE_P(val), desc->class_entry)) {
+ Message *intern = (Message*)Z_OBJ_P(val);
+ upb_arena_fuse(arena, Arena_Get(&intern->arena));
+ *msg = intern->msg;
+ return true;
+ } else {
+ zend_throw_exception_ex(NULL, 0, "Given value is not an instance of %s.",
+ ZSTR_VAL(desc->class_entry->name));
+ return false;
+ }
+}
+
+// Message PHP methods /////////////////////////////////////////////////////////
+
+/**
+ * Message_InitFromPhp()
+ *
+ * Helper method to handle the initialization of a message from a PHP value, eg.
+ *
+ * $m = new TestMessage([
+ * 'optional_int32' => -42,
+ * 'optional_bool' => true,
+ * 'optional_string' => 'a',
+ * 'optional_enum' => TestEnum::ONE,
+ * 'optional_message' => new Sub([
+ * 'a' => 33
+ * ]),
+ * 'repeated_int32' => [-42, -52],
+ * 'repeated_enum' => [TestEnum::ZERO, TestEnum::ONE],
+ * 'repeated_message' => [new Sub(['a' => 34]),
+ * new Sub(['a' => 35])],
+ * 'map_int32_int32' => [-62 => -62],
+ * 'map_int32_enum' => [1 => TestEnum::ONE],
+ * 'map_int32_message' => [1 => new Sub(['a' => 36])],
+ * ]);
+ *
+ * The initializer must be an array.
+ */
+bool Message_InitFromPhp(upb_msg *msg, const upb_msgdef *m, zval *init,
+ upb_arena *arena) {
+ HashTable* table = HASH_OF(init);
+ HashPosition pos;
+
+ if (Z_ISREF_P(init)) {
+ ZVAL_DEREF(init);
+ }
+
+ if (Z_TYPE_P(init) != IS_ARRAY) {
+ zend_throw_exception_ex(NULL, 0,
+ "Initializer for a message %s must be an array.",
+ upb_msgdef_fullname(m));
+ return false;
+ }
+
+ zend_hash_internal_pointer_reset_ex(table, &pos);
+
+ while (true) { // Iterate over key/value pairs.
+ zval key;
+ zval *val;
+ const upb_fielddef *f;
+ upb_msgval msgval;
+
+ zend_hash_get_current_key_zval_ex(table, &key, &pos);
+ val = zend_hash_get_current_data_ex(table, &pos);
+
+ if (!val) return true; // Finished iteration.
+
+ if (Z_ISREF_P(val)) {
+ ZVAL_DEREF(val);
+ }
-// -----------------------------------------------------------------------------
-// C Message Utilities
-// -----------------------------------------------------------------------------
+ f = upb_msgdef_ntof(m, Z_STRVAL_P(&key), Z_STRLEN_P(&key));
-void* message_data(MessageHeader* msg) {
- return msg->data;
-}
+ if (!f) {
+ zend_throw_exception_ex(NULL, 0,
+ "No such field %s", Z_STRVAL_P(&key));
+ return false;
+ }
-void custom_data_init(const zend_class_entry* ce,
- MessageHeader* intern PHP_PROTO_TSRMLS_DC) {
- DescriptorInternal* desc = get_ce_desc(ce);
- intern->data = ALLOC_N(uint8_t, 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 PHP_PROTO_TSRMLS_CC);
-}
+ if (upb_fielddef_ismap(f)) {
+ msgval.map_val = MapField_GetUpbMap(val, f, arena);
+ if (!msgval.map_val) return false;
+ } else if (upb_fielddef_isseq(f)) {
+ msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
+ if (!msgval.array_val) return false;
+ } else {
+ const Descriptor *desc = Descriptor_GetFromFieldDef(f);
+ upb_fieldtype_t type = upb_fielddef_type(f);
+ if (!Convert_PhpToUpbAutoWrap(val, &msgval, type, desc, arena)) {
+ return false;
+ }
+ }
-#define INIT_MESSAGE_WITH_ARRAY \
- { \
- zval* array_wrapper = NULL; \
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, \
- "|a!", &array_wrapper) == FAILURE) { \
- return; \
- } \
- Message_construct(getThis(), array_wrapper); \
+ upb_msg_set(msg, f, msgval, arena);
+ zend_hash_move_forward_ex(table, &pos);
+ zval_dtor(&key);
}
-
-// -----------------------------------------------------------------------------
-// PHP Methods
-// -----------------------------------------------------------------------------
-
-static void append_wrapper_message(
- zend_class_entry* subklass, RepeatedField* intern, zval* value TSRMLS_DC) {
- MessageHeader* submsg;
- const upb_fielddef* field;
-#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);
-
- field = upb_msgdef_itof(submsg->descriptor->msgdef, 1);
- layout_set(submsg->descriptor->layout, submsg, field, value TSRMLS_CC);
-}
-
-static void set_wrapper_message_as_map_value(
- zend_class_entry* subklass, zval* map, zval* key, zval* value TSRMLS_DC) {
- MessageHeader* submsg;
- const upb_fielddef* field;
-#if PHP_MAJOR_VERSION < 7
- zval* val = NULL;
- MAKE_STD_ZVAL(val);
- ZVAL_OBJ(val, subklass->create_object(subklass TSRMLS_CC));
- map_field_handlers->write_dimension(
- map, key, val TSRMLS_CC);
- submsg = UNBOX(MessageHeader, val);
-#else
- zval val;
- zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
- ZVAL_OBJ(&val, obj);
- map_field_handlers->write_dimension(map, key, &val TSRMLS_CC);
- submsg = (MessageHeader*)((char*)obj - XtOffsetOf(MessageHeader, std));
-#endif
- custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
-
- field = upb_msgdef_itof(submsg->descriptor->msgdef, 1);
- layout_set(submsg->descriptor->layout, submsg, field, value TSRMLS_CC);
}
-void Message_construct(zval* msg, zval* array_wrapper) {
- TSRMLS_FETCH();
- zend_class_entry* ce = Z_OBJCE_P(msg);
- MessageHeader* intern = NULL;
-
- if (!class_added(ce)) {
-#if PHP_MAJOR_VERSION < 7
- DescriptorInternal* desc = get_class_desc(ce->name);
-#else
- DescriptorInternal* desc = get_class_desc(ZSTR_VAL(ce->name));
-#endif
- register_class(desc, false TSRMLS_CC);
- }
+/**
+ * Message::__construct()
+ *
+ * Constructor for Message.
+ * @param array Map of initial values ['k' = val]
+ */
+PHP_METHOD(Message, __construct) {
+ Message* intern = (Message*)Z_OBJ_P(getThis());
+ const Descriptor* desc = Descriptor_GetFromClassEntry(Z_OBJCE_P(getThis()));
+ const upb_msgdef *msgdef = desc->msgdef;
+ upb_arena *arena = Arena_Get(&intern->arena);
+ zval *init_arr = NULL;
- intern = UNBOX(MessageHeader, msg);
- custom_data_init(ce, intern PHP_PROTO_TSRMLS_CC);
+ intern->desc = desc;
+ intern->msg = upb_msg_new(msgdef, arena);
+ ObjCache_Add(intern->msg, &intern->std);
- if (array_wrapper == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &init_arr) == FAILURE) {
return;
}
- HashTable* array = Z_ARRVAL_P(array_wrapper);
- HashPosition pointer;
- zval key;
- void* value;
- const upb_fielddef* field;
-
- for (zend_hash_internal_pointer_reset_ex(array, &pointer);
- php_proto_zend_hash_get_current_data_ex(array, (void**)&value,
- &pointer) == SUCCESS;
- zend_hash_move_forward_ex(array, &pointer)) {
- zend_hash_get_current_key_zval_ex(array, &key, &pointer);
- field = upb_msgdef_ntofz(intern->descriptor->msgdef, Z_STRVAL_P(&key));
-#if PHP_MAJOR_VERSION >= 7
- if (Z_ISREF_P((CACHED_VALUE*)value)) {
- value = Z_REFVAL_P((CACHED_VALUE*)value);
- }
-#endif
- if (field == NULL) {
- zend_error(E_USER_ERROR, "Unknown field: %s", Z_STRVAL_P(&key));
- }
- if (upb_fielddef_ismap(field)) {
- PHP_PROTO_FAKE_SCOPE_BEGIN(Z_OBJCE_P(msg));
- zval* submap = message_get_property_internal(msg, &key TSRMLS_CC);
- PHP_PROTO_FAKE_SCOPE_END;
- HashTable* subtable = HASH_OF(
- CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value));
- HashPosition subpointer;
- zval subkey;
- void* memory;
- bool is_wrapper = false;
- zend_class_entry* subklass = NULL;
- const upb_msgdef* mapentry = upb_fielddef_msgsubdef(field);
- const upb_fielddef *value_field = upb_msgdef_itof(mapentry, 2);
-
- if (upb_fielddef_issubmsg(value_field)) {
- const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(value_field);
- is_wrapper = is_wrapper_msg(submsgdef);
-
- if (is_wrapper) {
- DescriptorInternal* subdesc = get_msgdef_desc(submsgdef);
- register_class(subdesc, false TSRMLS_CC);
- subklass = subdesc->klass;
- }
- }
-
- for (zend_hash_internal_pointer_reset_ex(subtable, &subpointer);
- php_proto_zend_hash_get_current_data_ex(subtable, (void**)&memory,
- &subpointer) == SUCCESS;
- zend_hash_move_forward_ex(subtable, &subpointer)) {
- zend_hash_get_current_key_zval_ex(subtable, &subkey, &subpointer);
- if (is_wrapper &&
- Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory)) != IS_OBJECT) {
- set_wrapper_message_as_map_value(
- subklass, submap, &subkey,
- CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory) TSRMLS_CC);
- } else {
- map_field_handlers->write_dimension(
- submap, &subkey,
- CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory) TSRMLS_CC);
- }
- zval_dtor(&subkey);
- }
- } else if (upb_fielddef_isseq(field)) {
- PHP_PROTO_FAKE_SCOPE_BEGIN(Z_OBJCE_P(msg));
- zval* subarray = message_get_property_internal(msg, &key TSRMLS_CC);
- PHP_PROTO_FAKE_SCOPE_END;
- HashTable* subtable = HASH_OF(
- CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value));
- HashPosition subpointer;
- void* memory;
- bool is_wrapper = false;
- zend_class_entry* subklass = NULL;
-
- if (upb_fielddef_issubmsg(field)) {
- const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
- is_wrapper = is_wrapper_msg(submsgdef);
-
- if (is_wrapper) {
- DescriptorInternal* subdesc = get_msgdef_desc(submsgdef);
- register_class(subdesc, false TSRMLS_CC);
- subklass = subdesc->klass;
- }
- }
-
- for (zend_hash_internal_pointer_reset_ex(subtable, &subpointer);
- php_proto_zend_hash_get_current_data_ex(subtable, (void**)&memory,
- &subpointer) == SUCCESS;
- zend_hash_move_forward_ex(subtable, &subpointer)) {
- if (is_wrapper &&
- Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory)) != IS_OBJECT) {
- RepeatedField* intern = UNBOX(RepeatedField, subarray);
- append_wrapper_message(
- subklass, intern,
- CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory) TSRMLS_CC);
- } else {
- repeated_field_handlers->write_dimension(
- subarray, NULL,
- CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory) TSRMLS_CC);
- }
- }
- } else if (upb_fielddef_issubmsg(field)) {
- const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
- DescriptorInternal* desc = get_msgdef_desc(submsgdef);
- register_class(desc, false TSRMLS_CC);
-
- CACHED_VALUE* cached = NULL;
- if (upb_fielddef_containingoneof(field)) {
- void* memory = slot_memory(intern->descriptor->layout,
- message_data(intern), field);
- uint32_t* oneof_case = slot_oneof_case(intern->descriptor->layout,
- message_data(intern), field);
- int property_cache_index =
- intern->descriptor->layout->fields[upb_fielddef_index(field)]
- .cache_index;
- cached = OBJ_PROP(Z_OBJ_P(msg), property_cache_index);
- *(CACHED_VALUE**)(memory) = cached;
- *oneof_case = upb_fielddef_number(field);
- } else {
- zend_property_info* property_info;
- PHP_PROTO_FAKE_SCOPE_BEGIN(Z_OBJCE_P(msg));
-#if PHP_MAJOR_VERSION < 7
- property_info =
- zend_get_property_info(Z_OBJCE_P(msg), &key, true TSRMLS_CC);
-#else
- property_info =
- zend_get_property_info(Z_OBJCE_P(msg), Z_STR_P(&key), true);
-#endif
- PHP_PROTO_FAKE_SCOPE_END;
- cached = OBJ_PROP(Z_OBJ_P(msg), property_info->offset);
- }
-#if PHP_MAJOR_VERSION < 7
- SEPARATE_ZVAL_IF_NOT_REF(cached);
-#endif
- zval* submsg = CACHED_PTR_TO_ZVAL_PTR(cached);
- ZVAL_OBJ(submsg, desc->klass->create_object(desc->klass TSRMLS_CC));
- Message_construct(submsg, NULL);
- MessageHeader* to = UNBOX(MessageHeader, submsg);
- const upb_filedef *file = upb_msgdef_file(submsgdef);
- if (!strcmp(upb_filedef_name(file), "google/protobuf/wrappers.proto") &&
- Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value)) != IS_OBJECT) {
- const upb_fielddef *value_field = upb_msgdef_itof(submsgdef, 1);
- layout_set(to->descriptor->layout, to,
- value_field, CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value)
- TSRMLS_CC);
- } else {
- MessageHeader* from =
- UNBOX(MessageHeader,
- CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value));
- if(from->descriptor != to->descriptor) {
- zend_error(E_USER_ERROR,
- "Cannot merge messages with different class.");
- return;
- }
-
- layout_merge(from->descriptor->layout, from, to TSRMLS_CC);
- }
- } else {
- message_set_property_internal(msg, &key,
- CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value) TSRMLS_CC);
- }
- zval_dtor(&key);
+ if (init_arr) {
+ Message_InitFromPhp(intern->msg, desc->msgdef, init_arr, arena);
}
}
-// At the first time the message is created, the class entry hasn't been
-// 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) {
- INIT_MESSAGE_WITH_ARRAY;
+/**
+ * Message::discardUnknownFields()
+ *
+ * Discards any unknown fields for this message or any submessages.
+ */
+PHP_METHOD(Message, discardUnknownFields) {
+ Message* intern = (Message*)Z_OBJ_P(getThis());
+ upb_msg_discardunknown(intern->msg, intern->desc->msgdef, 64);
}
+/**
+ * Message::clear()
+ *
+ * Clears all fields of this message.
+ */
PHP_METHOD(Message, clear) {
- MessageHeader* msg = UNBOX(MessageHeader, getThis());
- DescriptorInternal* desc = msg->descriptor;
- register_class(desc, false TSRMLS_CC);
- zend_class_entry* ce = desc->klass;
-
- zend_object_std_dtor(&msg->std TSRMLS_CC);
- object_properties_init(&msg->std, ce);
-
- layout_init(desc->layout, message_data(msg), &msg->std TSRMLS_CC);
+ Message* intern = (Message*)Z_OBJ_P(getThis());
+ upb_msg_clear(intern->msg, intern->desc->msgdef);
}
+/**
+ * Message::mergeFrom()
+ *
+ * Merges from the given message, which must be of the same class as us.
+ * @param object Message to merge from.
+ */
PHP_METHOD(Message, mergeFrom) {
+ Message* intern = (Message*)Z_OBJ_P(getThis());
+ Message* from;
+ upb_arena *arena = Arena_Get(&intern->arena);
+ const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef);
zval* value;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &value,
- message_type) == FAILURE) {
+ char *pb;
+ size_t size;
+ bool ok;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &value,
+ intern->desc->class_entry) == FAILURE) {
return;
}
- MessageHeader* from = UNBOX(MessageHeader, value);
- MessageHeader* to = UNBOX(MessageHeader, getThis());
+ from = (Message*)Z_OBJ_P(value);
- if(from->descriptor != to->descriptor) {
- zend_error(E_USER_ERROR, "Cannot merge messages with different class.");
- return;
- }
+ // Should be guaranteed since we passed the class type to
+ // zend_parse_parameters().
+ PBPHP_ASSERT(from->desc == intern->desc);
- layout_merge(from->descriptor->layout, from, to TSRMLS_CC);
-}
+ // TODO(haberman): use a temp arena for this once we can make upb_decode()
+ // copy strings.
+ pb = upb_encode(from->msg, l, arena, &size);
-PHP_METHOD(Message, readWrapperValue) {
- char* member;
- PHP_PROTO_SIZE length;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &member,
- &length) == FAILURE) {
+ if (!pb) {
+ zend_throw_exception_ex(NULL, 0, "Max nesting exceeded");
return;
}
- MessageHeader* msg = UNBOX(MessageHeader, getThis());
- const upb_fielddef* field =
- upb_msgdef_ntofz(msg->descriptor->msgdef, member);
-
- if (upb_fielddef_containingoneof(field)) {
- uint32_t* oneof_case =
- slot_oneof_case(msg->descriptor->layout, message_data(msg), field);
- if (*oneof_case != upb_fielddef_number(field)) {
- RETURN_NULL();
- }
- }
+ ok = upb_decode(pb, size, intern->msg, l, arena);
+ PBPHP_ASSERT(ok);
+}
- zval* cached_zval =
- CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, field));
+/**
+ * Message::mergeFromString()
+ *
+ * Merges from the given string.
+ * @param string Binary protobuf data to merge.
+ */
+PHP_METHOD(Message, mergeFromString) {
+ Message* intern = (Message*)Z_OBJ_P(getThis());
+ char *data = NULL;
+ char *data_copy = NULL;
+ zend_long data_len;
+ const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef);
+ upb_arena *arena = Arena_Get(&intern->arena);
- if (Z_TYPE_P(cached_zval) == IS_NULL) {
- RETURN_NULL();
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &data, &data_len) ==
+ FAILURE) {
+ return;
}
- if (Z_TYPE_P(cached_zval) == IS_OBJECT) {
- const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
- const upb_fielddef* value_field = upb_msgdef_itof(submsgdef, 1);
- MessageHeader* submsg = UNBOX(MessageHeader, cached_zval);
- CACHED_VALUE* cached_value = find_zval_property(submsg, value_field);
- layout_get(submsg->descriptor->layout, submsg, value_field,
- cached_value TSRMLS_CC);
- RETURN_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cached_value), 1, 0);
- } else {
- RETURN_ZVAL(cached_zval, 1, 0);
- }
-}
+ // TODO(haberman): avoid this copy when we can make the decoder copy.
+ data_copy = upb_arena_malloc(arena, data_len);
+ memcpy(data_copy, data, data_len);
-PHP_METHOD(Message, writeWrapperValue) {
- char* member;
- PHP_PROTO_SIZE length;
- zval* value;
- if (zend_parse_parameters(
- ZEND_NUM_ARGS() TSRMLS_CC, "sz", &member, &length, &value) ==
- FAILURE) {
+ if (!upb_decode(data_copy, data_len, intern->msg, l, arena)) {
+ zend_throw_exception_ex(NULL, 0, "Error occurred during parsing");
return;
}
+}
- MessageHeader* msg = UNBOX(MessageHeader, getThis());
- const upb_fielddef* field = upb_msgdef_ntofz(msg->descriptor->msgdef, member);
+/**
+ * Message::serializeToString()
+ *
+ * Serializes this message instance to protobuf data.
+ * @return string Serialized protobuf data.
+ */
+PHP_METHOD(Message, serializeToString) {
+ Message* intern = (Message*)Z_OBJ_P(getThis());
+ const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef);
+ upb_arena *tmp_arena = upb_arena_new();
+ char *data;
+ size_t size;
- zval* cached_zval =
- CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, field));
+ data = upb_encode(intern->msg, l, tmp_arena, &size);
- if (Z_TYPE_P(value) == IS_NULL) {
- MessageHeader* msg = UNBOX(MessageHeader, getThis());
- layout_set(msg->descriptor->layout, msg,
- field, value TSRMLS_CC);
+ if (!data) {
+ zend_throw_exception_ex(NULL, 0, "Error occurred during serialization");
+ upb_arena_free(tmp_arena);
return;
}
- {
- // Type Checking
- const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
- const upb_fielddef* value_field = upb_msgdef_itof(submsgdef, 1);
- upb_fieldtype_t type = upb_fielddef_type(value_field);
- switch(type) {
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES: {
- if (!protobuf_convert_to_string(value)) {
- return;
- }
- 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;
- }
- }
- break;
-#define CASE_TYPE(upb_type, type, c_type) \
- case UPB_TYPE_##upb_type: { \
- c_type type##_value; \
- if (!protobuf_convert_to_##type(value, &type##_value)) { \
- return; \
- } \
- break; \
- }
- CASE_TYPE(INT32, int32, int32_t)
- CASE_TYPE(UINT32, uint32, uint32_t)
- CASE_TYPE(ENUM, int32, int32_t)
- CASE_TYPE(INT64, int64, int64_t)
- CASE_TYPE(UINT64, uint64, uint64_t)
- CASE_TYPE(FLOAT, float, float)
- CASE_TYPE(DOUBLE, double, double)
- CASE_TYPE(BOOL, bool, int8_t)
-
-#undef CASE_TYPE
- case UPB_TYPE_MESSAGE:
- zend_error(E_ERROR, "No wrapper for message.");
- break;
- }
+ RETVAL_STRINGL(data, size);
+ upb_arena_free(tmp_arena);
+}
+
+/**
+ * Message::mergeFromJsonString()
+ *
+ * Merges the JSON data parsed from the given string.
+ * @param string Serialized JSON data.
+ */
+PHP_METHOD(Message, mergeFromJsonString) {
+ Message* intern = (Message*)Z_OBJ_P(getThis());
+ char *data = NULL;
+ char *data_copy = NULL;
+ zend_long data_len;
+ upb_arena *arena = Arena_Get(&intern->arena);
+ upb_status status;
+ zend_bool ignore_json_unknown = false;
+ int options = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &data, &data_len,
+ &ignore_json_unknown) == FAILURE) {
+ return;
}
- if (upb_fielddef_containingoneof(field)) {
- uint32_t* oneof_case =
- slot_oneof_case(msg->descriptor->layout, message_data(msg), field);
- if (*oneof_case != upb_fielddef_number(field)) {
- zval null_value;
- ZVAL_NULL(&null_value);
- layout_set(msg->descriptor->layout, msg, field, &null_value TSRMLS_CC);
- cached_zval = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, field));
- ZVAL_ZVAL(cached_zval, value, 1, 0);
- return;
- }
+ // TODO(haberman): avoid this copy when we can make the decoder copy.
+ data_copy = upb_arena_malloc(arena, data_len + 1);
+ memcpy(data_copy, data, data_len);
+ data_copy[data_len] = '\0';
+
+ if (ignore_json_unknown) {
+ options |= UPB_JSONDEC_IGNOREUNKNOWN;
}
- if (Z_TYPE_P(cached_zval) == IS_OBJECT) {
- const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
- const upb_fielddef* value_field = upb_msgdef_itof(submsgdef, 1);
- MessageHeader* submsg = UNBOX(MessageHeader, cached_zval);
- layout_set(submsg->descriptor->layout, submsg,
- value_field, value TSRMLS_CC);
- } else {
- ZVAL_ZVAL(cached_zval, value, 1, 0);
+ upb_status_clear(&status);
+ if (!upb_json_decode(data_copy, data_len, intern->msg, intern->desc->msgdef,
+ DescriptorPool_GetSymbolTable(), options, arena,
+ &status)) {
+ zend_throw_exception_ex(NULL, 0, "Error occurred during parsing: %s",
+ upb_status_errmsg(&status));
+ return;
}
}
-PHP_METHOD(Message, readOneof) {
- PHP_PROTO_LONG index;
+/**
+ * Message::serializeToJsonString()
+ *
+ * Serializes this object to JSON.
+ * @return string Serialized JSON data.
+ */
+PHP_METHOD(Message, serializeToJsonString) {
+ Message* intern = (Message*)Z_OBJ_P(getThis());
+ size_t size;
+ int options = 0;
+ char buf[1024];
+ zend_bool preserve_proto_fieldnames = false;
+ upb_status status;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
- FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b",
+ &preserve_proto_fieldnames) == FAILURE) {
return;
}
- MessageHeader* msg = UNBOX(MessageHeader, getThis());
-
- const upb_fielddef* field = upb_msgdef_itof(msg->descriptor->msgdef, index);
+ if (preserve_proto_fieldnames) {
+ options |= UPB_JSONENC_PROTONAMES;
+ }
- // Unlike singular fields, oneof fields share cached property. So we cannot
- // let layout_get modify the cached property. Instead, we pass in the return
- // value directly.
- layout_get(msg->descriptor->layout, msg, field,
- ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
-}
+ upb_status_clear(&status);
+ size = upb_json_encode(intern->msg, intern->desc->msgdef,
+ DescriptorPool_GetSymbolTable(), options, buf,
+ sizeof(buf), &status);
-PHP_METHOD(Message, writeOneof) {
- PHP_PROTO_LONG index;
- zval* value;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &index, &value) ==
- FAILURE) {
+ if (!upb_ok(&status)) {
+ zend_throw_exception_ex(NULL, 0,
+ "Error occurred during JSON serialization: %s",
+ upb_status_errmsg(&status));
return;
}
- MessageHeader* msg = UNBOX(MessageHeader, getThis());
-
- const upb_fielddef* field = upb_msgdef_itof(msg->descriptor->msgdef, index);
-
- layout_set(msg->descriptor->layout, msg, field, value TSRMLS_CC);
-}
-
-PHP_METHOD(Message, whichOneof) {
- char* oneof_name;
- PHP_PROTO_SIZE length;
+ if (size >= sizeof(buf)) {
+ char *buf2 = malloc(size + 1);
+ upb_json_encode(intern->msg, intern->desc->msgdef,
+ DescriptorPool_GetSymbolTable(), options, buf2, size + 1,
+ &status);
+ RETVAL_STRINGL(buf2, size);
+ free(buf2);
+ } else {
+ RETVAL_STRINGL(buf, size);
+ }
+}
+
+/**
+ * Message::readWrapperValue()
+ *
+ * Returns an unboxed value for the given field. This is called from generated
+ * methods for wrapper fields, eg.
+ *
+ * public function getDoubleValueUnwrapped()
+ * {
+ * return $this->readWrapperValue("double_value");
+ * }
+ *
+ * @return Unwrapped field value or null.
+ */
+PHP_METHOD(Message, readWrapperValue) {
+ Message* intern = (Message*)Z_OBJ_P(getThis());
+ char* member;
+ const upb_fielddef *f;
+ zend_long size;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &oneof_name,
- &length) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &member, &size) == FAILURE) {
return;
}
- MessageHeader* msg = UNBOX(MessageHeader, getThis());
-
- 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);
-}
-
-// -----------------------------------------------------------------------------
-// Well Known Types Support
-// -----------------------------------------------------------------------------
+ f = upb_msgdef_ntof(intern->desc->msgdef, member, size);
-#define PHP_PROTO_FIELD_ACCESSORS(UPPER_CLASS, LOWER_CLASS, UPPER_FIELD, \
- LOWER_FIELD) \
- PHP_METHOD(UPPER_CLASS, get##UPPER_FIELD) { \
- zval member; \
- PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1); \
- PHP_PROTO_FAKE_SCOPE_BEGIN(LOWER_CLASS##_type); \
- zval* value = message_get_property_internal(getThis(), &member TSRMLS_CC); \
- PHP_PROTO_FAKE_SCOPE_END; \
- zval_dtor(&member); \
- PHP_PROTO_RETVAL_ZVAL(value); \
- } \
- PHP_METHOD(UPPER_CLASS, set##UPPER_FIELD) { \
- zval* value = NULL; \
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == \
- FAILURE) { \
- return; \
- } \
- zval member; \
- PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1); \
- message_set_property_internal(getThis(), &member, value TSRMLS_CC); \
- zval_dtor(&member); \
- PHP_PROTO_RETVAL_ZVAL(getThis()); \
- }
-
-#define PHP_PROTO_ONEOF_FIELD_ACCESSORS(UPPER_CLASS, LOWER_CLASS, UPPER_FIELD, \
- LOWER_FIELD) \
- PHP_METHOD(UPPER_CLASS, get##UPPER_FIELD) { \
- zval member; \
- PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1); \
- PHP_PROTO_FAKE_SCOPE_BEGIN(LOWER_CLASS##_type); \
- message_get_oneof_property_internal(getThis(), &member, \
- return_value TSRMLS_CC); \
- PHP_PROTO_FAKE_SCOPE_END; \
- zval_dtor(&member); \
- } \
- PHP_METHOD(UPPER_CLASS, set##UPPER_FIELD) { \
- zval* value = NULL; \
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == \
- FAILURE) { \
- return; \
- } \
- zval member; \
- PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1); \
- message_set_property_internal(getThis(), &member, value TSRMLS_CC); \
- zval_dtor(&member); \
- PHP_PROTO_RETVAL_ZVAL(getThis()); \
+ if (!f || !upb_msgdef_iswrapper(upb_fielddef_msgsubdef(f))) {
+ zend_throw_exception_ex(NULL, 0, "Message %s has no field %s",
+ upb_msgdef_fullname(intern->desc->msgdef), member);
+ return;
}
-#define PHP_PROTO_ONEOF_ACCESSORS(UPPER_CLASS, LOWER_CLASS, UPPER_FIELD, \
- LOWER_FIELD) \
- PHP_METHOD(UPPER_CLASS, get##UPPER_FIELD) { \
- MessageHeader* msg = UNBOX(MessageHeader, getThis()); \
- PHP_PROTO_FAKE_SCOPE_BEGIN(LOWER_CLASS##_type); \
- const upb_oneofdef* oneof = upb_msgdef_ntoo( \
- msg->descriptor->msgdef, LOWER_FIELD, strlen(LOWER_FIELD)); \
- const char* oneof_case_name = layout_get_oneof_case( \
- msg->descriptor->layout, message_data(msg), oneof TSRMLS_CC); \
- PHP_PROTO_FAKE_SCOPE_END; \
- PHP_PROTO_RETURN_STRING(oneof_case_name, 1); \
+ if (upb_msg_has(intern->msg, f)) {
+ const upb_msg *wrapper = upb_msg_get(intern->msg, f).msg_val;
+ const upb_msgdef *m = upb_fielddef_msgsubdef(f);
+ const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
+ const upb_fieldtype_t val_type = upb_fielddef_type(val_f);
+ upb_msgval msgval = upb_msg_get(wrapper, val_f);
+ zval ret;
+ Convert_UpbToPhp(msgval, &ret, val_type, NULL, &intern->arena);
+ RETURN_ZVAL(&ret, 1, 0);
+ } else {
+ RETURN_NULL();
}
-
-// Forward declare file init functions
-static void init_file_any(TSRMLS_D);
-static void init_file_api(TSRMLS_D);
-static void init_file_duration(TSRMLS_D);
-static void init_file_field_mask(TSRMLS_D);
-static void init_file_empty(TSRMLS_D);
-static void init_file_source_context(TSRMLS_D);
-static void init_file_struct(TSRMLS_D);
-static void init_file_timestamp(TSRMLS_D);
-static void init_file_type(TSRMLS_D);
-static void init_file_wrappers(TSRMLS_D);
-
-// Define file init functions
-static void init_file_any(TSRMLS_D) {
- if (is_inited_file_any) return;
- init_generated_pool_once(TSRMLS_C);
- const char* generated_file =
- "0acd010a19676f6f676c652f70726f746f6275662f616e792e70726f746f"
- "120f676f6f676c652e70726f746f62756622260a03416e7912100a087479"
- "70655f75726c180120012809120d0a0576616c756518022001280c426f0a"
- "13636f6d2e676f6f676c652e70726f746f6275664208416e7950726f746f"
- "50015a256769746875622e636f6d2f676f6c616e672f70726f746f627566"
- "2f7074797065732f616e79a20203475042aa021e476f6f676c652e50726f"
- "746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33";
- char* binary;
- int binary_len;
- hex_to_binary(generated_file, &binary, &binary_len);
- internal_add_generated_file(binary, binary_len,
- generated_pool, true TSRMLS_CC);
- FREE(binary);
- is_inited_file_any = true;
-}
-
-static void init_file_api(TSRMLS_D) {
- if (is_inited_file_api) return;
- init_file_source_context(TSRMLS_C);
- init_file_type(TSRMLS_C);
- init_generated_pool_once(TSRMLS_C);
- const char* generated_file =
- "0aee050a19676f6f676c652f70726f746f6275662f6170692e70726f746f"
- "120f676f6f676c652e70726f746f6275661a24676f6f676c652f70726f74"
- "6f6275662f736f757263655f636f6e746578742e70726f746f1a1a676f6f"
- "676c652f70726f746f6275662f747970652e70726f746f2281020a034170"
- "69120c0a046e616d6518012001280912280a076d6574686f647318022003"
- "280b32172e676f6f676c652e70726f746f6275662e4d6574686f6412280a"
- "076f7074696f6e7318032003280b32172e676f6f676c652e70726f746f62"
- "75662e4f7074696f6e120f0a0776657273696f6e18042001280912360a0e"
- "736f757263655f636f6e7465787418052001280b321e2e676f6f676c652e"
- "70726f746f6275662e536f75726365436f6e7465787412260a066d697869"
- "6e7318062003280b32162e676f6f676c652e70726f746f6275662e4d6978"
- "696e12270a0673796e74617818072001280e32172e676f6f676c652e7072"
- "6f746f6275662e53796e74617822d5010a064d6574686f64120c0a046e61"
- "6d6518012001280912180a10726571756573745f747970655f75726c1802"
- "2001280912190a11726571756573745f73747265616d696e671803200128"
- "0812190a11726573706f6e73655f747970655f75726c180420012809121a"
- "0a12726573706f6e73655f73747265616d696e6718052001280812280a07"
- "6f7074696f6e7318062003280b32172e676f6f676c652e70726f746f6275"
- "662e4f7074696f6e12270a0673796e74617818072001280e32172e676f6f"
- "676c652e70726f746f6275662e53796e74617822230a054d6978696e120c"
- "0a046e616d65180120012809120c0a04726f6f7418022001280942750a13"
- "636f6d2e676f6f676c652e70726f746f627566420841706950726f746f50"
- "015a2b676f6f676c652e676f6c616e672e6f72672f67656e70726f746f2f"
- "70726f746f6275662f6170693b617069a20203475042aa021e476f6f676c"
- "652e50726f746f6275662e57656c6c4b6e6f776e5479706573620670726f"
- "746f33";
- char* binary;
- int binary_len;
- hex_to_binary(generated_file, &binary, &binary_len);
- internal_add_generated_file(binary, binary_len,
- generated_pool, true TSRMLS_CC);
- FREE(binary);
- is_inited_file_api = true;
-}
-
-static void init_file_duration(TSRMLS_D) {
- if (is_inited_file_duration) return;
- init_generated_pool_once(TSRMLS_C);
- const char* generated_file =
- "0ae3010a1e676f6f676c652f70726f746f6275662f6475726174696f6e2e"
- "70726f746f120f676f6f676c652e70726f746f627566222a0a0844757261"
- "74696f6e120f0a077365636f6e6473180120012803120d0a056e616e6f73"
- "180220012805427c0a13636f6d2e676f6f676c652e70726f746f62756642"
- "0d4475726174696f6e50726f746f50015a2a6769746875622e636f6d2f67"
- "6f6c616e672f70726f746f6275662f7074797065732f6475726174696f6e"
- "f80101a20203475042aa021e476f6f676c652e50726f746f6275662e5765"
- "6c6c4b6e6f776e5479706573620670726f746f33";
- char* binary;
- int binary_len;
- hex_to_binary(generated_file, &binary, &binary_len);
- internal_add_generated_file(binary, binary_len,
- generated_pool, true TSRMLS_CC);
- FREE(binary);
- is_inited_file_duration = true;
-}
-
-static void init_file_field_mask(TSRMLS_D) {
- if (is_inited_file_field_mask) return;
- init_generated_pool_once(TSRMLS_C);
- const char* generated_file =
- "0ae3010a20676f6f676c652f70726f746f6275662f6669656c645f6d6173"
- "6b2e70726f746f120f676f6f676c652e70726f746f627566221a0a094669"
- "656c644d61736b120d0a0570617468731801200328094289010a13636f6d"
- "2e676f6f676c652e70726f746f627566420e4669656c644d61736b50726f"
- "746f50015a39676f6f676c652e676f6c616e672e6f72672f67656e70726f"
- "746f2f70726f746f6275662f6669656c645f6d61736b3b6669656c645f6d"
- "61736ba20203475042aa021e476f6f676c652e50726f746f6275662e5765"
- "6c6c4b6e6f776e5479706573620670726f746f33";
- char* binary;
- int binary_len;
- hex_to_binary(generated_file, &binary, &binary_len);
- internal_add_generated_file(binary, binary_len,
- generated_pool, true TSRMLS_CC);
- FREE(binary);
- is_inited_file_field_mask = true;
-}
-
-static void init_file_empty(TSRMLS_D) {
- if (is_inited_file_empty) return;
- init_generated_pool_once(TSRMLS_C);
- const char* generated_file =
- "0ab7010a1b676f6f676c652f70726f746f6275662f656d7074792e70726f"
- "746f120f676f6f676c652e70726f746f62756622070a05456d7074794276"
- "0a13636f6d2e676f6f676c652e70726f746f627566420a456d7074795072"
- "6f746f50015a276769746875622e636f6d2f676f6c616e672f70726f746f"
- "6275662f7074797065732f656d707479f80101a20203475042aa021e476f"
- "6f676c652e50726f746f6275662e57656c6c4b6e6f776e54797065736206"
- "70726f746f33";
- char* binary;
- int binary_len;
- hex_to_binary(generated_file, &binary, &binary_len);
- internal_add_generated_file(binary, binary_len,
- generated_pool, true TSRMLS_CC);
- FREE(binary);
- is_inited_file_empty = true;
-}
-
-static void init_file_source_context(TSRMLS_D) {
- if (is_inited_file_source_context) return;
- init_generated_pool_once(TSRMLS_C);
- const char* generated_file =
- "0afb010a24676f6f676c652f70726f746f6275662f736f757263655f636f"
- "6e746578742e70726f746f120f676f6f676c652e70726f746f6275662222"
- "0a0d536f75726365436f6e7465787412110a0966696c655f6e616d651801"
- "200128094295010a13636f6d2e676f6f676c652e70726f746f6275664212"
- "536f75726365436f6e7465787450726f746f50015a41676f6f676c652e67"
- "6f6c616e672e6f72672f67656e70726f746f2f70726f746f6275662f736f"
- "757263655f636f6e746578743b736f757263655f636f6e74657874a20203"
- "475042aa021e476f6f676c652e50726f746f6275662e57656c6c4b6e6f77"
- "6e5479706573620670726f746f33";
- char* binary;
- int binary_len;
- hex_to_binary(generated_file, &binary, &binary_len);
- internal_add_generated_file(binary, binary_len,
- generated_pool, true TSRMLS_CC);
- FREE(binary);
- is_inited_file_source_context = true;
-}
-
-static void init_file_struct(TSRMLS_D) {
- if (is_inited_file_struct) return;
- init_generated_pool_once(TSRMLS_C);
- const char* generated_file =
- "0a81050a1c676f6f676c652f70726f746f6275662f7374727563742e7072"
- "6f746f120f676f6f676c652e70726f746f6275662284010a065374727563"
- "7412330a066669656c647318012003280b32232e676f6f676c652e70726f"
- "746f6275662e5374727563742e4669656c6473456e7472791a450a0b4669"
- "656c6473456e747279120b0a036b657918012001280912250a0576616c75"
- "6518022001280b32162e676f6f676c652e70726f746f6275662e56616c75"
- "653a02380122ea010a0556616c756512300a0a6e756c6c5f76616c756518"
- "012001280e321a2e676f6f676c652e70726f746f6275662e4e756c6c5661"
- "6c7565480012160a0c6e756d6265725f76616c7565180220012801480012"
- "160a0c737472696e675f76616c7565180320012809480012140a0a626f6f"
- "6c5f76616c75651804200128084800122f0a0c7374727563745f76616c75"
- "6518052001280b32172e676f6f676c652e70726f746f6275662e53747275"
- "6374480012300a0a6c6973745f76616c756518062001280b321a2e676f6f"
- "676c652e70726f746f6275662e4c69737456616c7565480042060a046b69"
- "6e6422330a094c69737456616c756512260a0676616c7565731801200328"
- "0b32162e676f6f676c652e70726f746f6275662e56616c75652a1b0a094e"
- "756c6c56616c7565120e0a0a4e554c4c5f56414c554510004281010a1363"
- "6f6d2e676f6f676c652e70726f746f627566420b53747275637450726f74"
- "6f50015a316769746875622e636f6d2f676f6c616e672f70726f746f6275"
- "662f7074797065732f7374727563743b7374727563747062f80101a20203"
- "475042aa021e476f6f676c652e50726f746f6275662e57656c6c4b6e6f77"
- "6e5479706573620670726f746f33";
- char* binary;
- int binary_len;
- hex_to_binary(generated_file, &binary, &binary_len);
- internal_add_generated_file(binary, binary_len,
- generated_pool, true TSRMLS_CC);
- FREE(binary);
- is_inited_file_struct = true;
-}
-
-static void init_file_timestamp(TSRMLS_D) {
- if (is_inited_file_timestamp) return;
- init_generated_pool_once(TSRMLS_C);
- const char* generated_file =
- "0ae7010a1f676f6f676c652f70726f746f6275662f74696d657374616d70"
- "2e70726f746f120f676f6f676c652e70726f746f627566222b0a0954696d"
- "657374616d70120f0a077365636f6e6473180120012803120d0a056e616e"
- "6f73180220012805427e0a13636f6d2e676f6f676c652e70726f746f6275"
- "66420e54696d657374616d7050726f746f50015a2b6769746875622e636f"
- "6d2f676f6c616e672f70726f746f6275662f7074797065732f74696d6573"
- "74616d70f80101a20203475042aa021e476f6f676c652e50726f746f6275"
- "662e57656c6c4b6e6f776e5479706573620670726f746f33";
- char* binary;
- int binary_len;
- hex_to_binary(generated_file, &binary, &binary_len);
- internal_add_generated_file(binary, binary_len,
- generated_pool, true TSRMLS_CC);
- FREE(binary);
- is_inited_file_timestamp = true;
}
-static void init_file_type(TSRMLS_D) {
- if (is_inited_file_type) return;
- init_file_any(TSRMLS_C);
- init_file_source_context(TSRMLS_C);
- init_generated_pool_once(TSRMLS_C);
- const char* generated_file =
- "0aba0c0a1a676f6f676c652f70726f746f6275662f747970652e70726f74"
- "6f120f676f6f676c652e70726f746f6275661a19676f6f676c652f70726f"
- "746f6275662f616e792e70726f746f1a24676f6f676c652f70726f746f62"
- "75662f736f757263655f636f6e746578742e70726f746f22d7010a045479"
- "7065120c0a046e616d6518012001280912260a066669656c647318022003"
- "280b32162e676f6f676c652e70726f746f6275662e4669656c64120e0a06"
- "6f6e656f667318032003280912280a076f7074696f6e7318042003280b32"
- "172e676f6f676c652e70726f746f6275662e4f7074696f6e12360a0e736f"
- "757263655f636f6e7465787418052001280b321e2e676f6f676c652e7072"
- "6f746f6275662e536f75726365436f6e7465787412270a0673796e746178"
- "18062001280e32172e676f6f676c652e70726f746f6275662e53796e7461"
- "7822d5050a054669656c6412290a046b696e6418012001280e321b2e676f"
- "6f676c652e70726f746f6275662e4669656c642e4b696e6412370a0b6361"
- "7264696e616c69747918022001280e32222e676f6f676c652e70726f746f"
- "6275662e4669656c642e43617264696e616c697479120e0a066e756d6265"
- "72180320012805120c0a046e616d6518042001280912100a08747970655f"
- "75726c18062001280912130a0b6f6e656f665f696e646578180720012805"
- "120e0a067061636b656418082001280812280a076f7074696f6e73180920"
- "03280b32172e676f6f676c652e70726f746f6275662e4f7074696f6e1211"
- "0a096a736f6e5f6e616d65180a2001280912150a0d64656661756c745f76"
- "616c7565180b2001280922c8020a044b696e6412100a0c545950455f554e"
- "4b4e4f574e1000120f0a0b545950455f444f55424c451001120e0a0a5459"
- "50455f464c4f41541002120e0a0a545950455f494e5436341003120f0a0b"
- "545950455f55494e5436341004120e0a0a545950455f494e543332100512"
- "100a0c545950455f46495845443634100612100a0c545950455f46495845"
- "4433321007120d0a09545950455f424f4f4c1008120f0a0b545950455f53"
- "5452494e471009120e0a0a545950455f47524f5550100a12100a0c545950"
- "455f4d455353414745100b120e0a0a545950455f4259544553100c120f0a"
- "0b545950455f55494e543332100d120d0a09545950455f454e554d100e12"
- "110a0d545950455f5346495845443332100f12110a0d545950455f534649"
- "58454436341010120f0a0b545950455f53494e5433321011120f0a0b5459"
- "50455f53494e543634101222740a0b43617264696e616c69747912170a13"
- "43415244494e414c4954595f554e4b4e4f574e100012180a144341524449"
- "4e414c4954595f4f5054494f4e414c100112180a1443415244494e414c49"
- "54595f5245515549524544100212180a1443415244494e414c4954595f52"
- "45504541544544100322ce010a04456e756d120c0a046e616d6518012001"
- "2809122d0a09656e756d76616c756518022003280b321a2e676f6f676c65"
- "2e70726f746f6275662e456e756d56616c756512280a076f7074696f6e73"
- "18032003280b32172e676f6f676c652e70726f746f6275662e4f7074696f"
- "6e12360a0e736f757263655f636f6e7465787418042001280b321e2e676f"
- "6f676c652e70726f746f6275662e536f75726365436f6e7465787412270a"
- "0673796e74617818052001280e32172e676f6f676c652e70726f746f6275"
- "662e53796e74617822530a09456e756d56616c7565120c0a046e616d6518"
- "0120012809120e0a066e756d62657218022001280512280a076f7074696f"
- "6e7318032003280b32172e676f6f676c652e70726f746f6275662e4f7074"
- "696f6e223b0a064f7074696f6e120c0a046e616d6518012001280912230a"
- "0576616c756518022001280b32142e676f6f676c652e70726f746f627566"
- "2e416e792a2e0a0653796e74617812110a0d53594e5441585f50524f544f"
- "32100012110a0d53594e5441585f50524f544f331001427d0a13636f6d2e"
- "676f6f676c652e70726f746f62756642095479706550726f746f50015a2f"
- "676f6f676c652e676f6c616e672e6f72672f67656e70726f746f2f70726f"
- "746f6275662f70747970653b7074797065f80101a20203475042aa021e47"
- "6f6f676c652e50726f746f6275662e57656c6c4b6e6f776e547970657362"
- "0670726f746f33";
- char* binary;
- int binary_len;
- hex_to_binary(generated_file, &binary, &binary_len);
- internal_add_generated_file(binary, binary_len,
- generated_pool, true TSRMLS_CC);
- FREE(binary);
- is_inited_file_type = true;
-}
-
-static void init_file_wrappers(TSRMLS_D) {
- if (is_inited_file_wrappers) return;
- init_generated_pool_once(TSRMLS_C);
- const char* generated_file =
- "0abf030a1e676f6f676c652f70726f746f6275662f77726170706572732e"
- "70726f746f120f676f6f676c652e70726f746f627566221c0a0b446f7562"
- "6c6556616c7565120d0a0576616c7565180120012801221b0a0a466c6f61"
- "7456616c7565120d0a0576616c7565180120012802221b0a0a496e743634"
- "56616c7565120d0a0576616c7565180120012803221c0a0b55496e743634"
- "56616c7565120d0a0576616c7565180120012804221b0a0a496e74333256"
- "616c7565120d0a0576616c7565180120012805221c0a0b55496e74333256"
- "616c7565120d0a0576616c756518012001280d221a0a09426f6f6c56616c"
- "7565120d0a0576616c7565180120012808221c0a0b537472696e6756616c"
- "7565120d0a0576616c7565180120012809221b0a0a427974657356616c75"
- "65120d0a0576616c756518012001280c427c0a13636f6d2e676f6f676c65"
- "2e70726f746f627566420d577261707065727350726f746f50015a2a6769"
- "746875622e636f6d2f676f6c616e672f70726f746f6275662f7074797065"
- "732f7772617070657273f80101a20203475042aa021e476f6f676c652e50"
- "726f746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33";
- char* binary;
- int binary_len;
- hex_to_binary(generated_file, &binary, &binary_len);
- internal_add_generated_file(binary, binary_len,
- generated_pool, true TSRMLS_CC);
- FREE(binary);
- is_inited_file_wrappers = true;
-}
-
-// -----------------------------------------------------------------------------
-// Define enum
-// -----------------------------------------------------------------------------
-
-// -----------------------------------------------------------------------------
-// Field_Cardinality
-// -----------------------------------------------------------------------------
-
-static zend_function_entry field_cardinality_methods[] = {
- PHP_ME(Field_Cardinality, name, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Field_Cardinality, value, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- {NULL, NULL, NULL}
-};
+/**
+ * Message::writeWrapperValue()
+ *
+ * Sets the given wrapper field to the given unboxed value. This is called from
+ * generated methods for wrapper fields, eg.
+ *
+ *
+ * public function setDoubleValueUnwrapped($var)
+ * {
+ * $this->writeWrapperValue("double_value", $var);
+ * return $this;
+ * }
+ *
+ * @param Unwrapped field value or null.
+ */
+PHP_METHOD(Message, writeWrapperValue) {
+ Message* intern = (Message*)Z_OBJ_P(getThis());
+ upb_arena *arena = Arena_Get(&intern->arena);
+ char* member;
+ const upb_fielddef *f;
+ upb_msgval msgval;
+ zend_long size;
+ zval* val;
-zend_class_entry* field_cardinality_type;
-
-// Init class entry.
-PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field\\Cardinality",
- Field_Cardinality, field_cardinality)
- zend_declare_class_constant_long(field_cardinality_type,
- "CARDINALITY_UNKNOWN", 19, 0 TSRMLS_CC);
- zend_declare_class_constant_long(field_cardinality_type,
- "CARDINALITY_OPTIONAL", 20, 1 TSRMLS_CC);
- zend_declare_class_constant_long(field_cardinality_type,
- "CARDINALITY_REQUIRED", 20, 2 TSRMLS_CC);
- zend_declare_class_constant_long(field_cardinality_type,
- "CARDINALITY_REPEATED", 20, 3 TSRMLS_CC);
- const char *alias = "Google\\Protobuf\\Field_Cardinality";
-#if PHP_VERSION_ID < 70300
- zend_register_class_alias_ex(alias, strlen(alias), field_cardinality_type TSRMLS_CC);
-#else
- zend_register_class_alias_ex(alias, strlen(alias), field_cardinality_type, 1);
-#endif
-PHP_PROTO_INIT_ENUMCLASS_END
-
-PHP_METHOD(Field_Cardinality, name) {
- PHP_PROTO_LONG value;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) ==
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz", &member, &size, &val) ==
FAILURE) {
return;
}
- switch (value) {
- case 0:
- PHP_PROTO_RETURN_STRING("CARDINALITY_UNKNOWN", 1);
- case 1:
- PHP_PROTO_RETURN_STRING("CARDINALITY_OPTIONAL", 1);
- case 2:
- PHP_PROTO_RETURN_STRING("CARDINALITY_REQUIRED", 1);
- case 3:
- PHP_PROTO_RETURN_STRING("CARDINALITY_REPEATED", 1);
- default:
- zend_throw_exception_ex(
- NULL, 0 TSRMLS_CC,
- "Enum Google\\Protobuf\\Field_Cardinality has no name "
-#if PHP_MAJOR_VERSION < 7
- "defined for value %d.",
-#else
- "defined for value " ZEND_LONG_FMT ".",
-#endif
- value);
- }
-}
-PHP_METHOD(Field_Cardinality, value) {
- char *name = NULL;
- PHP_PROTO_SIZE name_len;
+ f = upb_msgdef_ntof(intern->desc->msgdef, member, size);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) ==
- FAILURE) {
+ if (!f || !upb_msgdef_iswrapper(upb_fielddef_msgsubdef(f))) {
+ zend_throw_exception_ex(NULL, 0, "Message %s has no field %s",
+ upb_msgdef_fullname(intern->desc->msgdef), member);
return;
}
- if (strncmp(name, "CARDINALITY_UNKNOWN", name_len) == 0) RETURN_LONG(0);
- if (strncmp(name, "CARDINALITY_OPTIONAL", name_len) == 0) RETURN_LONG(1);
- if (strncmp(name, "CARDINALITY_REQUIRED", name_len) == 0) RETURN_LONG(2);
- if (strncmp(name, "CARDINALITY_REPEATED", name_len) == 0) RETURN_LONG(3);
-
- zend_throw_exception_ex(
- NULL, 0 TSRMLS_CC,
- "Enum Google\\Protobuf\\Field_Cardinality has no value "
- "defined for name %s.",
- name);
-}
+ if (Z_ISREF_P(val)) {
+ ZVAL_DEREF(val);
+ }
-// -----------------------------------------------------------------------------
-// Field_Kind
-// -----------------------------------------------------------------------------
+ if (Z_TYPE_P(val) == IS_NULL) {
+ upb_msg_clearfield(intern->msg, f);
+ } else {
+ const upb_msgdef *m = upb_fielddef_msgsubdef(f);
+ const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
+ upb_fieldtype_t val_type = upb_fielddef_type(val_f);
+ upb_msg *wrapper;
-static zend_function_entry field_kind_methods[] = {
- PHP_ME(Field_Kind, name, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Field_Kind, value, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- {NULL, NULL, NULL}
-};
+ if (!Convert_PhpToUpb(val, &msgval, val_type, NULL, arena)) {
+ return; // Error is already set.
+ }
-zend_class_entry* field_kind_type;
-
-// Init class entry.
-PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field\\Kind",
- Field_Kind, field_kind)
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_UNKNOWN", 12, 0 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_DOUBLE", 11, 1 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_FLOAT", 10, 2 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_INT64", 10, 3 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_UINT64", 11, 4 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_INT32", 10, 5 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_FIXED64", 12, 6 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_FIXED32", 12, 7 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_BOOL", 9, 8 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_STRING", 11, 9 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_GROUP", 10, 10 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_MESSAGE", 12, 11 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_BYTES", 10, 12 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_UINT32", 11, 13 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_ENUM", 9, 14 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_SFIXED32", 13, 15 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_SFIXED64", 13, 16 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_SINT32", 11, 17 TSRMLS_CC);
- zend_declare_class_constant_long(field_kind_type,
- "TYPE_SINT64", 11, 18 TSRMLS_CC);
- const char *alias = "Google\\Protobuf\\Field_Kind";
-#if PHP_VERSION_ID < 70300
- zend_register_class_alias_ex(alias, strlen(alias), field_kind_type TSRMLS_CC);
-#else
- zend_register_class_alias_ex(alias, strlen(alias), field_kind_type, 1);
-#endif
-PHP_PROTO_INIT_ENUMCLASS_END
-
-PHP_METHOD(Field_Kind, name) {
- PHP_PROTO_LONG value;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) ==
- FAILURE) {
- return;
- }
- switch (value) {
- case 0:
- PHP_PROTO_RETURN_STRING("TYPE_UNKNOWN", 1);
- case 1:
- PHP_PROTO_RETURN_STRING("TYPE_DOUBLE", 1);
- case 2:
- PHP_PROTO_RETURN_STRING("TYPE_FLOAT", 1);
- case 3:
- PHP_PROTO_RETURN_STRING("TYPE_INT64", 1);
- case 4:
- PHP_PROTO_RETURN_STRING("TYPE_UINT64", 1);
- case 5:
- PHP_PROTO_RETURN_STRING("TYPE_INT32", 1);
- case 6:
- PHP_PROTO_RETURN_STRING("TYPE_FIXED64", 1);
- case 7:
- PHP_PROTO_RETURN_STRING("TYPE_FIXED32", 1);
- case 8:
- PHP_PROTO_RETURN_STRING("TYPE_BOOL", 1);
- case 9:
- PHP_PROTO_RETURN_STRING("TYPE_STRING", 1);
- case 10:
- PHP_PROTO_RETURN_STRING("TYPE_GROUP", 1);
- case 11:
- PHP_PROTO_RETURN_STRING("TYPE_MESSAGE", 1);
- case 12:
- PHP_PROTO_RETURN_STRING("TYPE_BYTES", 1);
- case 13:
- PHP_PROTO_RETURN_STRING("TYPE_UINT32", 1);
- case 14:
- PHP_PROTO_RETURN_STRING("TYPE_ENUM", 1);
- case 15:
- PHP_PROTO_RETURN_STRING("TYPE_SFIXED32", 1);
- case 16:
- PHP_PROTO_RETURN_STRING("TYPE_SFIXED64", 1);
- case 17:
- PHP_PROTO_RETURN_STRING("TYPE_SINT32", 1);
- case 18:
- PHP_PROTO_RETURN_STRING("TYPE_SINT64", 1);
- default:
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
- "Enum Google\\Protobuf\\Field_Kind has no name "
-#if PHP_MAJOR_VERSION < 7
- "defined for value %d.",
-#else
- "defined for value " ZEND_LONG_FMT ".",
-#endif
- value);
+ wrapper = upb_msg_mutable(intern->msg, f, arena).msg;
+ upb_msg_set(wrapper, val_f, msgval, arena);
}
}
-PHP_METHOD(Field_Kind, value) {
- char *name = NULL;
- PHP_PROTO_SIZE name_len;
+/**
+ * Message::whichOneof()
+ *
+ * Given a oneof name, returns the name of the field that is set for this oneof,
+ * or otherwise the empty string.
+ *
+ * @return string The field name in this oneof that is currently set.
+ */
+PHP_METHOD(Message, whichOneof) {
+ Message* intern = (Message*)Z_OBJ_P(getThis());
+ const upb_oneofdef* oneof;
+ const upb_fielddef* field;
+ char* name;
+ zend_long len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) ==
- FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &len) == FAILURE) {
return;
}
- if (strncmp(name, "TYPE_UNKNOWN", name_len) == 0) RETURN_LONG(0);
- if (strncmp(name, "TYPE_DOUBLE", name_len) == 0) RETURN_LONG(1);
- if (strncmp(name, "TYPE_FLOAT", name_len) == 0) RETURN_LONG(2);
- if (strncmp(name, "TYPE_INT64", name_len) == 0) RETURN_LONG(3);
- if (strncmp(name, "TYPE_UINT64", name_len) == 0) RETURN_LONG(4);
- if (strncmp(name, "TYPE_INT32", name_len) == 0) RETURN_LONG(5);
- if (strncmp(name, "TYPE_FIXED64", name_len) == 0) RETURN_LONG(6);
- if (strncmp(name, "TYPE_FIXED32", name_len) == 0) RETURN_LONG(7);
- if (strncmp(name, "TYPE_BOOL", name_len) == 0) RETURN_LONG(8);
- if (strncmp(name, "TYPE_STRING", name_len) == 0) RETURN_LONG(9);
- if (strncmp(name, "TYPE_GROUP", name_len) == 0) RETURN_LONG(10);
- if (strncmp(name, "TYPE_MESSAGE", name_len) == 0) RETURN_LONG(11);
- if (strncmp(name, "TYPE_BYTES", name_len) == 0) RETURN_LONG(12);
- if (strncmp(name, "TYPE_UINT32", name_len) == 0) RETURN_LONG(13);
- if (strncmp(name, "TYPE_ENUM", name_len) == 0) RETURN_LONG(14);
- if (strncmp(name, "TYPE_SFIXED32", name_len) == 0) RETURN_LONG(15);
- if (strncmp(name, "TYPE_SFIXED64", name_len) == 0) RETURN_LONG(16);
- if (strncmp(name, "TYPE_SINT32", name_len) == 0) RETURN_LONG(17);
- if (strncmp(name, "TYPE_SINT64", name_len) == 0) RETURN_LONG(18);
-
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
- "Enum Google\\Protobuf\\Field_Kind has no value "
- "defined for name %s.",
- name);
-}
-
-// -----------------------------------------------------------------------------
-// NullValue
-// -----------------------------------------------------------------------------
-
-static zend_function_entry null_value_methods[] = {
- PHP_ME(NullValue, name, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(NullValue, value, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* null_value_type;
+ oneof = upb_msgdef_ntoo(intern->desc->msgdef, name, len);
-// Init class entry.
-PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\NullValue",
- NullValue, null_value)
- zend_declare_class_constant_long(null_value_type,
- "NULL_VALUE", 10, 0 TSRMLS_CC);
-PHP_PROTO_INIT_ENUMCLASS_END
-
-PHP_METHOD(NullValue, name) {
- PHP_PROTO_LONG value;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) ==
- FAILURE) {
+ if (!oneof) {
+ zend_throw_exception_ex(NULL, 0, "Message %s has no oneof %s",
+ upb_msgdef_fullname(intern->desc->msgdef), name);
return;
}
- switch (value) {
- case 0:
- PHP_PROTO_RETURN_STRING("NULL_VALUE", 1);
- default:
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
- "Enum Google\\Protobuf\\NullValue has no name "
-#if PHP_MAJOR_VERSION < 7
- "defined for value %d.",
-#else
- "defined for value " ZEND_LONG_FMT ".",
-#endif
- value);
- }
+
+ field = upb_msg_whichoneof(intern->msg, oneof);
+ RETURN_STRING(field ? upb_fielddef_name(field) : "");
}
-PHP_METHOD(NullValue, value) {
- char *name = NULL;
- PHP_PROTO_SIZE name_len;
+/**
+ * Message::readOneof()
+ *
+ * Returns the contents of the given oneof field, given a field number. Called
+ * from generated code methods such as:
+ *
+ * public function getDoubleValueOneof()
+ * {
+ * return $this->readOneof(10);
+ * }
+ *
+ * @return object The oneof's field value.
+ */
+PHP_METHOD(Message, readOneof) {
+ Message* intern = (Message*)Z_OBJ_P(getThis());
+ zend_long field_num;
+ const upb_fielddef* f;
+ zval ret;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) ==
- FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &field_num) == FAILURE) {
return;
}
- if (strncmp(name, "NULL_VALUE", name_len) == 0) RETURN_LONG(0);
-
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
- "Enum Google\\Protobuf\\NullValue has no value "
- "defined for name %s.",
- name);
-}
-
-// -----------------------------------------------------------------------------
-// Syntax
-// -----------------------------------------------------------------------------
-
-static zend_function_entry syntax_methods[] = {
- PHP_ME(Syntax, name, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Syntax, value, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- {NULL, NULL, NULL}
-};
+ f = upb_msgdef_itof(intern->desc->msgdef, field_num);
-zend_class_entry* syntax_type;
+ if (!f || !upb_fielddef_realcontainingoneof(f)) {
+ php_error_docref(NULL, E_USER_ERROR,
+ "Internal error, no such oneof field %d\n",
+ (int)field_num);
+ }
-// Init class entry.
-PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Syntax",
- Syntax, syntax)
- zend_declare_class_constant_long(syntax_type,
- "SYNTAX_PROTO2", 13, 0 TSRMLS_CC);
- zend_declare_class_constant_long(syntax_type,
- "SYNTAX_PROTO3", 13, 1 TSRMLS_CC);
-PHP_PROTO_INIT_ENUMCLASS_END
+ {
+ upb_msgval msgval = upb_msg_get(intern->msg, f);
+ const Descriptor *subdesc = Descriptor_GetFromFieldDef(f);
+ Convert_UpbToPhp(msgval, &ret, upb_fielddef_type(f), subdesc,
+ &intern->arena);
+ }
+
+ RETURN_ZVAL(&ret, 1, 0);
+}
+
+/**
+ * Message::writeOneof()
+ *
+ * Sets the contents of the given oneof field, given a field number. Called
+ * from generated code methods such as:
+ *
+ * public function setDoubleValueOneof($var)
+ * {
+ * GPBUtil::checkMessage($var, \Google\Protobuf\DoubleValue::class);
+ * $this->writeOneof(10, $var);
+ *
+ * return $this;
+ * }
+ *
+ * The C extension version of GPBUtil::check*() does nothing, so we perform
+ * all type checking and conversion here.
+ *
+ * @param integer The field number we are setting.
+ * @param object The field value we want to set.
+ */
+PHP_METHOD(Message, writeOneof) {
+ Message* intern = (Message*)Z_OBJ_P(getThis());
+ zend_long field_num;
+ const upb_fielddef* f;
+ upb_arena *arena = Arena_Get(&intern->arena);
+ upb_msgval msgval;
+ zval* val;
-PHP_METHOD(Syntax, name) {
- PHP_PROTO_LONG value;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) ==
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz", &field_num, &val) ==
FAILURE) {
return;
}
- switch (value) {
- case 0:
- PHP_PROTO_RETURN_STRING("SYNTAX_PROTO2", 1);
- case 1:
- PHP_PROTO_RETURN_STRING("SYNTAX_PROTO3", 1);
- default:
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
- "Enum Google\\Protobuf\\Syntax has no name "
-#if PHP_MAJOR_VERSION < 7
- "defined for value %d.",
-#else
- "defined for value " ZEND_LONG_FMT ".",
-#endif
- value);
- }
-}
-PHP_METHOD(Syntax, value) {
- char *name = NULL;
- PHP_PROTO_SIZE name_len;
+ f = upb_msgdef_itof(intern->desc->msgdef, field_num);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) ==
- FAILURE) {
+ if (!Convert_PhpToUpb(val, &msgval, upb_fielddef_type(f),
+ Descriptor_GetFromFieldDef(f), arena)) {
return;
}
- if (strncmp(name, "SYNTAX_PROTO2", name_len) == 0) RETURN_LONG(0);
- if (strncmp(name, "SYNTAX_PROTO3", name_len) == 0) RETURN_LONG(1);
-
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
- "Enum Google\\Protobuf\\Syntax has no value "
- "defined for name %s.",
- name);
+ upb_msg_set(intern->msg, f, msgval, arena);
}
-// -----------------------------------------------------------------------------
-// Define message
-// -----------------------------------------------------------------------------
-
-// -----------------------------------------------------------------------------
-// Any
-// -----------------------------------------------------------------------------
-
-static zend_function_entry any_methods[] = {
- PHP_ME(Any, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Any, getTypeUrl, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Any, setTypeUrl, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Any, getValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Any, setValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Any, pack, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Any, unpack, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Any, is, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
+static zend_function_entry Message_methods[] = {
+ PHP_ME(Message, clear, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Message, discardUnknownFields, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Message, serializeToString, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Message, mergeFromString, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Message, serializeToJsonString, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Message, mergeFromJsonString, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Message, mergeFrom, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Message, readWrapperValue, NULL, ZEND_ACC_PROTECTED)
+ PHP_ME(Message, writeWrapperValue, NULL, ZEND_ACC_PROTECTED)
+ PHP_ME(Message, readOneof, NULL, ZEND_ACC_PROTECTED)
+ PHP_ME(Message, writeOneof, NULL, ZEND_ACC_PROTECTED)
+ PHP_ME(Message, whichOneof, NULL, ZEND_ACC_PROTECTED)
+ PHP_ME(Message, __construct, NULL, ZEND_ACC_PROTECTED)
+ ZEND_FE_END
};
-zend_class_entry* any_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Any", Any, any)
- zend_declare_property_string(any_type, "type_url", strlen("type_url"),
- "" ,ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_string(any_type, "value", strlen("value"),
- "" ,ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-static void hex_to_binary(const char* hex, char** binary, int* binary_len) {
- int i;
- int hex_len = strlen(hex);
- *binary_len = hex_len / 2;
- *binary = ALLOC_N(char, *binary_len);
- for (i = 0; i < *binary_len; i++) {
- char value = 0;
- if (hex[i * 2] >= '0' && hex[i * 2] <= '9') {
- value += (hex[i * 2] - '0') * 16;
- } else {
- value += (hex[i * 2] - 'a' + 10) * 16;
- }
- if (hex[i * 2 + 1] >= '0' && hex[i * 2 + 1] <= '9') {
- value += hex[i * 2 + 1] - '0';
- } else {
- value += hex[i * 2 + 1] - 'a' + 10;
- }
- (*binary)[i] = value;
- }
-}
+/**
+ * Message_ModuleInit()
+ *
+ * Called when the C extension is loaded to register all types.
+ */
+void Message_ModuleInit() {
+ zend_class_entry tmp_ce;
+ zend_object_handlers *h = &message_object_handlers;
-PHP_METHOD(Any, __construct) {
- init_file_any(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
+ INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\Message",
+ Message_methods);
-PHP_PROTO_FIELD_ACCESSORS(Any, any, TypeUrl, "type_url")
-PHP_PROTO_FIELD_ACCESSORS(Any, any, Value, "value")
-
-PHP_METHOD(Any, unpack) {
- // Get type url.
- zval type_url_member;
- PHP_PROTO_ZVAL_STRING(&type_url_member, "type_url", 1);
- PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
- zval* type_url_php = php_proto_message_read_property(
- getThis(), &type_url_member PHP_PROTO_TSRMLS_CC);
- zval_dtor(&type_url_member);
- PHP_PROTO_FAKE_SCOPE_END;
-
- // Get fully-qualified name from type url.
- size_t url_prefix_len = strlen(TYPE_URL_PREFIX);
- const char* type_url = Z_STRVAL_P(type_url_php);
- size_t type_url_len = Z_STRLEN_P(type_url_php);
-
- if (url_prefix_len > type_url_len ||
- strncmp(TYPE_URL_PREFIX, type_url, url_prefix_len) != 0) {
- zend_throw_exception(
- NULL, "Type url needs to be type.googleapis.com/fully-qualified",
- 0 TSRMLS_CC);
- return;
- }
+ message_ce = zend_register_internal_class(&tmp_ce);
+ message_ce->create_object = Message_create;
- const char* fully_qualified_name = type_url + url_prefix_len;
- DescriptorInternal* desc = get_proto_desc(fully_qualified_name);
- if (desc == NULL) {
- zend_throw_exception(
- NULL, "Specified message in any hasn't been added to descriptor pool",
- 0 TSRMLS_CC);
- return;
- }
- register_class(desc, false TSRMLS_CC);
- zend_class_entry* klass = desc->klass;
- ZVAL_OBJ(return_value, klass->create_object(klass TSRMLS_CC));
- MessageHeader* msg = UNBOX(MessageHeader, return_value);
- custom_data_init(klass, msg PHP_PROTO_TSRMLS_CC);
-
- // Get value.
- zval value_member;
- PHP_PROTO_ZVAL_STRING(&value_member, "value", 1);
- PHP_PROTO_FAKE_SCOPE_RESTART(any_type);
- zval* value = php_proto_message_read_property(
- getThis(), &value_member PHP_PROTO_TSRMLS_CC);
- zval_dtor(&value_member);
- PHP_PROTO_FAKE_SCOPE_END;
-
- merge_from_string(Z_STRVAL_P(value), Z_STRLEN_P(value), desc, msg);
+ memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
+ h->dtor_obj = Message_dtor;
+ h->read_property = Message_read_property;
+ h->write_property = Message_write_property;
+ h->get_properties = Message_get_properties;
+ h->get_property_ptr_ptr = Message_get_property_ptr_ptr;
}
-
-PHP_METHOD(Any, pack) {
- zval* val;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &val) ==
- FAILURE) {
- return;
- }
-
- if (!instanceof_function(Z_OBJCE_P(val), message_type TSRMLS_CC)) {
- zend_error(E_USER_ERROR, "Given value is not an instance of Message.");
- return;
- }
-
- // Set value by serialized data.
- zval data;
- serialize_to_string(val, &data TSRMLS_CC);
-
- zval member;
- PHP_PROTO_ZVAL_STRING(&member, "value", 1);
-
- PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
- message_handlers->write_property(getThis(), &member, &data,
- NULL PHP_PROTO_TSRMLS_CC);
- zval_dtor(&data);
- zval_dtor(&member);
- PHP_PROTO_FAKE_SCOPE_END;
-
- // Set type url.
- DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(val));
- const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef);
- size_t type_url_len =
- strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1;
- char* type_url = ALLOC_N(char, type_url_len);
- sprintf(type_url, "%s%s", TYPE_URL_PREFIX, fully_qualified_name);
- zval type_url_php;
- PHP_PROTO_ZVAL_STRING(&type_url_php, type_url, 1);
- PHP_PROTO_ZVAL_STRING(&member, "type_url", 1);
-
- PHP_PROTO_FAKE_SCOPE_RESTART(any_type);
- message_handlers->write_property(getThis(), &member, &type_url_php,
- NULL PHP_PROTO_TSRMLS_CC);
- zval_dtor(&type_url_php);
- zval_dtor(&member);
- PHP_PROTO_FAKE_SCOPE_END;
- FREE(type_url);
-}
-
-PHP_METHOD(Any, is) {
- zend_class_entry *klass = NULL;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "C", &klass) ==
- FAILURE) {
- return;
- }
-
- DescriptorInternal* desc = get_ce_desc(klass);
- if (desc == NULL) {
- RETURN_BOOL(false);
- }
-
- // Create corresponded type url.
- const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef);
- size_t type_url_len =
- strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1;
- char* type_url = ALLOC_N(char, type_url_len);
- sprintf(type_url, "%s%s", TYPE_URL_PREFIX, fully_qualified_name);
-
- // Fetch stored type url.
- zval member;
- PHP_PROTO_ZVAL_STRING(&member, "type_url", 1);
- PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
- zval* value =
- php_proto_message_read_property(getThis(), &member PHP_PROTO_TSRMLS_CC);
- zval_dtor(&member);
- PHP_PROTO_FAKE_SCOPE_END;
-
- // Compare two type url.
- bool is = strcmp(type_url, Z_STRVAL_P(value)) == 0;
- FREE(type_url);
-
- RETURN_BOOL(is);
-}
-
-// -----------------------------------------------------------------------------
-// Duration
-// -----------------------------------------------------------------------------
-
-static zend_function_entry duration_methods[] = {
- PHP_ME(Duration, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Duration, getSeconds, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Duration, setSeconds, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Duration, getNanos, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Duration, setNanos, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* duration_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Duration",
- Duration, duration)
- zend_declare_property_long(duration_type, "seconds", strlen("seconds"),
- 0 ,ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_long(duration_type, "nanos", strlen("nanos"),
- 0 ,ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Duration, __construct) {
- init_file_duration(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Duration, duration, Seconds, "seconds")
-PHP_PROTO_FIELD_ACCESSORS(Duration, duration, Nanos, "nanos")
-
-// -----------------------------------------------------------------------------
-// Timestamp
-// -----------------------------------------------------------------------------
-
-static zend_function_entry timestamp_methods[] = {
- PHP_ME(Timestamp, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Timestamp, fromDateTime, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Timestamp, toDateTime, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Timestamp, getSeconds, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Timestamp, setSeconds, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Timestamp, getNanos, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Timestamp, setNanos, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* timestamp_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Timestamp",
- Timestamp, timestamp)
- zend_declare_property_long(timestamp_type, "seconds", strlen("seconds"),
- 0 ,ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_long(timestamp_type, "nanos", strlen("nanos"),
- 0 ,ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-static PHP_METHOD(Timestamp, __construct) {
- init_file_timestamp(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Timestamp, timestamp, Seconds, "seconds")
-PHP_PROTO_FIELD_ACCESSORS(Timestamp, timestamp, Nanos, "nanos")
-
-PHP_METHOD(Timestamp, fromDateTime) {
- zval* datetime;
-
- PHP_PROTO_CE_DECLARE date_interface_ce;
- if (php_proto_zend_lookup_class("\\DatetimeInterface", 18,
- &date_interface_ce) == FAILURE) {
- zend_error(E_ERROR, "Make sure date extension is enabled.");
- return;
- }
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &datetime,
- PHP_PROTO_CE_UNREF(date_interface_ce)) == FAILURE) {
- zend_error(E_USER_ERROR, "Expect DatetimeInterface.");
- return;
- }
-
- int64_t timestamp_seconds;
- {
- zval retval;
- zval function_name;
-
-#if PHP_MAJOR_VERSION < 7
- INIT_ZVAL(retval);
- INIT_ZVAL(function_name);
-#endif
-
- PHP_PROTO_ZVAL_STRING(&function_name, "date_timestamp_get", 1);
-
- if (call_user_function(EG(function_table), NULL, &function_name, &retval, 1,
- ZVAL_PTR_TO_CACHED_PTR(datetime) TSRMLS_CC) == FAILURE) {
- zend_error(E_ERROR, "Cannot get timestamp from DateTime.");
- return;
- }
-
- protobuf_convert_to_int64(&retval, ×tamp_seconds);
-
- zval_dtor(&retval);
- zval_dtor(&function_name);
- }
-
- int64_t timestamp_micros;
- {
- zval retval;
- zval function_name;
- zval format_string;
-
-#if PHP_MAJOR_VERSION < 7
- INIT_ZVAL(retval);
- INIT_ZVAL(function_name);
- INIT_ZVAL(format_string);
-#endif
-
- PHP_PROTO_ZVAL_STRING(&function_name, "date_format", 1);
- PHP_PROTO_ZVAL_STRING(&format_string, "u", 1);
-
- CACHED_VALUE params[2] = {
- ZVAL_PTR_TO_CACHED_VALUE(datetime),
- ZVAL_TO_CACHED_VALUE(format_string),
- };
-
- if (call_user_function(EG(function_table), NULL, &function_name, &retval,
- ARRAY_SIZE(params), params TSRMLS_CC) == FAILURE) {
- zend_error(E_ERROR, "Cannot format DateTime.");
- return;
- }
-
- protobuf_convert_to_int64(&retval, ×tamp_micros);
-
- zval_dtor(&retval);
- zval_dtor(&function_name);
- zval_dtor(&format_string);
- }
-
- // Set seconds
- MessageHeader* self = UNBOX(MessageHeader, getThis());
- const upb_fielddef* field =
- upb_msgdef_ntofz(self->descriptor->msgdef, "seconds");
- void* storage = message_data(self);
- void* memory = slot_memory(self->descriptor->layout, storage, field);
- *(int64_t*)memory = timestamp_seconds;
-
- // Set nanos
- field = upb_msgdef_ntofz(self->descriptor->msgdef, "nanos");
- storage = message_data(self);
- memory = slot_memory(self->descriptor->layout, storage, field);
- *(int32_t*)memory = timestamp_micros * 1000;
-
- RETURN_NULL();
-}
-
-PHP_METHOD(Timestamp, toDateTime) {
- // Get seconds
- MessageHeader* self = UNBOX(MessageHeader, getThis());
- const upb_fielddef* field =
- upb_msgdef_ntofz(self->descriptor->msgdef, "seconds");
- void* storage = message_data(self);
- void* memory = slot_memory(self->descriptor->layout, storage, field);
- int64_t seconds = *(int64_t*)memory;
-
- // Get nanos
- field = upb_msgdef_ntofz(self->descriptor->msgdef, "nanos");
- memory = slot_memory(self->descriptor->layout, storage, field);
- int32_t nanos = *(int32_t*)memory;
-
- // Get formatted time string.
- char formatted_time[32];
- snprintf(formatted_time, sizeof(formatted_time), "%" PRId64 ".%06" PRId32,
- seconds, nanos / 1000);
-
- // Create Datetime object.
- zval datetime;
- zval function_name;
- zval format_string;
- zval formatted_time_php;
-
-#if PHP_MAJOR_VERSION < 7
- INIT_ZVAL(function_name);
- INIT_ZVAL(format_string);
- INIT_ZVAL(formatted_time_php);
-#endif
-
- PHP_PROTO_ZVAL_STRING(&function_name, "date_create_from_format", 1);
- PHP_PROTO_ZVAL_STRING(&format_string, "U.u", 1);
- PHP_PROTO_ZVAL_STRING(&formatted_time_php, formatted_time, 1);
-
- CACHED_VALUE params[2] = {
- ZVAL_TO_CACHED_VALUE(format_string),
- ZVAL_TO_CACHED_VALUE(formatted_time_php),
- };
-
- if (call_user_function(EG(function_table), NULL, &function_name, &datetime,
- ARRAY_SIZE(params), params TSRMLS_CC) == FAILURE) {
- zend_error(E_ERROR, "Cannot create DateTime.");
- return;
- }
-
- zval_dtor(&function_name);
- zval_dtor(&format_string);
- zval_dtor(&formatted_time_php);
-
-#if PHP_MAJOR_VERSION < 7
- zval* datetime_ptr = &datetime;
- PHP_PROTO_RETVAL_ZVAL(datetime_ptr);
-#else
- ZVAL_OBJ(return_value, Z_OBJ(datetime));
-#endif
-}
-
-// -----------------------------------------------------------------------------
-// Api
-// -----------------------------------------------------------------------------
-
-static zend_function_entry api_methods[] = {
- PHP_ME(Api, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Api, getName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Api, setName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Api, getMethods, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Api, setMethods, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Api, getOptions, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Api, setOptions, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Api, getVersion, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Api, setVersion, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Api, getSourceContext, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Api, setSourceContext, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Api, getMixins, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Api, setMixins, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Api, getSyntax, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Api, setSyntax, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* api_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Api",
- Api, api)
- zend_declare_property_string(api_type, "name", strlen("name"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_null(api_type, "methods", strlen("methods"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_null(api_type, "options", strlen("options"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_string(api_type, "version", strlen("version"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_null(api_type, "source_context", strlen("source_context"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_null(api_type, "mixins", strlen("mixins"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_long(api_type, "syntax", strlen("syntax"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Api, __construct) {
- init_file_api(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Api, api, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(Api, api, Methods, "methods")
-PHP_PROTO_FIELD_ACCESSORS(Api, api, Options, "options")
-PHP_PROTO_FIELD_ACCESSORS(Api, api, Version, "version")
-PHP_PROTO_FIELD_ACCESSORS(Api, api, SourceContext, "source_context")
-PHP_PROTO_FIELD_ACCESSORS(Api, api, Mixins, "mixins")
-PHP_PROTO_FIELD_ACCESSORS(Api, api, Syntax, "syntax")
-
-// -----------------------------------------------------------------------------
-// BoolValue
-// -----------------------------------------------------------------------------
-
-static zend_function_entry bool_value_methods[] = {
- PHP_ME(BoolValue, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(BoolValue, getValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(BoolValue, setValue, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* bool_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\BoolValue",
- BoolValue, bool_value)
- zend_declare_property_bool(bool_value_type, "value", strlen("value"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(BoolValue, __construct) {
- init_file_wrappers(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(BoolValue, bool_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// BytesValue
-// -----------------------------------------------------------------------------
-
-static zend_function_entry bytes_value_methods[] = {
- PHP_ME(BytesValue, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(BytesValue, getValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(BytesValue, setValue, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* bytes_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\BytesValue",
- BytesValue, bytes_value)
- zend_declare_property_string(bytes_value_type, "value", strlen("value"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(BytesValue, __construct) {
- init_file_wrappers(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(BytesValue, bytes_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// DoubleValue
-// -----------------------------------------------------------------------------
-
-static zend_function_entry double_value_methods[] = {
- PHP_ME(DoubleValue, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(DoubleValue, getValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(DoubleValue, setValue, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* double_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\DoubleValue",
- DoubleValue, double_value)
- zend_declare_property_double(double_value_type, "value", strlen("value"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(DoubleValue, __construct) {
- init_file_wrappers(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(DoubleValue, double_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// Enum
-// -----------------------------------------------------------------------------
-
-static zend_function_entry enum_methods[] = {
- PHP_ME(Enum, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Enum, getName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Enum, setName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Enum, getEnumvalue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Enum, setEnumvalue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Enum, getOptions, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Enum, setOptions, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Enum, getSourceContext, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Enum, setSourceContext, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Enum, getSyntax, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Enum, setSyntax, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* enum_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Enum",
- Enum, enum)
- zend_declare_property_string(enum_type, "name", strlen("name"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_null(enum_type, "enumvalue", strlen("enumvalue"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_null(enum_type, "options", strlen("options"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_null(enum_type, "source_context", strlen("source_context"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_long(enum_type, "syntax", strlen("syntax"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Enum, __construct) {
- init_file_type(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Enum, enum, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(Enum, enum, Enumvalue, "enumvalue")
-PHP_PROTO_FIELD_ACCESSORS(Enum, enum, Options, "options")
-PHP_PROTO_FIELD_ACCESSORS(Enum, enum, SourceContext, "source_context")
-PHP_PROTO_FIELD_ACCESSORS(Enum, enum, Syntax, "syntax")
-
-// -----------------------------------------------------------------------------
-// EnumValue
-// -----------------------------------------------------------------------------
-
-static zend_function_entry enum_value_methods[] = {
- PHP_ME(EnumValue, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(EnumValue, getName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(EnumValue, setName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(EnumValue, getNumber, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(EnumValue, setNumber, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(EnumValue, getOptions, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(EnumValue, setOptions, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* enum_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\EnumValue",
- EnumValue, enum_value)
- zend_declare_property_string(enum_value_type, "name", strlen("name"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_long(enum_value_type, "number", strlen("number"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_null(enum_value_type, "options", strlen("options"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(EnumValue, __construct) {
- init_file_type(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(EnumValue, enum_value, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(EnumValue, enum_value, Number, "number")
-PHP_PROTO_FIELD_ACCESSORS(EnumValue, enum_value, Options, "options")
-
-// -----------------------------------------------------------------------------
-// FieldMask
-// -----------------------------------------------------------------------------
-
-static zend_function_entry field_mask_methods[] = {
- PHP_ME(FieldMask, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(FieldMask, getPaths, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(FieldMask, setPaths, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* field_mask_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\FieldMask",
- FieldMask, field_mask)
- zend_declare_property_null(field_mask_type, "paths", strlen("paths"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(FieldMask, __construct) {
- init_file_field_mask(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(FieldMask, field_mask, Paths, "paths")
-
-// -----------------------------------------------------------------------------
-// Field
-// -----------------------------------------------------------------------------
-
-static zend_function_entry field_methods[] = {
- PHP_ME(Field, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, getKind, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, setKind, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, getCardinality, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, setCardinality, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, getNumber, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, setNumber, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, getName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, setName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, getTypeUrl, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, setTypeUrl, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, getOneofIndex, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, setOneofIndex, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, getPacked, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, setPacked, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, getOptions, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, setOptions, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, getJsonName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, setJsonName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, getDefaultValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Field, setDefaultValue, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* field_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Field",
- Field, field)
- zend_declare_property_long(field_type, "kind", strlen("kind"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_long(field_type, "cardinality", strlen("cardinality"),
- 0, ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_long(field_type, "number", strlen("number"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_string(field_type, "name", strlen("name"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_string(field_type, "type_url", strlen("type_url"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_long(field_type, "oneof_index", strlen("oneof_index"),
- 0, ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_bool(field_type, "packed", strlen("packed"), false,
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_null(field_type, "options", strlen("options"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_string(field_type, "json_name", strlen("json_name"),
- "", ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_string(field_type, "default_value",
- strlen("default_value"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Field, __construct) {
- init_file_type(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Field, field, Kind, "kind")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, Cardinality, "cardinality")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, Number, "number")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, TypeUrl, "type_url")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, OneofIndex, "oneof_index")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, Packed, "packed")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, Options, "options")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, JsonName, "json_name")
-PHP_PROTO_FIELD_ACCESSORS(Field, field, DefaultValue, "default_value")
-
-// -----------------------------------------------------------------------------
-// FloatValue
-// -----------------------------------------------------------------------------
-
-static zend_function_entry float_value_methods[] = {
- PHP_ME(FloatValue, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(FloatValue, getValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(FloatValue, setValue, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* float_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\FloatValue",
- FloatValue, float_value)
- zend_declare_property_double(float_value_type, "value", strlen("value"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(FloatValue, __construct) {
- init_file_wrappers(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(FloatValue, float_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// GPBEmpty
-// -----------------------------------------------------------------------------
-
-static zend_function_entry empty_methods[] = {
- PHP_ME(GPBEmpty, __construct, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* empty_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\GPBEmpty",
- GPBEmpty, empty)
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(GPBEmpty, __construct) {
- init_file_empty(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-
-// -----------------------------------------------------------------------------
-// Int32Value
-// -----------------------------------------------------------------------------
-
-static zend_function_entry int32_value_methods[] = {
- PHP_ME(Int32Value, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Int32Value, getValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Int32Value, setValue, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* int32_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Int32Value",
- Int32Value, int32_value)
- zend_declare_property_long(int32_value_type, "value", strlen("value"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Int32Value, __construct) {
- init_file_wrappers(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Int32Value, int32_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// Int64Value
-// -----------------------------------------------------------------------------
-
-static zend_function_entry int64_value_methods[] = {
- PHP_ME(Int64Value, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Int64Value, getValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Int64Value, setValue, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* int64_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Int64Value",
- Int64Value, int64_value)
- zend_declare_property_long(int64_value_type, "value", strlen("value"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Int64Value, __construct) {
- init_file_wrappers(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Int64Value, int64_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// ListValue
-// -----------------------------------------------------------------------------
-
-static zend_function_entry list_value_methods[] = {
- PHP_ME(ListValue, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(ListValue, getValues, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(ListValue, setValues, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* list_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\ListValue",
- ListValue, list_value)
- zend_declare_property_null(list_value_type, "values", strlen("values"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(ListValue, __construct) {
- init_file_struct(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(ListValue, list_value, Values, "values")
-
-// -----------------------------------------------------------------------------
-// Method
-// -----------------------------------------------------------------------------
-
-static zend_function_entry method_methods[] = {
- PHP_ME(Method, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Method, getName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Method, setName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Method, getRequestTypeUrl, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Method, setRequestTypeUrl, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Method, getRequestStreaming, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Method, setRequestStreaming, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Method, getResponseTypeUrl, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Method, setResponseTypeUrl, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Method, getResponseStreaming, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Method, setResponseStreaming, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Method, getOptions, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Method, setOptions, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Method, getSyntax, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Method, setSyntax, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* method_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Method",
- Method, method)
- zend_declare_property_string(method_type, "name", strlen("name"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_string(method_type, "request_type_url",
- strlen("request_type_url"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_bool(method_type, "request_streaming",
- strlen("request_streaming"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_string(method_type, "response_type_url",
- strlen("response_type_url"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_bool(method_type, "response_streaming",
- strlen("response_streaming"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_null(method_type, "options", strlen("options"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_long(method_type, "syntax", strlen("syntax"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Method, __construct) {
- init_file_api(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Method, method, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(Method, method, RequestTypeUrl, "request_type_url")
-PHP_PROTO_FIELD_ACCESSORS(Method, method, RequestStreaming, "request_streaming")
-PHP_PROTO_FIELD_ACCESSORS(Method, method, ResponseTypeUrl, "response_type_url")
-PHP_PROTO_FIELD_ACCESSORS(Method, method, ResponseStreaming, "response_streaming")
-PHP_PROTO_FIELD_ACCESSORS(Method, method, Options, "options")
-PHP_PROTO_FIELD_ACCESSORS(Method, method, Syntax, "syntax")
-
-// -----------------------------------------------------------------------------
-// Mixin
-// -----------------------------------------------------------------------------
-
-static zend_function_entry mixin_methods[] = {
- PHP_ME(Mixin, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Mixin, getName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Mixin, setName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Mixin, getRoot, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Mixin, setRoot, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* mixin_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Mixin",
- Mixin, mixin)
- zend_declare_property_string(mixin_type, "name", strlen("name"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_string(mixin_type, "root", strlen("root"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Mixin, __construct) {
- init_file_api(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Mixin, mixin, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(Mixin, mixin, Root, "root")
-
-// -----------------------------------------------------------------------------
-// Option
-// -----------------------------------------------------------------------------
-
-static zend_function_entry option_methods[] = {
- PHP_ME(Option, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Option, getName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Option, setName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Option, getValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Option, setValue, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* option_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Option",
- Option, option)
- zend_declare_property_string(option_type, "name", strlen("name"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_null(option_type, "value", strlen("value"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Option, __construct) {
- init_file_type(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Option, option, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(Option, option, Value, "value")
-
-// -----------------------------------------------------------------------------
-// SourceContext
-// -----------------------------------------------------------------------------
-
-static zend_function_entry source_context_methods[] = {
- PHP_ME(SourceContext, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(SourceContext, getFileName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(SourceContext, setFileName, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* source_context_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\SourceContext",
- SourceContext, source_context)
- zend_declare_property_string(source_context_type, "file_name",
- strlen("file_name"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(SourceContext, __construct) {
- init_file_source_context(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(SourceContext, source_context, FileName, "file_name")
-
-// -----------------------------------------------------------------------------
-// StringValue
-// -----------------------------------------------------------------------------
-
-static zend_function_entry string_value_methods[] = {
- PHP_ME(StringValue, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(StringValue, getValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(StringValue, setValue, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* string_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\StringValue",
- StringValue, string_value)
- zend_declare_property_string(string_value_type, "value", strlen("value"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(StringValue, __construct) {
- init_file_wrappers(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(StringValue, string_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// Struct
-// -----------------------------------------------------------------------------
-
-static zend_function_entry struct_methods[] = {
- PHP_ME(Struct, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Struct, getFields, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Struct, setFields, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* struct_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Struct",
- Struct, struct)
- zend_declare_property_null(struct_type, "fields", strlen("fields"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Struct, __construct) {
- init_file_struct(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Struct, struct, Fields, "fields")
-
-// -----------------------------------------------------------------------------
-// Type
-// -----------------------------------------------------------------------------
-
-static zend_function_entry type_methods[] = {
- PHP_ME(Type, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Type, getName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Type, setName, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Type, getFields, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Type, setFields, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Type, getOneofs, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Type, setOneofs, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Type, getOptions, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Type, setOptions, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Type, getSourceContext, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Type, setSourceContext, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Type, getSyntax, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Type, setSyntax, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* type_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Type",
- Type, type)
- zend_declare_property_string(type_type, "name", strlen("name"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_null(type_type, "fields", strlen("fields"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_string(type_type, "oneofs", strlen("oneofs"), "",
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_null(type_type, "options", strlen("options"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_null(type_type, "source_context", strlen("source_context"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
- zend_declare_property_long(type_type, "syntax", strlen("syntax"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Type, __construct) {
- init_file_type(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(Type, type, Name, "name")
-PHP_PROTO_FIELD_ACCESSORS(Type, type, Fields, "fields")
-PHP_PROTO_FIELD_ACCESSORS(Type, type, Oneofs, "oneofs")
-PHP_PROTO_FIELD_ACCESSORS(Type, type, Options, "options")
-PHP_PROTO_FIELD_ACCESSORS(Type, type, SourceContext, "source_context")
-PHP_PROTO_FIELD_ACCESSORS(Type, type, Syntax, "syntax")
-
-// -----------------------------------------------------------------------------
-// UInt32Value
-// -----------------------------------------------------------------------------
-
-static zend_function_entry u_int32_value_methods[] = {
- PHP_ME(UInt32Value, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(UInt32Value, getValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(UInt32Value, setValue, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* u_int32_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\UInt32Value",
- UInt32Value, u_int32_value)
- zend_declare_property_long(u_int32_value_type, "value", strlen("value"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(UInt32Value, __construct) {
- init_file_wrappers(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(UInt32Value, u_int32_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// UInt64Value
-// -----------------------------------------------------------------------------
-
-static zend_function_entry u_int64_value_methods[] = {
- PHP_ME(UInt64Value, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(UInt64Value, getValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(UInt64Value, setValue, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* u_int64_value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\UInt64Value",
- UInt64Value, u_int64_value)
- zend_declare_property_long(u_int64_value_type, "value", strlen("value"), 0,
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(UInt64Value, __construct) {
- init_file_wrappers(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_FIELD_ACCESSORS(UInt64Value, u_int64_value, Value, "value")
-
-// -----------------------------------------------------------------------------
-// Value
-// -----------------------------------------------------------------------------
-
-static zend_function_entry value_methods[] = {
- PHP_ME(Value, __construct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Value, getNullValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Value, setNullValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Value, getNumberValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Value, setNumberValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Value, getStringValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Value, setStringValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Value, getBoolValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Value, setBoolValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Value, getStructValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Value, setStructValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Value, getListValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Value, setListValue, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Value, getKind, NULL, ZEND_ACC_PUBLIC)
- {NULL, NULL, NULL}
-};
-
-zend_class_entry* value_type;
-
-// Init class entry.
-PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Value",
- Value, value)
- zend_declare_property_null(value_type, "kind", strlen("kind"),
- ZEND_ACC_PRIVATE TSRMLS_CC);
-PHP_PROTO_INIT_SUBMSGCLASS_END
-
-PHP_METHOD(Value, __construct) {
- init_file_struct(TSRMLS_C);
- INIT_MESSAGE_WITH_ARRAY;
-}
-
-PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, NullValue, "null_value")
-PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, NumberValue, "number_value")
-PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, StringValue, "string_value")
-PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, BoolValue, "bool_value")
-PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, StructValue, "struct_value")
-PHP_PROTO_ONEOF_FIELD_ACCESSORS(Value, value, ListValue, "list_value")
-PHP_PROTO_ONEOF_ACCESSORS(Value, value, Kind, "kind")
-
-// -----------------------------------------------------------------------------
-// GPBMetadata files for well known types
-// -----------------------------------------------------------------------------
-
-#define DEFINE_GPBMETADATA_FILE(LOWERNAME, CAMELNAME, CLASSNAME) \
- zend_class_entry* gpb_metadata_##LOWERNAME##_type; \
- static zend_function_entry gpb_metadata_##LOWERNAME##_methods[] = { \
- PHP_ME(GPBMetadata_##CAMELNAME, initOnce, NULL, \
- ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) \
- ZEND_FE_END \
- }; \
- void gpb_metadata_##LOWERNAME##_init(TSRMLS_D) { \
- zend_class_entry class_type; \
- INIT_CLASS_ENTRY(class_type, CLASSNAME, \
- gpb_metadata_##LOWERNAME##_methods); \
- gpb_metadata_##LOWERNAME##_type = \
- zend_register_internal_class(&class_type TSRMLS_CC); \
- } \
- PHP_METHOD(GPBMetadata_##CAMELNAME, initOnce) { \
- init_file_##LOWERNAME(TSRMLS_C); \
- }
-
-DEFINE_GPBMETADATA_FILE(any, Any, "GPBMetadata\\Google\\Protobuf\\Any");
-DEFINE_GPBMETADATA_FILE(api, Api, "GPBMetadata\\Google\\Protobuf\\Api");
-DEFINE_GPBMETADATA_FILE(duration, Duration,
- "GPBMetadata\\Google\\Protobuf\\Duration");
-DEFINE_GPBMETADATA_FILE(field_mask, FieldMask,
- "GPBMetadata\\Google\\Protobuf\\FieldMask");
-DEFINE_GPBMETADATA_FILE(empty, Empty,
- "GPBMetadata\\Google\\Protobuf\\GPBEmpty");
-DEFINE_GPBMETADATA_FILE(source_context, SourceContext,
- "GPBMetadata\\Google\\Protobuf\\SourceContext");
-DEFINE_GPBMETADATA_FILE(struct, Struct,
- "GPBMetadata\\Google\\Protobuf\\Struct");
-DEFINE_GPBMETADATA_FILE(timestamp, Timestamp,
- "GPBMetadata\\Google\\Protobuf\\Timestamp");
-DEFINE_GPBMETADATA_FILE(type, Type, "GPBMetadata\\Google\\Protobuf\\Type");
-DEFINE_GPBMETADATA_FILE(wrappers, Wrappers,
- "GPBMetadata\\Google\\Protobuf\\Wrappers");
-
-#undef DEFINE_GPBMETADATA_FILE
diff --git a/php/ext/google/protobuf2/message.h b/php/ext/google/protobuf/message.h
similarity index 100%
rename from php/ext/google/protobuf2/message.h
rename to php/ext/google/protobuf/message.h
diff --git a/php/ext/google/protobuf2/names.c b/php/ext/google/protobuf/names.c
similarity index 100%
rename from php/ext/google/protobuf2/names.c
rename to php/ext/google/protobuf/names.c
diff --git a/php/ext/google/protobuf2/names.h b/php/ext/google/protobuf/names.h
similarity index 100%
rename from php/ext/google/protobuf2/names.h
rename to php/ext/google/protobuf/names.h
diff --git a/php/ext/google/protobuf/package.xml b/php/ext/google/protobuf/package.xml
index 01a4b86d67..b8ae8bae71 100644
--- a/php/ext/google/protobuf/package.xml
+++ b/php/ext/google/protobuf/package.xml
@@ -25,20 +25,26 @@
+
+
-
+
+
+
+
+
-
+
+
+
+
+
+
+
-
-
-
-
-
-
diff --git a/php/ext/google/protobuf2/php-upb.c b/php/ext/google/protobuf/php-upb.c
similarity index 100%
rename from php/ext/google/protobuf2/php-upb.c
rename to php/ext/google/protobuf/php-upb.c
diff --git a/php/ext/google/protobuf2/php-upb.h b/php/ext/google/protobuf/php-upb.h
similarity index 100%
rename from php/ext/google/protobuf2/php-upb.h
rename to php/ext/google/protobuf/php-upb.h
diff --git a/php/ext/google/protobuf/protobuf.c b/php/ext/google/protobuf/protobuf.c
index e9ac935949..15c8f9bd72 100644
--- a/php/ext/google/protobuf/protobuf.c
+++ b/php/ext/google/protobuf/protobuf.c
@@ -30,481 +30,281 @@
#include "protobuf.h"
-#include
-
-static PHP_GINIT_FUNCTION(protobuf);
-static PHP_GSHUTDOWN_FUNCTION(protobuf);
-static PHP_RINIT_FUNCTION(protobuf);
-static PHP_RSHUTDOWN_FUNCTION(protobuf);
-static PHP_MINIT_FUNCTION(protobuf);
-static PHP_MSHUTDOWN_FUNCTION(protobuf);
-
-ZEND_DECLARE_MODULE_GLOBALS(protobuf)
-
-// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
-// instances.
-static HashTable* upb_def_to_php_obj_map;
-static upb_inttable upb_def_to_desc_map_persistent;
-static upb_inttable upb_def_to_enumdesc_map_persistent;
-// Global map from message/enum's php class entry to corresponding wrapper
-// Descriptor/EnumDescriptor instances.
-static HashTable* ce_to_php_obj_map;
-static upb_strtable ce_to_desc_map_persistent;
-static upb_strtable ce_to_enumdesc_map_persistent;
-// Global map from message/enum's proto fully-qualified name to corresponding
-// wrapper Descriptor/EnumDescriptor instances.
-static upb_strtable proto_to_desc_map_persistent;
-static upb_strtable class_to_desc_map_persistent;
-
-upb_strtable reserved_names;
+#include
+#include
+
+#include "arena.h"
+#include "array.h"
+#include "bundled_php.h"
+#include "convert.h"
+#include "def.h"
+#include "map.h"
+#include "message.h"
+#include "names.h"
// -----------------------------------------------------------------------------
-// Global maps.
+// Module "globals"
// -----------------------------------------------------------------------------
-static void add_to_table(HashTable* t, const void* def, void* value) {
- zval* pDest = NULL;
- php_proto_zend_hash_index_update_mem(t, (zend_ulong)def, &value,
- sizeof(zval*), (void**)&pDest);
-}
+// Despite the name, module "globals" are really thread-locals:
+// * PROTOBUF_G(var) accesses the thread-local variable for 'var'. Either:
+// * PROTOBUF_G(var) -> protobuf_globals.var (Non-ZTS / non-thread-safe)
+// * PROTOBUF_G(var) -> (ZTS / thread-safe builds)
-static void* get_from_table(const HashTable* t, const void* def) {
- void** value;
- if (php_proto_zend_hash_index_find_mem(t, (zend_ulong)def, (void**)&value) ==
- FAILURE) {
- return NULL;
- }
- return *value;
-}
+#define PROTOBUF_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(protobuf, v)
-void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value) {
-#if PHP_MAJOR_VERSION < 7
- Z_ADDREF_P(value);
-#else
- GC_ADDREF(value);
-#endif
- add_to_table(upb_def_to_php_obj_map, def, value);
-}
+ZEND_BEGIN_MODULE_GLOBALS(protobuf)
+ // Set by the user to make the descriptor pool persist between requests.
+ zend_bool keep_descriptor_pool_after_request;
-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);
-}
+ // Currently we make the generated pool a "global", which means that if a user
+ // does explicitly create threads within their request, the other threads will
+ // get different results from DescriptorPool::getGeneratedPool(). We require
+ // that all descriptors are loaded from the main thread.
+ zval generated_pool;
-void add_msgdef_desc(const upb_msgdef* m, DescriptorInternal* desc) {
- upb_inttable_insertptr(&upb_def_to_desc_map_persistent,
- m, upb_value_ptr(desc));
-}
+ // A upb_symtab that we are saving for the next request so that we don't have
+ // to rebuild it from scratch. When keep_descriptor_pool_after_request==true,
+ // we steal the upb_symtab from the global DescriptorPool object just before
+ // destroying it.
+ upb_symtab *saved_symtab;
-DescriptorInternal* get_msgdef_desc(const upb_msgdef* m) {
- upb_value v;
-#ifndef NDEBUG
- v.ctype = UPB_CTYPE_PTR;
-#endif
- if (!upb_inttable_lookupptr(&upb_def_to_desc_map_persistent, m, &v)) {
- return NULL;
- } else {
- return upb_value_getptr(v);
- }
-}
-
-void add_enumdef_enumdesc(const upb_enumdef* e, EnumDescriptorInternal* desc) {
- upb_inttable_insertptr(&upb_def_to_enumdesc_map_persistent,
- e, upb_value_ptr(desc));
-}
-
-EnumDescriptorInternal* get_enumdef_enumdesc(const upb_enumdef* e) {
- upb_value v;
-#ifndef NDEBUG
- v.ctype = UPB_CTYPE_PTR;
-#endif
- if (!upb_inttable_lookupptr(&upb_def_to_enumdesc_map_persistent, e, &v)) {
- return NULL;
- } else {
- return upb_value_getptr(v);
- }
-}
+ // Object cache (see interface in protobuf.h).
+ HashTable object_cache;
-void add_ce_obj(const void* ce, PHP_PROTO_HASHTABLE_VALUE value) {
-#if PHP_MAJOR_VERSION < 7
- Z_ADDREF_P(value);
-#else
- GC_ADDREF(value);
-#endif
- add_to_table(ce_to_php_obj_map, ce, value);
-}
+ // Name cache (see interface in protobuf.h).
+ HashTable name_msg_cache;
+ HashTable name_enum_cache;
+ZEND_END_MODULE_GLOBALS(protobuf)
-PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce) {
- return (PHP_PROTO_HASHTABLE_VALUE)get_from_table(ce_to_php_obj_map, ce);
-}
+ZEND_DECLARE_MODULE_GLOBALS(protobuf)
-void add_ce_desc(const zend_class_entry* ce, DescriptorInternal* desc) {
-#if PHP_MAJOR_VERSION < 7
- const char* klass = ce->name;
-#else
- const char* klass = ZSTR_VAL(ce->name);
-#endif
- upb_strtable_insert(&ce_to_desc_map_persistent, klass,
- upb_value_ptr(desc));
+const zval *get_generated_pool() {
+ return &PROTOBUF_G(generated_pool);
}
-DescriptorInternal* get_ce_desc(const zend_class_entry* ce) {
-#if PHP_MAJOR_VERSION < 7
- const char* klass = ce->name;
-#else
- const char* klass = ZSTR_VAL(ce->name);
-#endif
-
- upb_value v;
-#ifndef NDEBUG
- v.ctype = UPB_CTYPE_PTR;
-#endif
+// This is a PHP extension (not a Zend extension). What follows is a summary of
+// a PHP extension's lifetime and when various handlers are called.
+//
+// * PHP_GINIT_FUNCTION(protobuf) / PHP_GSHUTDOWN_FUNCTION(protobuf)
+// are the constructor/destructor for the globals. The sequence over the
+// course of a process lifetime is:
+//
+// # Process startup
+// GINIT()
+// MINIT
+//
+// foreach request:
+// RINIT
+// # Request is processed here.
+// RSHUTDOWN
+//
+// foreach thread:
+// GINIT()
+// # Code for the thread runs here.
+// GSHUTDOWN()
+//
+// # Process Shutdown
+// #
+// # These should be running per the docs, but I have not been able to
+// # actually get the process-wide shutdown functions to run.
+// #
+// # MSHUTDOWN
+// # GSHUTDOWN()
+//
+// * Threads can be created either explicitly by the user, inside a request,
+// or implicitly by the runtime, to process multiple requests concurrently.
+// If the latter is being used, then the "foreach thread" block above
+// actually looks like this:
+//
+// foreach thread:
+// GINIT()
+// # A non-main thread will only receive requests when using a threaded
+// # MPM with Apache
+// foreach request:
+// RINIT
+// # Request is processed here.
+// RSHUTDOWN
+// GSHUTDOWN()
+//
+// That said, it appears that few people use threads with PHP:
+// * The pthread package documented at
+// https://www.php.net/manual/en/class.thread.php nas not been released
+// since 2016, and the current release fails to compile against any PHP
+// newer than 7.0.33.
+// * The GitHub master branch supports 7.2+, but this has not been released
+// to PECL.
+// * Its owner has disavowed it as "broken by design" and "in an untenable
+// position for the future": https://github.com/krakjoe/pthreads/issues/929
+// * The only way to use PHP with requests in different threads is to use the
+// Apache 2 mod_php with the "worker" MPM. But this is explicitly
+// discouraged by the documentation: https://serverfault.com/a/231660
- if (!upb_strtable_lookup(&ce_to_desc_map_persistent, klass, &v)) {
- return NULL;
- } else {
- return upb_value_getptr(v);
+static PHP_GSHUTDOWN_FUNCTION(protobuf) {
+ if (protobuf_globals->saved_symtab) {
+ upb_symtab_free(protobuf_globals->saved_symtab);
}
}
-void add_ce_enumdesc(const zend_class_entry* ce, EnumDescriptorInternal* desc) {
-#if PHP_MAJOR_VERSION < 7
- const char* klass = ce->name;
-#else
- const char* klass = ZSTR_VAL(ce->name);
-#endif
- upb_strtable_insert(&ce_to_enumdesc_map_persistent, klass,
- upb_value_ptr(desc));
-}
-
-EnumDescriptorInternal* get_ce_enumdesc(const zend_class_entry* ce) {
-#if PHP_MAJOR_VERSION < 7
- const char* klass = ce->name;
-#else
- const char* klass = ZSTR_VAL(ce->name);
-#endif
- upb_value v;
-#ifndef NDEBUG
- v.ctype = UPB_CTYPE_PTR;
-#endif
- if (!upb_strtable_lookup(&ce_to_enumdesc_map_persistent, klass, &v)) {
- return NULL;
- } else {
- return upb_value_getptr(v);
- }
+static PHP_GINIT_FUNCTION(protobuf) {
+ ZVAL_NULL(&protobuf_globals->generated_pool);
+ protobuf_globals->saved_symtab = NULL;
}
-bool class_added(const void* ce) {
- return get_ce_desc(ce) != NULL;
-}
+/**
+ * PHP_RINIT_FUNCTION(protobuf)
+ *
+ * This function is run at the beginning of processing each request.
+ */
+static PHP_RINIT_FUNCTION(protobuf) {
+ // Create the global generated pool.
+ // Reuse the symtab (if any) left to us by the last request.
+ upb_symtab *symtab = PROTOBUF_G(saved_symtab);
+ DescriptorPool_CreateWithSymbolTable(&PROTOBUF_G(generated_pool), symtab);
-void add_proto_desc(const char* proto, DescriptorInternal* desc) {
- upb_strtable_insert(&proto_to_desc_map_persistent, proto,
- upb_value_ptr(desc));
-}
+ // Set up autoloader for bundled sources.
+ zend_eval_string("spl_autoload_register('protobuf_internal_loadbundled');",
+ NULL, "autoload_register.php");
-DescriptorInternal* get_proto_desc(const char* proto) {
- upb_value v;
-#ifndef NDEBUG
- v.ctype = UPB_CTYPE_PTR;
-#endif
- if (!upb_strtable_lookup(&proto_to_desc_map_persistent, proto, &v)) {
- return NULL;
- } else {
- return upb_value_getptr(v);
- }
-}
+ zend_hash_init(&PROTOBUF_G(object_cache), 64, NULL, NULL, 0);
+ zend_hash_init(&PROTOBUF_G(name_msg_cache), 64, NULL, NULL, 0);
+ zend_hash_init(&PROTOBUF_G(name_enum_cache), 64, NULL, NULL, 0);
-void add_class_desc(const char* klass, DescriptorInternal* desc) {
- upb_strtable_insert(&class_to_desc_map_persistent, klass,
- upb_value_ptr(desc));
+ return SUCCESS;
}
-DescriptorInternal* get_class_desc(const char* klass) {
- upb_value v;
-#ifndef NDEBUG
- v.ctype = UPB_CTYPE_PTR;
-#endif
- if (!upb_strtable_lookup(&class_to_desc_map_persistent, klass, &v)) {
- return NULL;
- } else {
- return upb_value_getptr(v);
+/**
+ * PHP_RSHUTDOWN_FUNCTION(protobuf)
+ *
+ * This function is run at the end of processing each request.
+ */
+static PHP_RSHUTDOWN_FUNCTION(protobuf) {
+ // Preserve the symtab if requested.
+ if (PROTOBUF_G(keep_descriptor_pool_after_request)) {
+ zval *zv = &PROTOBUF_G(generated_pool);
+ PROTOBUF_G(saved_symtab) = DescriptorPool_Steal(zv);
}
-}
-void add_class_enumdesc(const char* klass, EnumDescriptorInternal* desc) {
- upb_strtable_insert(&class_to_desc_map_persistent, klass,
- upb_value_ptr(desc));
-}
+ zval_dtor(&PROTOBUF_G(generated_pool));
+ zend_hash_destroy(&PROTOBUF_G(object_cache));
+ zend_hash_destroy(&PROTOBUF_G(name_msg_cache));
+ zend_hash_destroy(&PROTOBUF_G(name_enum_cache));
-EnumDescriptorInternal* get_class_enumdesc(const char* klass) {
- upb_value v;
-#ifndef NDEBUG
- v.ctype = UPB_CTYPE_PTR;
-#endif
- if (!upb_strtable_lookup(&class_to_desc_map_persistent, klass, &v)) {
- return NULL;
- } else {
- return upb_value_getptr(v);
- }
+ return SUCCESS;
}
// -----------------------------------------------------------------------------
-// Well Known Types.
+// Bundled PHP sources
// -----------------------------------------------------------------------------
-bool is_inited_file_any;
-bool is_inited_file_api;
-bool is_inited_file_duration;
-bool is_inited_file_field_mask;
-bool is_inited_file_empty;
-bool is_inited_file_source_context;
-bool is_inited_file_struct;
-bool is_inited_file_timestamp;
-bool is_inited_file_type;
-bool is_inited_file_wrappers;
+// We bundle PHP sources for well-known types into the C extension. There is no
+// need to implement these in C.
-// -----------------------------------------------------------------------------
-// Reserved Name.
-// -----------------------------------------------------------------------------
+static PHP_FUNCTION(protobuf_internal_loadbundled) {
+ char *name = NULL;
+ zend_long size;
+ BundledPhp_File *file;
-// Although we already have kReservedNames, we still add them to hash table to
-// speed up look up.
-const char *const kReservedNames[] = {
- "abstract", "and", "array", "as", "break",
- "callable", "case", "catch", "class", "clone",
- "const", "continue", "declare", "default", "die",
- "do", "echo", "else", "elseif", "empty",
- "enddeclare", "endfor", "endforeach", "endif", "endswitch",
- "endwhile", "eval", "exit", "extends", "final",
- "for", "foreach", "function", "global", "goto",
- "if", "implements", "include", "include_once", "instanceof",
- "insteadof", "interface", "isset", "list", "namespace",
- "new", "or", "print", "private", "protected",
- "public", "require", "require_once", "return", "static",
- "switch", "throw", "trait", "try", "unset",
- "use", "var", "while", "xor", "int",
- "float", "bool", "string", "true", "false",
- "null", "void", "iterable"};
-const int kReservedNamesSize = 73;
-
-bool is_reserved_name(const char* name) {
- upb_value v;
-#ifndef NDEBUG
- v.ctype = UPB_CTYPE_UINT64;
-#endif
- return upb_strtable_lookup2(&reserved_names, name, strlen(name), &v);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &size) != SUCCESS) {
+ return;
+ }
+
+ for (file = bundled_files; file->filename; file++) {
+ if (strcmp(file->filename, name) == 0) {
+ zend_eval_string((char*)file->contents, NULL, (char*)file->filename);
+ return;
+ }
+ }
}
+ZEND_BEGIN_ARG_INFO_EX(arginfo_load_bundled_source, 0, 0, 1)
+ ZEND_ARG_INFO(0, class_name)
+ZEND_END_ARG_INFO()
+
// -----------------------------------------------------------------------------
-// Utilities.
+// Object Cache.
// -----------------------------------------------------------------------------
-zend_function_entry protobuf_functions[] = {
- ZEND_FE_END
-};
-
-static const zend_module_dep protobuf_deps[] = {
- ZEND_MOD_OPTIONAL("date")
- ZEND_MOD_END
-};
-
-zend_module_entry protobuf_module_entry = {
- STANDARD_MODULE_HEADER_EX,
- NULL,
- protobuf_deps,
- PHP_PROTOBUF_EXTNAME, // extension name
- protobuf_functions, // function list
- PHP_MINIT(protobuf), // process startup
- PHP_MSHUTDOWN(protobuf), // process shutdown
- PHP_RINIT(protobuf), // request shutdown
- PHP_RSHUTDOWN(protobuf), // request shutdown
- NULL, // extension info
- PHP_PROTOBUF_VERSION, // extension version
- PHP_MODULE_GLOBALS(protobuf), // globals descriptor
- PHP_GINIT(protobuf), // globals ctor
- PHP_GSHUTDOWN(protobuf), // globals dtor
- NULL, // post deactivate
- STANDARD_MODULE_PROPERTIES_EX
-};
-
-// install module
-ZEND_GET_MODULE(protobuf)
-
-// global variables
-static PHP_GINIT_FUNCTION(protobuf) {
+void ObjCache_Add(const void *upb_obj, zend_object *php_obj) {
+ zend_ulong k = (zend_ulong)upb_obj;
+ zend_hash_index_add_ptr(&PROTOBUF_G(object_cache), k, php_obj);
}
-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;
- GC_DELREF(object);
- if(GC_REFCOUNT(object) == 0) {
- zend_objects_store_del(object);
+void ObjCache_Delete(const void *upb_obj) {
+ if (upb_obj) {
+ zend_ulong k = (zend_ulong)upb_obj;
+ int ret = zend_hash_index_del(&PROTOBUF_G(object_cache), k);
+ PBPHP_ASSERT(ret == SUCCESS);
}
- efree(ptr);
-}
-#endif
-
-static void initialize_persistent_descriptor_pool(TSRMLS_D) {
- upb_inttable_init(&upb_def_to_desc_map_persistent, UPB_CTYPE_PTR);
- upb_inttable_init(&upb_def_to_enumdesc_map_persistent, UPB_CTYPE_PTR);
- upb_strtable_init(&ce_to_desc_map_persistent, UPB_CTYPE_PTR);
- upb_strtable_init(&ce_to_enumdesc_map_persistent, UPB_CTYPE_PTR);
- upb_strtable_init(&proto_to_desc_map_persistent, UPB_CTYPE_PTR);
- upb_strtable_init(&class_to_desc_map_persistent, UPB_CTYPE_PTR);
-
- internal_descriptor_pool_impl_init(&generated_pool_impl TSRMLS_CC);
-
- is_inited_file_any = false;
- is_inited_file_api = false;
- is_inited_file_duration = false;
- is_inited_file_field_mask = false;
- is_inited_file_empty = false;
- is_inited_file_source_context = false;
- is_inited_file_struct = false;
- is_inited_file_timestamp = false;
- is_inited_file_type = false;
- is_inited_file_wrappers = false;
}
-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);
-
- ALLOC_HASHTABLE(ce_to_php_obj_map);
- zend_hash_init(ce_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0);
-
- generated_pool = NULL;
- generated_pool_php = NULL;
- internal_generated_pool_php = NULL;
-
- if (PROTOBUF_G(keep_descriptor_pool_after_request)) {
- // Needs to clean up obsolete class entry
- upb_strtable_iter i;
- upb_value v;
-
- DescriptorInternal* desc;
- for(upb_strtable_begin(&i, &ce_to_desc_map_persistent);
- !upb_strtable_done(&i);
- upb_strtable_next(&i)) {
- v = upb_strtable_iter_value(&i);
- desc = upb_value_getptr(v);
- desc->klass = NULL;
- }
+bool ObjCache_Get(const void *upb_obj, zval *val) {
+ zend_ulong k = (zend_ulong)upb_obj;
+ zend_object *obj = zend_hash_index_find_ptr(&PROTOBUF_G(object_cache), k);
- EnumDescriptorInternal* enumdesc;
- for(upb_strtable_begin(&i, &ce_to_enumdesc_map_persistent);
- !upb_strtable_done(&i);
- upb_strtable_next(&i)) {
- v = upb_strtable_iter_value(&i);
- enumdesc = upb_value_getptr(v);
- enumdesc->klass = NULL;
- }
+ if (obj) {
+ GC_ADDREF(obj);
+ ZVAL_OBJ(val, obj);
+ return true;
} else {
- initialize_persistent_descriptor_pool(TSRMLS_C);
+ ZVAL_NULL(val);
+ return false;
}
-
- return 0;
}
-static void cleanup_desc_table(upb_inttable* t) {
- upb_inttable_iter i;
- upb_value v;
- DescriptorInternal* desc;
- for(upb_inttable_begin(&i, t);
- !upb_inttable_done(&i);
- upb_inttable_next(&i)) {
- v = upb_inttable_iter_value(&i);
- desc = upb_value_getptr(v);
- if (desc->layout) {
- free_layout(desc->layout);
- desc->layout = NULL;
- }
- free(desc->classname);
- SYS_FREE(desc);
- }
-}
+// -----------------------------------------------------------------------------
+// Name Cache.
+// -----------------------------------------------------------------------------
-static void cleanup_enumdesc_table(upb_inttable* t) {
- upb_inttable_iter i;
- upb_value v;
- EnumDescriptorInternal* desc;
- for(upb_inttable_begin(&i, t);
- !upb_inttable_done(&i);
- upb_inttable_next(&i)) {
- v = upb_inttable_iter_value(&i);
- desc = upb_value_getptr(v);
- free(desc->classname);
- SYS_FREE(desc);
- }
+void NameMap_AddMessage(const upb_msgdef *m) {
+ char *k = GetPhpClassname(upb_msgdef_file(m), upb_msgdef_fullname(m));
+ zend_hash_str_add_ptr(&PROTOBUF_G(name_msg_cache), k, strlen(k), (void*)m);
+ free(k);
}
-static void cleanup_persistent_descriptor_pool(TSRMLS_D) {
- // Clean up
-
- // Only needs to clean one map out of three (def=>desc, ce=>desc, proto=>desc)
- cleanup_desc_table(&upb_def_to_desc_map_persistent);
- cleanup_enumdesc_table(&upb_def_to_enumdesc_map_persistent);
-
- internal_descriptor_pool_impl_destroy(&generated_pool_impl TSRMLS_CC);
-
- upb_inttable_uninit(&upb_def_to_desc_map_persistent);
- upb_inttable_uninit(&upb_def_to_enumdesc_map_persistent);
- upb_strtable_uninit(&ce_to_desc_map_persistent);
- upb_strtable_uninit(&ce_to_enumdesc_map_persistent);
- upb_strtable_uninit(&proto_to_desc_map_persistent);
- upb_strtable_uninit(&class_to_desc_map_persistent);
+void NameMap_AddEnum(const upb_enumdef *e) {
+ char *k = GetPhpClassname(upb_enumdef_file(e), upb_enumdef_fullname(e));
+ zend_hash_str_add_ptr(&PROTOBUF_G(name_enum_cache), k, strlen(k), (void*)e);
+ free(k);
}
-static PHP_RSHUTDOWN_FUNCTION(protobuf) {
- zend_hash_destroy(upb_def_to_php_obj_map);
- FREE_HASHTABLE(upb_def_to_php_obj_map);
-
- zend_hash_destroy(ce_to_php_obj_map);
- FREE_HASHTABLE(ce_to_php_obj_map);
+const upb_msgdef *NameMap_GetMessage(zend_class_entry *ce) {
+ const upb_msgdef *ret =
+ zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name);
-#if PHP_MAJOR_VERSION < 7
- if (generated_pool_php != NULL) {
- zval_dtor(generated_pool_php);
- FREE_ZVAL(generated_pool_php);
- }
- if (internal_generated_pool_php != NULL) {
- zval_dtor(internal_generated_pool_php);
- FREE_ZVAL(internal_generated_pool_php);
- }
-#else
- if (generated_pool_php != NULL) {
+ if (!ret && ce->create_object) {
zval tmp;
- ZVAL_OBJ(&tmp, generated_pool_php);
- zval_dtor(&tmp);
- }
- if (internal_generated_pool_php != NULL) {
- zval tmp;
- ZVAL_OBJ(&tmp, internal_generated_pool_php);
- zval_dtor(&tmp);
- }
-#endif
-
- if (!PROTOBUF_G(keep_descriptor_pool_after_request)) {
- cleanup_persistent_descriptor_pool(TSRMLS_C);
+ zval zv;
+ ZVAL_OBJ(&tmp, ce->create_object(ce));
+ zend_call_method_with_0_params(&tmp, ce, NULL, "__construct", &zv);
+ zval_ptr_dtor(&tmp);
+ zval_ptr_dtor(&zv);
+ ret = zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name);
}
- return 0;
+ return ret;
}
-static void reserved_names_init() {
- size_t i;
- upb_value v = upb_value_bool(false);
- for (i = 0; i < kReservedNamesSize; i++) {
- upb_strtable_insert2(&reserved_names, kReservedNames[i],
- strlen(kReservedNames[i]), v);
- }
+const upb_enumdef *NameMap_GetEnum(zend_class_entry *ce) {
+ const upb_enumdef *ret =
+ zend_hash_find_ptr(&PROTOBUF_G(name_enum_cache), ce->name);
+ return ret;
}
+// -----------------------------------------------------------------------------
+// Module init.
+// -----------------------------------------------------------------------------
+
+zend_function_entry protobuf_functions[] = {
+ PHP_FE(protobuf_internal_loadbundled, arginfo_load_bundled_source)
+ ZEND_FE_END
+};
+
+static const zend_module_dep protobuf_deps[] = {
+ ZEND_MOD_OPTIONAL("date")
+ ZEND_MOD_END
+};
+
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("protobuf.keep_descriptor_pool_after_request", "0",
PHP_INI_SYSTEM, OnUpdateBool,
@@ -514,86 +314,36 @@ PHP_INI_END()
static PHP_MINIT_FUNCTION(protobuf) {
REGISTER_INI_ENTRIES();
-
- upb_strtable_init(&reserved_names, UPB_CTYPE_UINT64);
- reserved_names_init();
-
- if (PROTOBUF_G(keep_descriptor_pool_after_request)) {
- initialize_persistent_descriptor_pool(TSRMLS_C);
- }
-
- descriptor_pool_init(TSRMLS_C);
- descriptor_init(TSRMLS_C);
- enum_descriptor_init(TSRMLS_C);
- enum_value_descriptor_init(TSRMLS_C);
- field_descriptor_init(TSRMLS_C);
- gpb_type_init(TSRMLS_C);
- internal_descriptor_pool_init(TSRMLS_C);
- map_field_init(TSRMLS_C);
- map_field_iter_init(TSRMLS_C);
- message_init(TSRMLS_C);
- oneof_descriptor_init(TSRMLS_C);
- repeated_field_init(TSRMLS_C);
- repeated_field_iter_init(TSRMLS_C);
- util_init(TSRMLS_C);
-
- gpb_metadata_any_init(TSRMLS_C);
- gpb_metadata_api_init(TSRMLS_C);
- gpb_metadata_duration_init(TSRMLS_C);
- gpb_metadata_field_mask_init(TSRMLS_C);
- gpb_metadata_empty_init(TSRMLS_C);
- gpb_metadata_source_context_init(TSRMLS_C);
- gpb_metadata_struct_init(TSRMLS_C);
- gpb_metadata_timestamp_init(TSRMLS_C);
- gpb_metadata_type_init(TSRMLS_C);
- gpb_metadata_wrappers_init(TSRMLS_C);
-
- any_init(TSRMLS_C);
- api_init(TSRMLS_C);
- bool_value_init(TSRMLS_C);
- bytes_value_init(TSRMLS_C);
- double_value_init(TSRMLS_C);
- duration_init(TSRMLS_C);
- enum_init(TSRMLS_C);
- enum_value_init(TSRMLS_C);
- field_cardinality_init(TSRMLS_C);
- field_init(TSRMLS_C);
- field_kind_init(TSRMLS_C);
- field_mask_init(TSRMLS_C);
- float_value_init(TSRMLS_C);
- empty_init(TSRMLS_C);
- int32_value_init(TSRMLS_C);
- int64_value_init(TSRMLS_C);
- list_value_init(TSRMLS_C);
- method_init(TSRMLS_C);
- mixin_init(TSRMLS_C);
- null_value_init(TSRMLS_C);
- option_init(TSRMLS_C);
- source_context_init(TSRMLS_C);
- string_value_init(TSRMLS_C);
- struct_init(TSRMLS_C);
- syntax_init(TSRMLS_C);
- timestamp_init(TSRMLS_C);
- type_init(TSRMLS_C);
- u_int32_value_init(TSRMLS_C);
- u_int64_value_init(TSRMLS_C);
- value_init(TSRMLS_C);
-
- return 0;
+ Arena_ModuleInit();
+ Array_ModuleInit();
+ Convert_ModuleInit();
+ Def_ModuleInit();
+ Map_ModuleInit();
+ Message_ModuleInit();
+ return SUCCESS;
}
static PHP_MSHUTDOWN_FUNCTION(protobuf) {
- if (PROTOBUF_G(keep_descriptor_pool_after_request)) {
- cleanup_persistent_descriptor_pool(TSRMLS_C);
- }
-
- upb_strtable_uninit(&reserved_names);
+ return SUCCESS;
+}
- PEFREE(message_handlers);
- PEFREE(repeated_field_handlers);
- PEFREE(repeated_field_iter_handlers);
- PEFREE(map_field_handlers);
- PEFREE(map_field_iter_handlers);
+zend_module_entry protobuf_module_entry = {
+ STANDARD_MODULE_HEADER_EX,
+ NULL,
+ protobuf_deps,
+ "protobuf", // extension name
+ protobuf_functions, // function list
+ PHP_MINIT(protobuf), // process startup
+ PHP_MSHUTDOWN(protobuf), // process shutdown
+ PHP_RINIT(protobuf), // request shutdown
+ PHP_RSHUTDOWN(protobuf), // request shutdown
+ NULL, // extension info
+ "3.13.0", // extension version
+ PHP_MODULE_GLOBALS(protobuf), // globals descriptor
+ PHP_GINIT(protobuf), // globals ctor
+ PHP_GSHUTDOWN(protobuf), // globals dtor
+ NULL, // post deactivate
+ STANDARD_MODULE_PROPERTIES_EX
+};
- return 0;
-}
+ZEND_GET_MODULE(protobuf)
diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h
index 520888733f..6a7afae061 100644
--- a/php/ext/google/protobuf/protobuf.h
+++ b/php/ext/google/protobuf/protobuf.h
@@ -28,1556 +28,62 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#ifndef __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
-#define __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
+#ifndef PHP_PROTOBUF_H_
+#define PHP_PROTOBUF_H_
#include
+#include
-// ubp.h has to be placed after php.h. Othwise, php.h will introduce NDEBUG.
-#include "upb.h"
+#include "php-upb.h"
-#define PHP_PROTOBUF_EXTNAME "protobuf"
-#define PHP_PROTOBUF_VERSION "3.12.3"
-
-#define MAX_LENGTH_OF_INT64 20
-#define SIZEOF_INT64 8
-
-/* From Chromium. */
-#define ARRAY_SIZE(x) \
- ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
-
-#define PHP_PROTO_UNUSED(var) (void)var
-/* PHP_PROTO_ASSERT(): in release mode, we use the expression without letting
- * it be evaluated. This prevents "unused variable" warnings. */
-#ifdef NDEBUG
-#define PHP_PROTO_ASSERT(expr) do {} while (false && (expr))
-#else
-#define PHP_PROTO_ASSERT(expr) assert(expr)
-#endif
-
-// -----------------------------------------------------------------------------
-// PHP7 Wrappers
-// ----------------------------------------------------------------------------
+const zval *get_generated_pool();
#if PHP_VERSION_ID < 70300
#define GC_ADDREF(h) ++GC_REFCOUNT(h)
#define GC_DELREF(h) --GC_REFCOUNT(h)
#endif
-#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_zval(ht, h, pData) \
- zend_hash_index_update(ht, h, &(pData), sizeof(void*), NULL)
-
-#define php_proto_zend_hash_update_zval(ht, key, key_len, value) \
- zend_hash_update(ht, key, key_len, value, sizeof(void*), NULL)
-
-#define php_proto_zend_hash_update(ht, key, key_len) \
- zend_hash_update(ht, key, key_len, 0, 0, NULL)
-
-#define php_proto_zend_hash_index_update_mem(ht, h, pData, nDataSize, pDest) \
- zend_hash_index_update(ht, h, pData, nDataSize, pDest)
-
-#define php_proto_zend_hash_update_mem(ht, key, key_len, pData, nDataSize, \
- pDest) \
- zend_hash_update(ht, key, key_len, pData, nDataSize, pDest)
-
-#define php_proto_zend_hash_index_find_zval(ht, h, pDest) \
- zend_hash_index_find(ht, h, pDest)
-
-#define php_proto_zend_hash_find(ht, key, key_len, pDest) \
- zend_hash_find(ht, key, key_len, pDest)
-
-#define php_proto_zend_hash_index_find_mem(ht, h, pDest) \
- zend_hash_index_find(ht, h, pDest)
-
-#define php_proto_zend_hash_find_zval(ht, key, key_len, pDest) \
- zend_hash_find(ht, key, key_len, pDest)
-
-#define php_proto_zend_hash_find_mem(ht, key, key_len, pDest) \
- zend_hash_find(ht, key, key_len, pDest)
-
-#define php_proto_zend_hash_next_index_insert_zval(ht, pData) \
- zend_hash_next_index_insert(ht, pData, sizeof(void*), NULL)
-
-#define php_proto_zend_hash_next_index_insert_mem(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_SUBMSGCLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \
- void LOWWERNAME##_init(TSRMLS_D) { \
- zend_class_entry class_type; \
- INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \
- LOWWERNAME##_methods); \
- LOWWERNAME##_type = zend_register_internal_class_ex( \
- &class_type, message_type, NULL TSRMLS_CC); \
- LOWWERNAME##_type->create_object = message_create; \
- zend_do_inheritance(LOWWERNAME##_type, message_type TSRMLS_CC);
-#define PHP_PROTO_INIT_SUBMSGCLASS_END \
- }
-
-#define PHP_PROTO_INIT_ENUMCLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \
- void LOWWERNAME##_init(TSRMLS_D) { \
- zend_class_entry class_type; \
- INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \
- LOWWERNAME##_methods); \
- LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC);
-#define PHP_PROTO_INIT_ENUMCLASS_END \
- }
-
-#define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \
- void LOWWERNAME##_init(TSRMLS_D) { \
- zend_class_entry class_type; \
- 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, 1); \
- 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_EMPTY_FREE_START(classname, lowername) \
- void lowername##_free(void* object TSRMLS_DC) { \
- classname* intern = object;
-#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_EMPTY_DTOR_START(classname, lowername)
-#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) (*(CACHED_VALUE*)(VALUE))
-#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (&VALUE)
-#define ZVAL_PTR_TO_CACHED_VALUE(VALUE) (VALUE)
-#define ZVAL_TO_CACHED_VALUE(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(OBJECT, OFFSET) &((OBJECT)->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 HASHTABLE_VALUE_CE(val) Z_OBJCE_P(val)
-
-#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)
-
-#define PHP_PROTO_RETVAL_ZVAL(value) ZVAL_ZVAL(return_value, value, 1, 0)
-
-#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_zval(HashTable* ht, zend_ulong h,
- zval* pData) {
- void* result = NULL;
- result = zend_hash_index_update(ht, h, pData);
- return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_update(HashTable* ht, const char* key,
- size_t key_len) {
- void* result = NULL;
- zval temp;
- ZVAL_LONG(&temp, 0);
- result = zend_hash_str_update(ht, key, key_len, &temp);
- return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_index_update_mem(HashTable* ht, zend_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_update_zval(HashTable* ht,
- const char* key, uint key_len,
- zval* pData) {
- void* result = NULL;
- zend_string* internal_key = zend_string_init(key, key_len, 0);
- result = zend_hash_update(ht, internal_key, pData);
- return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_update_mem(HashTable* ht, const char* key,
- uint key_len, void* pData,
- uint nDataSize, void** pDest) {
- zend_string* internal_key = zend_string_init(key, key_len, 0);
- void* result = zend_hash_update_mem(ht, internal_key, pData, nDataSize);
- zend_string_release(internal_key);
- if (pDest != NULL) *pDest = result;
- return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_index_find_zval(const HashTable* ht,
- zend_ulong h, void** pDest) {
- zval* result = zend_hash_index_find(ht, h);
- if (pDest != NULL) *pDest = result;
- return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_find(const HashTable* ht, const char* key,
- size_t key_len, void** pDest) {
- void* result = NULL;
- result = zend_hash_str_find(ht, key, key_len);
- return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_index_find_mem(const HashTable* ht,
- zend_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_find_zval(const HashTable* ht,
- const char* key, uint key_len,
- void** pDest) {
- zend_string* internal_key = zend_string_init(key, key_len, 1);
- zval* result = zend_hash_find(ht, internal_key);
- if (pDest != NULL) *pDest = result;
- return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_find_mem(const HashTable* ht,
- const char* key, uint key_len,
- void** pDest) {
- zend_string* internal_key = zend_string_init(key, key_len, 1);
- void* result = zend_hash_find_ptr(ht, internal_key);
- zend_string_release(internal_key);
- if (pDest != NULL) *pDest = result;
- return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_next_index_insert_zval(HashTable* ht,
- void* pData) {
- zval tmp;
- ZVAL_OBJ(&tmp, *(zend_object**)pData);
- zval* result = zend_hash_next_index_insert(ht, &tmp);
- return result != NULL ? SUCCESS : FAILURE;
-}
-
-static inline int php_proto_zend_hash_next_index_insert_mem(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_SUBMSGCLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \
- void LOWWERNAME##_init(TSRMLS_D) { \
- zend_class_entry class_type; \
- INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \
- LOWWERNAME##_methods); \
- LOWWERNAME##_type = zend_register_internal_class(&class_type); \
- zend_do_inheritance(LOWWERNAME##_type, message_type);
-#define PHP_PROTO_INIT_SUBMSGCLASS_END \
- }
-
-#define PHP_PROTO_INIT_ENUMCLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \
- void LOWWERNAME##_init(TSRMLS_D) { \
- zend_class_entry class_type; \
- INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \
- LOWWERNAME##_methods); \
- LOWWERNAME##_type = zend_register_internal_class(&class_type);
-#define PHP_PROTO_INIT_ENUMCLASS_END \
- }
-
-#define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \
- void LOWWERNAME##_init(TSRMLS_D) { \
- zend_class_entry class_type; \
- 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, 1); \
- 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_EMPTY_FREE_START(classname, lowername) \
- void lowername##_free(zend_object* object) {
-#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_EMPTY_DTOR_START(classname, lowername) \
- void lowername##_dtor(zend_object* object) {
-#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) ((CACHED_VALUE*)(VALUE))
-#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (VALUE)
-#define ZVAL_PTR_TO_CACHED_VALUE(VALUE) (*VALUE)
-#define ZVAL_TO_CACHED_VALUE(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 HASHTABLE_VALUE_CE(val) val->ce
-
-#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_DELREF(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;
-}
-
-#define PHP_PROTO_RETVAL_ZVAL(value) ZVAL_COPY(return_value, value)
-
-#endif // PHP_MAJOR_VERSION >= 7
-
-#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
-#define PHP_PROTO_FAKE_SCOPE_BEGIN(klass) \
- zend_class_entry* old_scope = EG(scope); \
- EG(scope) = klass;
-#define PHP_PROTO_FAKE_SCOPE_RESTART(klass) \
- old_scope = EG(scope); \
- EG(scope) = klass;
-#define PHP_PROTO_FAKE_SCOPE_END EG(scope) = old_scope;
-#else
-#define PHP_PROTO_FAKE_SCOPE_BEGIN(klass) \
- zend_class_entry* old_scope = EG(fake_scope); \
- EG(fake_scope) = klass;
-#define PHP_PROTO_FAKE_SCOPE_RESTART(klass) \
- old_scope = EG(fake_scope); \
- EG(fake_scope) = klass;
-#define PHP_PROTO_FAKE_SCOPE_END EG(fake_scope) = old_scope;
-#endif
-
-// Define PHP class
-#define DEFINE_PROTOBUF_INIT_CLASS(CLASSNAME, CAMELNAME, LOWERNAME) \
- PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWERNAME) \
- PHP_PROTO_INIT_CLASS_END
-
-#define DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME) \
- PHP_PROTO_OBJECT_CREATE_START(NAME, LOWERNAME) \
- LOWERNAME##_init_c_instance(intern TSRMLS_CC); \
- PHP_PROTO_OBJECT_CREATE_END(NAME, LOWERNAME)
-
-#define DEFINE_PROTOBUF_FREE(CAMELNAME, LOWERNAME) \
- PHP_PROTO_OBJECT_FREE_START(CAMELNAME, LOWERNAME) \
- LOWERNAME##_free_c(intern TSRMLS_CC); \
- PHP_PROTO_OBJECT_FREE_END
-
-#define DEFINE_PROTOBUF_DTOR(CAMELNAME, LOWERNAME) \
- PHP_PROTO_OBJECT_EMPTY_DTOR_START(CAMELNAME, LOWERNAME) \
- PHP_PROTO_OBJECT_DTOR_END
-
-#define DEFINE_CLASS(NAME, LOWERNAME, string_name) \
- zend_class_entry *LOWERNAME##_type; \
- zend_object_handlers *LOWERNAME##_handlers; \
- DEFINE_PROTOBUF_FREE(NAME, LOWERNAME) \
- DEFINE_PROTOBUF_DTOR(NAME, LOWERNAME) \
- DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME) \
- DEFINE_PROTOBUF_INIT_CLASS(string_name, NAME, LOWERNAME)
-
-// -----------------------------------------------------------------------------
-// Forward Declaration
-// ----------------------------------------------------------------------------
-
-struct Any;
-struct Api;
-struct BoolValue;
-struct BytesValue;
-struct Descriptor;
-struct DescriptorInternal;
-struct DescriptorPool;
-struct DoubleValue;
-struct Duration;
-struct Enum;
-struct EnumDescriptor;
-struct EnumDescriptorInternal;
-struct EnumValue;
-struct EnumValueDescriptor;
-struct Field;
-struct FieldDescriptor;
-struct FieldMask;
-struct Field_Cardinality;
-struct Field_Kind;
-struct FloatValue;
-struct GPBEmpty;
-struct Int32Value;
-struct Int64Value;
-struct InternalDescriptorPool;
-struct InternalDescriptorPoolImpl;
-struct ListValue;
-struct Map;
-struct MapIter;
-struct MessageField;
-struct MessageHeader;
-struct MessageLayout;
-struct Method;
-struct Mixin;
-struct NullValue;
-struct Oneof;
-struct Option;
-struct RepeatedField;
-struct RepeatedFieldIter;
-struct SourceContext;
-struct StringValue;
-struct Struct;
-struct Syntax;
-struct Timestamp;
-struct Type;
-struct UInt32Value;
-struct UInt64Value;
-struct Value;
-
-typedef struct Any Any;
-typedef struct Api Api;
-typedef struct BoolValue BoolValue;
-typedef struct BytesValue BytesValue;
-typedef struct Descriptor Descriptor;
-typedef struct DescriptorInternal DescriptorInternal;
-typedef struct DescriptorPool DescriptorPool;
-typedef struct DoubleValue DoubleValue;
-typedef struct Duration Duration;
-typedef struct EnumDescriptor EnumDescriptor;
-typedef struct EnumDescriptorInternal EnumDescriptorInternal;
-typedef struct Enum Enum;
-typedef struct EnumValueDescriptor EnumValueDescriptor;
-typedef struct EnumValue EnumValue;
-typedef struct Field_Cardinality Field_Cardinality;
-typedef struct FieldDescriptor FieldDescriptor;
-typedef struct Field Field;
-typedef struct Field_Kind Field_Kind;
-typedef struct FieldMask FieldMask;
-typedef struct FloatValue FloatValue;
-typedef struct GPBEmpty GPBEmpty;
-typedef struct Int32Value Int32Value;
-typedef struct Int64Value Int64Value;
-typedef struct InternalDescriptorPool InternalDescriptorPool;
-typedef struct InternalDescriptorPoolImpl InternalDescriptorPoolImpl;
-typedef struct ListValue ListValue;
-typedef struct MapIter MapIter;
-typedef struct Map Map;
-typedef struct MessageField MessageField;
-typedef struct MessageHeader MessageHeader;
-typedef struct MessageLayout MessageLayout;
-typedef struct Method Method;
-typedef struct Mixin Mixin;
-typedef struct NullValue NullValue;
-typedef struct Oneof Oneof;
-typedef struct Option Option;
-typedef struct RepeatedFieldIter RepeatedFieldIter;
-typedef struct RepeatedField RepeatedField;
-typedef struct SourceContext SourceContext;
-typedef struct StringValue StringValue;
-typedef struct Struct Struct;
-typedef struct Syntax Syntax;
-typedef struct Timestamp Timestamp;
-typedef struct Type Type;
-typedef struct UInt32Value UInt32Value;
-typedef struct UInt64Value UInt64Value;
-typedef struct Value Value;
-
-// -----------------------------------------------------------------------------
-// Globals.
-// -----------------------------------------------------------------------------
-
-ZEND_BEGIN_MODULE_GLOBALS(protobuf)
- zend_bool keep_descriptor_pool_after_request;
-ZEND_END_MODULE_GLOBALS(protobuf)
-
-ZEND_EXTERN_MODULE_GLOBALS(protobuf)
-
-#ifdef ZTS
-#define PROTOBUF_G(v) TSRMG(protobuf_globals_id, zend_protobuf_globals *, v)
-#else
-#define PROTOBUF_G(v) (protobuf_globals.v)
-#endif
-
-// Init module and PHP classes.
-void any_init(TSRMLS_D);
-void api_init(TSRMLS_D);
-void bool_value_init(TSRMLS_D);
-void bytes_value_init(TSRMLS_D);
-void descriptor_init(TSRMLS_D);
-void descriptor_pool_init(TSRMLS_D);
-void double_value_init(TSRMLS_D);
-void duration_init(TSRMLS_D);
-void empty_init(TSRMLS_D);
-void enum_descriptor_init(TSRMLS_D);
-void enum_value_descriptor_init(TSRMLS_D);
-void enum_init(TSRMLS_D);
-void enum_value_init(TSRMLS_D);
-void field_cardinality_init(TSRMLS_D);
-void field_descriptor_init(TSRMLS_D);
-void field_init(TSRMLS_D);
-void field_kind_init(TSRMLS_D);
-void field_mask_init(TSRMLS_D);
-void float_value_init(TSRMLS_D);
-void gpb_type_init(TSRMLS_D);
-void int32_value_init(TSRMLS_D);
-void int64_value_init(TSRMLS_D);
-void internal_descriptor_pool_init(TSRMLS_D);
-void list_value_init(TSRMLS_D);
-void map_field_init(TSRMLS_D);
-void map_field_iter_init(TSRMLS_D);
-void message_init(TSRMLS_D);
-void method_init(TSRMLS_D);
-void mixin_init(TSRMLS_D);
-void null_value_init(TSRMLS_D);
-void oneof_descriptor_init(TSRMLS_D);
-void option_init(TSRMLS_D);
-void repeated_field_init(TSRMLS_D);
-void repeated_field_iter_init(TSRMLS_D);
-void source_context_init(TSRMLS_D);
-void string_value_init(TSRMLS_D);
-void struct_init(TSRMLS_D);
-void syntax_init(TSRMLS_D);
-void timestamp_init(TSRMLS_D);
-void type_init(TSRMLS_D);
-void u_int32_value_init(TSRMLS_D);
-void u_int64_value_init(TSRMLS_D);
-void util_init(TSRMLS_D);
-void value_init(TSRMLS_D);
-
-void gpb_metadata_any_init(TSRMLS_D);
-void gpb_metadata_api_init(TSRMLS_D);
-void gpb_metadata_duration_init(TSRMLS_D);
-void gpb_metadata_field_mask_init(TSRMLS_D);
-void gpb_metadata_empty_init(TSRMLS_D);
-void gpb_metadata_source_context_init(TSRMLS_D);
-void gpb_metadata_struct_init(TSRMLS_D);
-void gpb_metadata_timestamp_init(TSRMLS_D);
-void gpb_metadata_type_init(TSRMLS_D);
-void gpb_metadata_wrappers_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_msgdef_desc(const upb_msgdef* m, DescriptorInternal* desc);
-DescriptorInternal* get_msgdef_desc(const upb_msgdef* m);
-void add_enumdef_enumdesc(const upb_enumdef* e, EnumDescriptorInternal* desc);
-EnumDescriptorInternal* get_enumdef_enumdesc(const upb_enumdef* e);
-
-// 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_desc(const zend_class_entry* ce, DescriptorInternal* desc);
-DescriptorInternal* get_ce_desc(const zend_class_entry* ce);
-void add_ce_enumdesc(const zend_class_entry* ce, EnumDescriptorInternal* desc);
-EnumDescriptorInternal* get_ce_enumdesc(const zend_class_entry* ce);
-
-// Global map from message/enum's proto fully-qualified name to corresponding
-// wrapper Descriptor/EnumDescriptor instances.
-void add_proto_desc(const char* proto, DescriptorInternal* desc);
-DescriptorInternal* get_proto_desc(const char* proto);
-void add_class_desc(const char* klass, DescriptorInternal* desc);
-DescriptorInternal* get_class_desc(const char* klass);
-void add_class_enumdesc(const char* klass, EnumDescriptorInternal* desc);
-EnumDescriptorInternal* get_class_enumdesc(const char* klass);
-
-extern zend_class_entry* map_field_type;
-extern zend_class_entry* repeated_field_type;
-
-// -----------------------------------------------------------------------------
-// Descriptor.
-// -----------------------------------------------------------------------------
-
-PHP_PROTO_WRAP_OBJECT_START(DescriptorPool)
- InternalDescriptorPoolImpl* intern;
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_METHOD(DescriptorPool, getGeneratedPool);
-PHP_METHOD(DescriptorPool, getDescriptorByClassName);
-PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName);
-
-struct InternalDescriptorPoolImpl {
- upb_symtab* symtab;
- upb_handlercache* fill_handler_cache;
- upb_handlercache* pb_serialize_handler_cache;
- upb_handlercache* json_serialize_handler_cache;
- upb_handlercache* json_serialize_handler_preserve_cache;
- upb_pbcodecache* fill_method_cache;
- upb_json_codecache* json_fill_method_cache;
-};
-
-PHP_PROTO_WRAP_OBJECT_START(InternalDescriptorPool)
- InternalDescriptorPoolImpl* intern;
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_METHOD(InternalDescriptorPool, getGeneratedPool);
-PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile);
-
-void internal_add_generated_file(const char* data, PHP_PROTO_SIZE data_len,
- InternalDescriptorPoolImpl* pool,
- bool use_nested_submsg TSRMLS_DC);
-void init_generated_pool_once(TSRMLS_D);
-void add_handlers_for_message(const void* closure, upb_handlers* h);
-void register_class(void *desc, bool is_enum TSRMLS_DC);
-
-// wrapper of generated pool
-#if PHP_MAJOR_VERSION < 7
-extern zval* generated_pool_php;
-extern zval* internal_generated_pool_php;
-void descriptor_pool_free(void* object TSRMLS_DC);
-void internal_descriptor_pool_free(void* object TSRMLS_DC);
-#else
-extern zend_object *generated_pool_php;
-extern zend_object *internal_generated_pool_php;
-void descriptor_pool_free(zend_object* object);
-void internal_descriptor_pool_free(zend_object* object);
-#endif
-extern InternalDescriptorPoolImpl* generated_pool;
-// The actual generated pool
-extern InternalDescriptorPoolImpl generated_pool_impl;
-
-void internal_descriptor_pool_impl_init(
- InternalDescriptorPoolImpl *pool TSRMLS_DC);
-void internal_descriptor_pool_impl_destroy(
- InternalDescriptorPoolImpl *pool TSRMLS_DC);
-
-struct DescriptorInternal {
- InternalDescriptorPoolImpl* pool;
- const upb_msgdef* msgdef;
- MessageLayout* layout;
- zend_class_entry* klass; // begins as NULL
- bool use_nested_submsg;
- char* classname;
-};
-
-PHP_PROTO_WRAP_OBJECT_START(Descriptor)
- DescriptorInternal* intern;
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_METHOD(Descriptor, getClass);
-PHP_METHOD(Descriptor, getFullName);
-PHP_METHOD(Descriptor, getField);
-PHP_METHOD(Descriptor, getFieldCount);
-PHP_METHOD(Descriptor, getOneofDecl);
-PHP_METHOD(Descriptor, getOneofDeclCount);
-
-extern zend_class_entry* descriptor_type;
-
-void descriptor_name_set(Descriptor *desc, const char *name);
-
-PHP_PROTO_WRAP_OBJECT_START(FieldDescriptor)
- const upb_fielddef* fielddef;
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_METHOD(FieldDescriptor, getName);
-PHP_METHOD(FieldDescriptor, getNumber);
-PHP_METHOD(FieldDescriptor, getLabel);
-PHP_METHOD(FieldDescriptor, getType);
-PHP_METHOD(FieldDescriptor, isMap);
-PHP_METHOD(FieldDescriptor, getEnumType);
-PHP_METHOD(FieldDescriptor, getMessageType);
-
-extern zend_class_entry* field_descriptor_type;
-
-struct EnumDescriptorInternal {
- const upb_enumdef* enumdef;
- zend_class_entry* klass; // begins as NULL
- bool use_nested_submsg;
- char* classname;
-};
-
-PHP_PROTO_WRAP_OBJECT_START(EnumDescriptor)
- EnumDescriptorInternal* intern;
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_METHOD(EnumDescriptor, getValue);
-PHP_METHOD(EnumDescriptor, getValueCount);
-
-extern zend_class_entry* enum_descriptor_type;
-
-PHP_PROTO_WRAP_OBJECT_START(EnumValueDescriptor)
- const char* name;
- int32_t number;
-PHP_PROTO_WRAP_OBJECT_END
-
-PHP_METHOD(EnumValueDescriptor, getName);
-PHP_METHOD(EnumValueDescriptor, getNumber);
-
-extern zend_class_entry* enum_value_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);
-
-extern zend_class_entry* message_type;
-extern zend_object_handlers* message_handlers;
-
-// -----------------------------------------------------------------------------
-// Message layout / storage.
-// -----------------------------------------------------------------------------
-
-/*
- * In c extension, each protobuf message is a zval instance. The zval instance
- * is like union, which can be used to store int, string, zend_object_value and
- * etc. For protobuf message, the zval instance is used to store the
- * zend_object_value.
- *
- * The zend_object_value is composed of handlers and a handle to look up the
- * actual stored data. The handlers are pointers to functions, e.g., read,
- * write, and etc, to access properties.
- *
- * The actual data of protobuf messages is stored as MessageHeader in zend
- * engine's central repository. Each MessageHeader instance is composed of a
- * zend_object, a Descriptor instance and the real message data.
- *
- * For the reason that PHP's native types may not be large enough to store
- * protobuf message's field (e.g., int64), all message's data is stored in
- * custom memory layout and is indexed by the Descriptor instance.
- *
- * The zend_object contains the zend class entry and the properties table. The
- * zend class entry contains all information about protobuf message's
- * corresponding PHP class. The most useful information is the offset table of
- * properties. Because read access to properties requires returning zval
- * instance, we need to convert data from the custom layout to zval instance.
- * Instead of creating zval instance for every read access, we use the zval
- * instances in the properties table in the zend_object as cache. When
- * accessing properties, the offset is needed to find the zval property in
- * zend_object's properties table. These properties will be updated using the
- * data from custom memory layout only when reading these properties.
- *
- * zval
- * |-zend_object_value obj
- * |-zend_object_handlers* handlers -> |-read_property_handler
- * | |-write_property_handler
- * | ++++++++++++++++++++++
- * |-zend_object_handle handle -> + central repository +
- * ++++++++++++++++++++++
- * MessageHeader <-----------------|
- * |-zend_object std
- * | |-class_entry* ce -> class_entry
- * | | |-HashTable properties_table (name->offset)
- * | |-zval** properties_table <------------------------------|
- * | |------> zval* property(cache)
- * |-Descriptor* desc (name->offset)
- * |-void** data <-----------|
- * |-----------------------> void* property(data)
- *
- */
-
-#define MESSAGE_FIELD_NO_CASE ((size_t)-1)
-
-struct MessageField {
- size_t offset;
- int cache_index; // Each field except oneof field has a zval cache to avoid
- // multiple creation when being accessed.
- size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE.
-};
-
-struct MessageLayout {
- const upb_msgdef* msgdef;
- void* empty_template; // Can memcpy() onto a layout to clear it.
- MessageField* fields;
- 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.
- DescriptorInternal* descriptor; // Kept alive by self.class.descriptor
- // reference.
-PHP_PROTO_WRAP_OBJECT_END
-
-MessageLayout* create_layout(const upb_msgdef* msgdef);
-void layout_init(MessageLayout* layout, void* storage,
- zend_object* object PHP_PROTO_TSRMLS_DC);
-zval* layout_get(MessageLayout* layout, MessageHeader* header,
- const upb_fielddef* field, CACHED_VALUE* 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,
- MessageHeader* to TSRMLS_DC);
-const char* layout_get_oneof_case(MessageLayout* layout, const void* storage,
- const upb_oneofdef* oneof TSRMLS_DC);
-void free_layout(MessageLayout* layout);
-uint32_t* slot_oneof_case(MessageLayout* layout, const void* storage,
- const upb_fielddef* field);
-void* slot_memory(MessageLayout* layout, const void* storage,
- const upb_fielddef* field);
-
-PHP_METHOD(Message, clear);
-PHP_METHOD(Message, mergeFrom);
-PHP_METHOD(Message, readWrapperValue);
-PHP_METHOD(Message, writeWrapperValue);
-PHP_METHOD(Message, readOneof);
-PHP_METHOD(Message, writeOneof);
-PHP_METHOD(Message, whichOneof);
-PHP_METHOD(Message, __construct);
-
-// -----------------------------------------------------------------------------
-// Encode / Decode.
-// -----------------------------------------------------------------------------
-
-// Maximum depth allowed during encoding, to avoid stack overflows due to
-// cycles.
-#define ENCODE_MAX_NESTING 63
-
-// Constructs the upb decoder method for parsing messages of this type.
-// This is called from the message class creation code.
-const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor *desc,
- const void *owner);
-void serialize_to_string(zval* val, zval* return_value TSRMLS_DC);
-void merge_from_string(const char* data, int data_len, DescriptorInternal* desc,
- MessageHeader* msg);
-
-PHP_METHOD(Message, serializeToString);
-PHP_METHOD(Message, mergeFromString);
-PHP_METHOD(Message, serializeToJsonString);
-PHP_METHOD(Message, mergeFromJsonString);
-PHP_METHOD(Message, discardUnknownFields);
-
-// -----------------------------------------------------------------------------
-// Type check / conversion.
-// -----------------------------------------------------------------------------
-
-bool protobuf_convert_to_int32(zval* from, int32_t* to);
-bool protobuf_convert_to_uint32(zval* from, uint32_t* to);
-bool protobuf_convert_to_int64(zval* from, int64_t* to);
-bool protobuf_convert_to_uint64(zval* from, uint64_t* to);
-bool protobuf_convert_to_float(zval* from, float* to);
-bool protobuf_convert_to_double(zval* from, double* to);
-bool protobuf_convert_to_bool(zval* from, int8_t* to);
-bool protobuf_convert_to_string(zval* from);
-
-void check_repeated_field(const zend_class_entry* klass, PHP_PROTO_LONG type,
- zval* val, zval* return_value);
-void check_map_field(const zend_class_entry* klass, PHP_PROTO_LONG key_type,
- PHP_PROTO_LONG value_type, zval* val, zval* return_value);
-
-PHP_METHOD(Util, checkInt32);
-PHP_METHOD(Util, checkUint32);
-PHP_METHOD(Util, checkInt64);
-PHP_METHOD(Util, checkUint64);
-PHP_METHOD(Util, checkEnum);
-PHP_METHOD(Util, checkFloat);
-PHP_METHOD(Util, checkDouble);
-PHP_METHOD(Util, checkBool);
-PHP_METHOD(Util, checkString);
-PHP_METHOD(Util, checkBytes);
-PHP_METHOD(Util, checkMessage);
-PHP_METHOD(Util, checkMapField);
-PHP_METHOD(Util, checkRepeatedField);
-
-// -----------------------------------------------------------------------------
-// Native slot storage abstraction.
-// -----------------------------------------------------------------------------
-
-#define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
-
-size_t native_slot_size(upb_fieldtype_t type);
-bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
- void* memory, zval* value 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);
-bool native_slot_set_by_map(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, CACHED_VALUE* cache);
-// For each property, in order to avoid conversion between the zval object and
-// the actual data type during parsing/serialization, the containing message
-// object use the custom memory layout to store the actual data type for each
-// property inside of it. To access a property from php code, the property
-// needs to be converted to a zval object. The message object is not responsible
-// for providing such a zval object. Instead the caller needs to provide one
-// (cache) and update it with the actual data (memory).
-void native_slot_get(upb_fieldtype_t type, const void* memory,
- 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_by_map_key(upb_fieldtype_t type, const void* memory,
- int length, CACHED_VALUE* cache TSRMLS_DC);
-void native_slot_get_by_map_value(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);
-
-// -----------------------------------------------------------------------------
-// Map Field.
-// -----------------------------------------------------------------------------
-
-extern zend_object_handlers* map_field_handlers;
-extern zend_object_handlers* map_field_iter_handlers;
-
-PHP_PROTO_WRAP_OBJECT_START(Map)
- 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
-
-PHP_PROTO_WRAP_OBJECT_START(MapIter)
- Map* self;
- upb_strtable_iter it;
-PHP_PROTO_WRAP_OBJECT_END
-
-void map_begin(zval* self, MapIter* iter TSRMLS_DC);
-void map_next(MapIter* iter);
-bool map_done(MapIter* iter);
-const char* map_iter_key(MapIter* iter, int* len);
-upb_value map_iter_value(MapIter* iter, int* len);
-
-// These operate on a map-entry msgdef.
-const upb_fielddef* map_entry_key(const upb_msgdef* msgdef);
-const upb_fielddef* map_entry_value(const upb_msgdef* msgdef);
-
-void map_field_ensure_created(const upb_fielddef *field,
- CACHED_VALUE *map_field PHP_PROTO_TSRMLS_DC);
-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,
- upb_fieldtype_t value_type,
- const zend_class_entry* msg_ce,
- CACHED_VALUE* map_field PHP_PROTO_TSRMLS_DC);
-void* upb_value_memory(upb_value* v);
-
-#define MAP_KEY_FIELD 1
-#define MAP_VALUE_FIELD 2
-
-// These operate on a map field (i.e., a repeated field of submessages whose
-// submessage type is a map-entry msgdef).
-bool is_map_field(const upb_fielddef* field);
-const upb_fielddef* map_field_key(const upb_fielddef* field);
-const upb_fielddef* map_field_value(const upb_fielddef* field);
-
-bool map_index_set(Map *intern, const char* keyval, int length, upb_value v);
-
-PHP_METHOD(MapField, __construct);
-PHP_METHOD(MapField, offsetExists);
-PHP_METHOD(MapField, offsetGet);
-PHP_METHOD(MapField, offsetSet);
-PHP_METHOD(MapField, offsetUnset);
-PHP_METHOD(MapField, count);
-PHP_METHOD(MapField, getIterator);
-
-PHP_METHOD(MapFieldIter, rewind);
-PHP_METHOD(MapFieldIter, current);
-PHP_METHOD(MapFieldIter, key);
-PHP_METHOD(MapFieldIter, next);
-PHP_METHOD(MapFieldIter, valid);
-
-// -----------------------------------------------------------------------------
-// Repeated Field.
-// -----------------------------------------------------------------------------
-
-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
- 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)
- RepeatedField* repeated_field;
- long position;
-PHP_PROTO_WRAP_OBJECT_END
-
-void repeated_field_ensure_created(
- 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,
- 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);
-// 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);
-
-PHP_METHOD(RepeatedField, __construct);
-PHP_METHOD(RepeatedField, append);
-PHP_METHOD(RepeatedField, offsetExists);
-PHP_METHOD(RepeatedField, offsetGet);
-PHP_METHOD(RepeatedField, offsetSet);
-PHP_METHOD(RepeatedField, offsetUnset);
-PHP_METHOD(RepeatedField, count);
-PHP_METHOD(RepeatedField, getIterator);
-
-PHP_METHOD(RepeatedFieldIter, rewind);
-PHP_METHOD(RepeatedFieldIter, current);
-PHP_METHOD(RepeatedFieldIter, key);
-PHP_METHOD(RepeatedFieldIter, next);
-PHP_METHOD(RepeatedFieldIter, valid);
-
-// -----------------------------------------------------------------------------
-// Oneof Field.
-// -----------------------------------------------------------------------------
-
-PHP_PROTO_WRAP_OBJECT_START(Oneof)
- const 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
-
-PHP_METHOD(Oneof, getName);
-PHP_METHOD(Oneof, getField);
-PHP_METHOD(Oneof, getFieldCount);
-
-extern zend_class_entry* oneof_descriptor_type;
-
-// Oneof case slot value to indicate that no oneof case is set. The value `0` is
-// safe because field numbers are used as case identifiers, and no field can
-// have a number of 0.
-#define ONEOF_CASE_NONE 0
-
-// -----------------------------------------------------------------------------
-// Well Known Type.
-// -----------------------------------------------------------------------------
-
-extern bool is_inited_file_any;
-extern bool is_inited_file_api;
-extern bool is_inited_file_duration;
-extern bool is_inited_file_field_mask;
-extern bool is_inited_file_empty;
-extern bool is_inited_file_source_context;
-extern bool is_inited_file_struct;
-extern bool is_inited_file_timestamp;
-extern bool is_inited_file_type;
-extern bool is_inited_file_wrappers;
-
-PHP_METHOD(GPBMetadata_Any, initOnce);
-PHP_METHOD(GPBMetadata_Api, initOnce);
-PHP_METHOD(GPBMetadata_Duration, initOnce);
-PHP_METHOD(GPBMetadata_FieldMask, initOnce);
-PHP_METHOD(GPBMetadata_Empty, initOnce);
-PHP_METHOD(GPBMetadata_SourceContext, initOnce);
-PHP_METHOD(GPBMetadata_Struct, initOnce);
-PHP_METHOD(GPBMetadata_Timestamp, initOnce);
-PHP_METHOD(GPBMetadata_Type, initOnce);
-PHP_METHOD(GPBMetadata_Wrappers, initOnce);
-
-PHP_METHOD(Any, __construct);
-PHP_METHOD(Any, getTypeUrl);
-PHP_METHOD(Any, setTypeUrl);
-PHP_METHOD(Any, getValue);
-PHP_METHOD(Any, setValue);
-PHP_METHOD(Any, unpack);
-PHP_METHOD(Any, pack);
-PHP_METHOD(Any, is);
-
-PHP_METHOD(Duration, __construct);
-PHP_METHOD(Duration, getSeconds);
-PHP_METHOD(Duration, setSeconds);
-PHP_METHOD(Duration, getNanos);
-PHP_METHOD(Duration, setNanos);
-
-static PHP_METHOD(Timestamp, __construct);
-PHP_METHOD(Timestamp, fromDateTime);
-PHP_METHOD(Timestamp, toDateTime);
-PHP_METHOD(Timestamp, getSeconds);
-PHP_METHOD(Timestamp, setSeconds);
-PHP_METHOD(Timestamp, getNanos);
-PHP_METHOD(Timestamp, setNanos);
-
-PHP_METHOD(Api, __construct);
-PHP_METHOD(Api, getName);
-PHP_METHOD(Api, setName);
-PHP_METHOD(Api, getMethods);
-PHP_METHOD(Api, setMethods);
-PHP_METHOD(Api, getOptions);
-PHP_METHOD(Api, setOptions);
-PHP_METHOD(Api, getVersion);
-PHP_METHOD(Api, setVersion);
-PHP_METHOD(Api, getSourceContext);
-PHP_METHOD(Api, setSourceContext);
-PHP_METHOD(Api, getMixins);
-PHP_METHOD(Api, setMixins);
-PHP_METHOD(Api, getSyntax);
-PHP_METHOD(Api, setSyntax);
-
-PHP_METHOD(BoolValue, __construct);
-PHP_METHOD(BoolValue, getValue);
-PHP_METHOD(BoolValue, setValue);
-
-PHP_METHOD(BytesValue, __construct);
-PHP_METHOD(BytesValue, getValue);
-PHP_METHOD(BytesValue, setValue);
-
-PHP_METHOD(DoubleValue, __construct);
-PHP_METHOD(DoubleValue, getValue);
-PHP_METHOD(DoubleValue, setValue);
-
-PHP_METHOD(Enum, __construct);
-PHP_METHOD(Enum, getName);
-PHP_METHOD(Enum, setName);
-PHP_METHOD(Enum, getEnumvalue);
-PHP_METHOD(Enum, setEnumvalue);
-PHP_METHOD(Enum, getOptions);
-PHP_METHOD(Enum, setOptions);
-PHP_METHOD(Enum, getSourceContext);
-PHP_METHOD(Enum, setSourceContext);
-PHP_METHOD(Enum, getSyntax);
-PHP_METHOD(Enum, setSyntax);
-
-PHP_METHOD(EnumValue, __construct);
-PHP_METHOD(EnumValue, getName);
-PHP_METHOD(EnumValue, setName);
-PHP_METHOD(EnumValue, getNumber);
-PHP_METHOD(EnumValue, setNumber);
-PHP_METHOD(EnumValue, getOptions);
-PHP_METHOD(EnumValue, setOptions);
-
-PHP_METHOD(FieldMask, __construct);
-PHP_METHOD(FieldMask, getPaths);
-PHP_METHOD(FieldMask, setPaths);
-
-PHP_METHOD(Field, __construct);
-PHP_METHOD(Field, getKind);
-PHP_METHOD(Field, setKind);
-PHP_METHOD(Field, getCardinality);
-PHP_METHOD(Field, setCardinality);
-PHP_METHOD(Field, getNumber);
-PHP_METHOD(Field, setNumber);
-PHP_METHOD(Field, getName);
-PHP_METHOD(Field, setName);
-PHP_METHOD(Field, getTypeUrl);
-PHP_METHOD(Field, setTypeUrl);
-PHP_METHOD(Field, getOneofIndex);
-PHP_METHOD(Field, setOneofIndex);
-PHP_METHOD(Field, getPacked);
-PHP_METHOD(Field, setPacked);
-PHP_METHOD(Field, getOptions);
-PHP_METHOD(Field, setOptions);
-PHP_METHOD(Field, getJsonName);
-PHP_METHOD(Field, setJsonName);
-PHP_METHOD(Field, getDefaultValue);
-PHP_METHOD(Field, setDefaultValue);
-
-PHP_METHOD(Field_Cardinality, name);
-PHP_METHOD(Field_Cardinality, value);
-
-PHP_METHOD(Field_Kind, name);
-PHP_METHOD(Field_Kind, value);
-
-PHP_METHOD(FloatValue, __construct);
-PHP_METHOD(FloatValue, getValue);
-PHP_METHOD(FloatValue, setValue);
-
-PHP_METHOD(GPBEmpty, __construct);
-
-PHP_METHOD(Int32Value, __construct);
-PHP_METHOD(Int32Value, getValue);
-PHP_METHOD(Int32Value, setValue);
-
-PHP_METHOD(Int64Value, __construct);
-PHP_METHOD(Int64Value, getValue);
-PHP_METHOD(Int64Value, setValue);
-
-PHP_METHOD(ListValue, __construct);
-PHP_METHOD(ListValue, getValues);
-PHP_METHOD(ListValue, setValues);
-
-PHP_METHOD(Method, __construct);
-PHP_METHOD(Method, getName);
-PHP_METHOD(Method, setName);
-PHP_METHOD(Method, getRequestTypeUrl);
-PHP_METHOD(Method, setRequestTypeUrl);
-PHP_METHOD(Method, getRequestStreaming);
-PHP_METHOD(Method, setRequestStreaming);
-PHP_METHOD(Method, getResponseTypeUrl);
-PHP_METHOD(Method, setResponseTypeUrl);
-PHP_METHOD(Method, getResponseStreaming);
-PHP_METHOD(Method, setResponseStreaming);
-PHP_METHOD(Method, getOptions);
-PHP_METHOD(Method, setOptions);
-PHP_METHOD(Method, getSyntax);
-PHP_METHOD(Method, setSyntax);
-
-PHP_METHOD(Mixin, __construct);
-PHP_METHOD(Mixin, getName);
-PHP_METHOD(Mixin, setName);
-PHP_METHOD(Mixin, getRoot);
-PHP_METHOD(Mixin, setRoot);
-
-PHP_METHOD(NullValue, name);
-PHP_METHOD(NullValue, value);
-
-PHP_METHOD(Option, __construct);
-PHP_METHOD(Option, getName);
-PHP_METHOD(Option, setName);
-PHP_METHOD(Option, getValue);
-PHP_METHOD(Option, setValue);
-
-PHP_METHOD(SourceContext, __construct);
-PHP_METHOD(SourceContext, getFileName);
-PHP_METHOD(SourceContext, setFileName);
-
-PHP_METHOD(StringValue, __construct);
-PHP_METHOD(StringValue, getValue);
-PHP_METHOD(StringValue, setValue);
-
-PHP_METHOD(Struct, __construct);
-PHP_METHOD(Struct, getFields);
-PHP_METHOD(Struct, setFields);
-
-PHP_METHOD(Syntax, name);
-PHP_METHOD(Syntax, value);
-
-PHP_METHOD(Type, __construct);
-PHP_METHOD(Type, getName);
-PHP_METHOD(Type, setName);
-PHP_METHOD(Type, getFields);
-PHP_METHOD(Type, setFields);
-PHP_METHOD(Type, getOneofs);
-PHP_METHOD(Type, setOneofs);
-PHP_METHOD(Type, getOptions);
-PHP_METHOD(Type, setOptions);
-PHP_METHOD(Type, getSourceContext);
-PHP_METHOD(Type, setSourceContext);
-PHP_METHOD(Type, getSyntax);
-PHP_METHOD(Type, setSyntax);
-
-PHP_METHOD(UInt32Value, __construct);
-PHP_METHOD(UInt32Value, getValue);
-PHP_METHOD(UInt32Value, setValue);
-
-PHP_METHOD(UInt64Value, __construct);
-PHP_METHOD(UInt64Value, getValue);
-PHP_METHOD(UInt64Value, setValue);
-
-PHP_METHOD(Value, __construct);
-PHP_METHOD(Value, getNullValue);
-PHP_METHOD(Value, setNullValue);
-PHP_METHOD(Value, getNumberValue);
-PHP_METHOD(Value, setNumberValue);
-PHP_METHOD(Value, getStringValue);
-PHP_METHOD(Value, setStringValue);
-PHP_METHOD(Value, getBoolValue);
-PHP_METHOD(Value, setBoolValue);
-PHP_METHOD(Value, getStructValue);
-PHP_METHOD(Value, setStructValue);
-PHP_METHOD(Value, getListValue);
-PHP_METHOD(Value, setListValue);
-PHP_METHOD(Value, getKind);
-
-extern zend_class_entry* any_type;
-extern zend_class_entry* api_type;
-extern zend_class_entry* bool_value_type;
-extern zend_class_entry* bytes_value_type;
-extern zend_class_entry* double_value_type;
-extern zend_class_entry* duration_type;
-extern zend_class_entry* empty_type;
-extern zend_class_entry* enum_type;
-extern zend_class_entry* enum_value_type;
-extern zend_class_entry* field_cardinality_type;
-extern zend_class_entry* field_kind_type;
-extern zend_class_entry* field_mask_type;
-extern zend_class_entry* field_type;
-extern zend_class_entry* float_value_type;
-extern zend_class_entry* int32_value_type;
-extern zend_class_entry* int64_value_type;
-extern zend_class_entry* list_value_type;
-extern zend_class_entry* method_type;
-extern zend_class_entry* mixin_type;
-extern zend_class_entry* null_value_type;
-extern zend_class_entry* option_type;
-extern zend_class_entry* source_context_type;
-extern zend_class_entry* string_value_type;
-extern zend_class_entry* struct_type;
-extern zend_class_entry* syntax_type;
-extern zend_class_entry* timestamp_type;
-extern zend_class_entry* type_type;
-extern zend_class_entry* uint32_value_type;
-extern zend_class_entry* uint64_value_type;
-extern zend_class_entry* value_type;
-
-// -----------------------------------------------------------------------------
-// Upb.
-// -----------------------------------------------------------------------------
-
-upb_fieldtype_t to_fieldtype(upb_descriptortype_t type);
-const zend_class_entry* field_type_class(
- const upb_fielddef* field PHP_PROTO_TSRMLS_DC);
-void stringsink_uninit_opaque(void *sink);
-
-typedef struct {
- upb_byteshandler handler;
- upb_bytessink sink;
- char *ptr;
- size_t len, size;
-} stringsink;
-
-void stringsink_init(stringsink *sink);
-void stringsink_uninit(stringsink *sink);
-size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
- size_t len, const upb_bufhandle *handle);
-
-// -----------------------------------------------------------------------------
-// Utilities.
-// -----------------------------------------------------------------------------
-
-// Memory management
-#define SYS_MALLOC(class_name) (class_name*) malloc(sizeof(class_name))
-#define SYS_MALLOC_N(class_name, n) (class_name*) malloc(sizeof(class_name) * n)
-#define SYS_FREE(ptr) free(ptr)
-#define ALLOC(class_name) (class_name*) emalloc(sizeof(class_name))
-#define PEMALLOC(class_name, persistent) (class_name*) pemalloc(sizeof(class_name), persistent)
-#define ALLOC_N(class_name, n) (class_name*) emalloc(sizeof(class_name) * n)
-#define FREE(object) efree(object)
-#define PEFREE(object) pefree(object, 1)
-
-// Find corresponding zval property for the field.
-CACHED_VALUE* find_zval_property(MessageHeader* msg, const upb_fielddef* field);
-
-// 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
-
-// Message handler
-static inline zval* php_proto_message_read_property(
- zval* msg, zval* member PHP_PROTO_TSRMLS_DC) {
-#if PHP_MAJOR_VERSION < 7
- return message_handlers->read_property(msg, member, BP_VAR_R,
- NULL PHP_PROTO_TSRMLS_CC);
+// ptr -> PHP object cache. This is a weak map that caches lazily-created
+// wrapper objects around upb types:
+// * upb_msg* -> Message
+// * upb_array* -> RepeatedField
+// * upb_map*, -> MapField
+// * upb_msgdef* -> Descriptor
+// * upb_enumdef* -> EnumDescriptor
+// * zend_class_entry* -> Descriptor
+//
+// Each wrapped object should add itself to the map when it is constructed, and
+// remove itself from the map when it is destroyed. This is how we ensure that
+// the map only contains live objects. The map is weak so it does not actually
+// take references to the cached objects.
+void ObjCache_Add(const void *key, zend_object *php_obj);
+void ObjCache_Delete(const void *key);
+bool ObjCache_Get(const void *key, zval *val);
+
+// PHP class name map. This is necessary because the pb_name->php_class_name
+// transformation is non-reversible, so when we need to look up a msgdef or
+// enumdef by PHP class, we can't turn the class name into a pb_name.
+// * php_class_name -> upb_msgdef*
+// * php_class_name -> upb_enumdef*
+void NameMap_AddMessage(const upb_msgdef *m);
+void NameMap_AddEnum(const upb_enumdef *m);
+const upb_msgdef *NameMap_GetMessage(zend_class_entry *ce);
+const upb_enumdef *NameMap_GetEnum(zend_class_entry *ce);
+
+// We need our own assert() because PHP takes control of NDEBUG in its headers.
+#ifdef PBPHP_ENABLE_ASSERTS
+#define PBPHP_ASSERT(x) \
+ do { \
+ if (!(x)) { \
+ fprintf(stderr, "Assertion failure at %s:%d %s", __FILE__, __LINE__, \
+ #x); \
+ abort(); \
+ } \
+ } while (false)
#else
- return message_handlers->read_property(msg, member, BP_VAR_R, NULL,
- NULL PHP_PROTO_TSRMLS_CC);
+#define PBPHP_ASSERT(x) \
+ do { \
+ } while (false && (x))
#endif
-}
-
-// Reserved name
-bool is_reserved_name(const char* name);
-bool is_valid_constant_name(const char* name);
-
-// For lazy wrapper
-bool is_wrapper_msg(const upb_msgdef* m);
-#endif // __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
+#endif // PHP_PROTOBUF_H_
diff --git a/php/ext/google/protobuf/storage.c b/php/ext/google/protobuf/storage.c
deleted file mode 100644
index fec7335847..0000000000
--- a/php/ext/google/protobuf/storage.c
+++ /dev/null
@@ -1,1180 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include
-#include
-#include
-
-#include "utf8.h"
-
-// -----------------------------------------------------------------------------
-// Native slot storage.
-// -----------------------------------------------------------------------------
-
-#define DEREF(memory, type) *(type*)(memory)
-
-size_t native_slot_size(upb_fieldtype_t type) {
- switch (type) {
- case UPB_TYPE_FLOAT: return 4;
- case UPB_TYPE_DOUBLE: return 8;
- case UPB_TYPE_BOOL: return 1;
- case UPB_TYPE_STRING: return sizeof(void*);
- case UPB_TYPE_BYTES: return sizeof(void*);
- case UPB_TYPE_MESSAGE: return sizeof(void*);
- case UPB_TYPE_ENUM: return 4;
- case UPB_TYPE_INT32: return 4;
- case UPB_TYPE_INT64: return 8;
- case UPB_TYPE_UINT32: return 4;
- case UPB_TYPE_UINT64: return 8;
- default: return 0;
- }
-}
-
-static bool native_slot_is_default(upb_fieldtype_t type, const void* memory) {
- switch (type) {
-#define CASE_TYPE(upb_type, c_type) \
- case UPB_TYPE_##upb_type: { \
- return DEREF(memory, c_type) == 0; \
- }
- 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:
- return Z_STRLEN_P(CACHED_PTR_TO_ZVAL_PTR(memory)) == 0;
- case UPB_TYPE_MESSAGE:
- return Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(memory)) == 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) {
- 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;
- }
-
- zval* cached_zval = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
- if (EXPECTED(cached_zval != NULL)) {
-#if PHP_MAJOR_VERSION < 7
- REPLACE_ZVAL_VALUE((zval**)memory, value, 1);
-#elif PHP_VERSION_ID < 70400
- zend_assign_to_variable(cached_zval, value, IS_CV);
-#else
- zend_assign_to_variable(cached_zval, value, IS_CV, 0);
-#endif
- }
- break;
- }
- case UPB_TYPE_MESSAGE: {
- if (Z_TYPE_P(value) != IS_OBJECT && Z_TYPE_P(value) != IS_NULL) {
- zend_error(E_USER_ERROR, "Given value is not message.");
- return false;
- }
- if (Z_TYPE_P(value) == IS_OBJECT && klass != Z_OBJCE_P(value)) {
- zend_error(E_USER_ERROR, "Given message does not have correct class.");
- return false;
- }
-
-#if PHP_MAJOR_VERSION < 7
- REPLACE_ZVAL_VALUE((CACHED_VALUE*)memory, value, 1);
-#else
- zval* property_ptr = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
- if (EXPECTED(property_ptr != value)) {
- php_proto_zval_ptr_dtor(property_ptr);
- }
-
- ZVAL_ZVAL(property_ptr, value, 1, 0);
-#endif
-
- 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(value, &type##_value)) { \
- DEREF(memory, c_type) = type##_value; \
- } \
- break; \
- }
- CASE_TYPE(INT32, int32, int32_t, LONG)
- CASE_TYPE(UINT32, uint32, uint32_t, LONG)
- CASE_TYPE(ENUM, int32, int32_t, LONG)
- CASE_TYPE(INT64, int64, int64_t, LONG)
- CASE_TYPE(UINT64, uint64, uint64_t, LONG)
- CASE_TYPE(FLOAT, float, float, DOUBLE)
- CASE_TYPE(DOUBLE, double, double, DOUBLE)
- CASE_TYPE(BOOL, bool, int8_t, BOOL)
-
-#undef CASE_TYPE
-
- default:
- break;
- }
-
- return true;
-}
-
-bool native_slot_set_by_array(upb_fieldtype_t type,
- const zend_class_entry* klass, void* memory,
- zval* value TSRMLS_DC) {
-#if PHP_MAJOR_VERSION >= 7
- if (Z_ISREF_P(value)) {
- ZVAL_DEREF(value);
- }
-#endif
- 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_init(Z_STRVAL_P(value), Z_STRLEN_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, zval*) = value;
- GC_ADDREF(Z_OBJ_P(value));
-#endif
- break;
- }
- default:
- return native_slot_set(type, klass, memory, value TSRMLS_CC);
- }
- return true;
-}
-
-bool native_slot_set_by_map(upb_fieldtype_t type, const zend_class_entry* klass,
- void* memory, zval* value TSRMLS_DC) {
-#if PHP_MAJOR_VERSION >= 7
- if (Z_ISREF_P(value)) {
- ZVAL_DEREF(value);
- }
-#endif
- 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_init(Z_STRVAL_P(value), Z_STRLEN_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_ADDREF(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, CACHED_VALUE* cache) {
- switch (type) {
- case UPB_TYPE_FLOAT:
- DEREF(memory, float) = 0.0;
- break;
- case UPB_TYPE_DOUBLE:
- DEREF(memory, double) = 0.0;
- break;
- case UPB_TYPE_BOOL:
- DEREF(memory, int8_t) = 0;
- break;
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES:
- case UPB_TYPE_MESSAGE:
- DEREF(memory, CACHED_VALUE*) = cache;
- break;
- case UPB_TYPE_ENUM:
- case UPB_TYPE_INT32:
- DEREF(memory, int32_t) = 0;
- break;
- case UPB_TYPE_INT64:
- DEREF(memory, int64_t) = 0;
- break;
- case UPB_TYPE_UINT32:
- DEREF(memory, uint32_t) = 0;
- break;
- case UPB_TYPE_UINT64:
- DEREF(memory, uint64_t) = 0;
- break;
- default:
- break;
- }
-}
-
-void native_slot_get(upb_fieldtype_t type, const void* memory,
- CACHED_VALUE* 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;
-
- 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; \
- }
-#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; \
- }
-#endif
-CASE(UINT64, uint64_t)
-CASE(INT64, int64_t)
-#undef CASE
-
- case UPB_TYPE_UINT32: {
- // Prepend bit-1 for negative numbers, so that uint32 value will be
- // consistent on both 32-bit and 64-bit architectures.
- PHP_PROTO_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);
- 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);
- }
- 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);
- }
- return;
- }
- default:
- return;
- }
-}
-
-void native_slot_get_by_array(upb_fieldtype_t type, const void* memory,
- CACHED_VALUE* 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
- ZVAL_COPY(CACHED_PTR_TO_ZVAL_PTR(cache), memory);
-#endif
- return;
- }
- default:
- native_slot_get(type, memory, cache TSRMLS_CC);
- }
-}
-
-void native_slot_get_by_map_key(upb_fieldtype_t type, const void* memory,
- int length, CACHED_VALUE* cache TSRMLS_DC) {
- switch (type) {
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES: {
- PHP_PROTO_ZVAL_STRINGL(CACHED_PTR_TO_ZVAL_PTR(cache), memory, length, 1);
- return;
- }
- default:
- native_slot_get(type, memory, cache TSRMLS_CC);
- }
-}
-
-void native_slot_get_by_map_value(upb_fieldtype_t type, const void* memory,
- CACHED_VALUE* cache TSRMLS_DC) {
- switch (type) {
- 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_ADDREF(*(zend_object**)memory);
- ZVAL_OBJ(cache, *(zend_object**)memory);
-#endif
- return;
- }
- default:
- native_slot_get_by_array(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); \
- return;
-
- CASE(FLOAT, DOUBLE)
- CASE(DOUBLE, DOUBLE)
- CASE(BOOL, BOOL)
- CASE(INT32, LONG)
- CASE(UINT32, LONG)
- CASE(ENUM, LONG)
-
-#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; \
- }
-#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; \
- }
-#endif
-CASE(UINT64)
-CASE(INT64)
-#undef CASE
-
- 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);
- break;
- }
- case UPB_TYPE_MESSAGE: {
- PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);
- ZVAL_NULL(CACHED_PTR_TO_ZVAL_PTR(cache));
- return;
- }
- default:
- return;
- }
-}
-
-// -----------------------------------------------------------------------------
-// Map field utilities.
-// ----------------------------------------------------------------------------
-
-const upb_msgdef* tryget_map_entry_msgdef(const upb_fielddef* field) {
- const upb_msgdef* subdef;
- if (upb_fielddef_label(field) != UPB_LABEL_REPEATED ||
- upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
- return NULL;
- }
- subdef = upb_fielddef_msgsubdef(field);
- return upb_msgdef_mapentry(subdef) ? subdef : NULL;
-}
-
-const upb_msgdef* map_entry_msgdef(const upb_fielddef* field) {
- const upb_msgdef* subdef = tryget_map_entry_msgdef(field);
- assert(subdef);
- return subdef;
-}
-
-bool is_map_field(const upb_fielddef* field) {
- return tryget_map_entry_msgdef(field) != NULL;
-}
-
-const upb_fielddef* map_field_key(const upb_fielddef* field) {
- const upb_msgdef* subdef = map_entry_msgdef(field);
- return map_entry_key(subdef);
-}
-
-const upb_fielddef* map_field_value(const upb_fielddef* field) {
- const upb_msgdef* subdef = map_entry_msgdef(field);
- return map_entry_value(subdef);
-}
-
-const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) {
- const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD);
- assert(key_field != NULL);
- return key_field;
-}
-
-const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
- const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD);
- assert(value_field != NULL);
- return value_field;
-}
-
-const zend_class_entry* field_type_class(
- const upb_fielddef* field PHP_PROTO_TSRMLS_DC) {
- if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
- DescriptorInternal* desc = get_msgdef_desc(upb_fielddef_msgsubdef(field));
- register_class(desc, false TSRMLS_CC);
- return desc->klass;
- } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
- EnumDescriptorInternal* desc =
- get_enumdef_enumdesc(upb_fielddef_enumsubdef(field));
- register_class(desc, false TSRMLS_CC);
- return desc->klass;
- }
- return NULL;
-}
-
-// -----------------------------------------------------------------------------
-// Memory layout management.
-// -----------------------------------------------------------------------------
-
-static size_t align_up_to(size_t offset, size_t granularity) {
- // Granularity must be a power of two.
- return (offset + granularity - 1) & ~(granularity - 1);
-}
-
-uint32_t* slot_oneof_case(MessageLayout* layout, const void* storage,
- const upb_fielddef* field) {
- return (uint32_t*)(((uint8_t*)storage) +
- layout->fields[upb_fielddef_index(field)].case_offset);
-}
-
-void* slot_memory(MessageLayout* layout, const void* storage,
- const upb_fielddef* field) {
- return ((uint8_t*)storage) + layout->fields[upb_fielddef_index(field)].offset;
-}
-
-MessageLayout* create_layout(const upb_msgdef* msgdef) {
- MessageLayout* layout = SYS_MALLOC(MessageLayout);
- int nfields = upb_msgdef_numfields(msgdef);
- upb_msg_field_iter it;
- upb_msg_oneof_iter oit;
- size_t off = 0;
- int i = 0;
-
- // Reserve space for unknown fields.
- off += sizeof(void*);
-
- layout->empty_template = NULL;
-
- TSRMLS_FETCH();
- DescriptorInternal* desc = get_msgdef_desc(msgdef);
- register_class(desc, false TSRMLS_CC);
- layout->fields = SYS_MALLOC_N(MessageField, nfields);
-
- 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);
- size_t field_size;
-
- if (upb_fielddef_containingoneof(field)) {
- // Oneofs are handled separately below.
- continue;
- }
-
- // Allocate |field_size| bytes for this field in the layout.
- field_size = 0;
- if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
- field_size = sizeof(zval*);
- } else {
- field_size = native_slot_size(upb_fielddef_type(field));
- }
-
- // Align current offset up to | size | granularity.
- off = align_up_to(off, field_size);
- layout->fields[upb_fielddef_index(field)].offset = off;
- layout->fields[upb_fielddef_index(field)].case_offset =
- MESSAGE_FIELD_NO_CASE;
-
- const char* fieldname = upb_fielddef_name(field);
-
-#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
- zend_class_entry* old_scope = EG(scope);
- EG(scope) = desc->klass;
-#else
- zend_class_entry* old_scope = EG(fake_scope);
- EG(fake_scope) = desc->klass;
-#endif
-
-#if PHP_MAJOR_VERSION < 7
- zval member;
- ZVAL_STRINGL(&member, fieldname, strlen(fieldname), 0);
- zend_property_info* property_info =
- zend_get_property_info(desc->klass, &member, true TSRMLS_CC);
-#else
- zend_string* member = zend_string_init(fieldname, strlen(fieldname), 1);
- zend_property_info* property_info =
- zend_get_property_info(desc->klass, member, true);
- zend_string_release(member);
-#endif
-
-#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
- EG(scope) = old_scope;
-#else
- EG(fake_scope) = old_scope;
-#endif
-
- layout->fields[upb_fielddef_index(field)].cache_index =
- property_info->offset;
- off += field_size;
- }
-
- // Handle oneofs now -- we iterate over oneofs specifically and allocate only
- // one slot per oneof.
- //
- // We assign all value slots first, then pack the 'case' fields at the end,
- // since in the common case (modern 64-bit platform) these are 8 bytes and 4
- // bytes respectively and we want to avoid alignment overhead.
- //
- // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value
- // space for oneof cases is conceptually as wide as field tag numbers. In
- // practice, it's unlikely that a oneof would have more than e.g. 256 or 64K
- // members (8 or 16 bits respectively), so conceivably we could assign
- // consecutive case numbers and then pick a smaller oneof case slot size, but
- // the complexity to implement this indirection is probably not worthwhile.
- for (upb_msg_oneof_begin(&oit, msgdef); !upb_msg_oneof_done(&oit);
- upb_msg_oneof_next(&oit)) {
- const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
- upb_oneof_iter fit;
-
- // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
- // all fields.
- size_t field_size = NATIVE_SLOT_MAX_SIZE;
- // Align the offset .
- off = align_up_to( off, field_size);
- // Assign all fields in the oneof this same offset.
- const char* oneofname = upb_oneofdef_name(oneof);
- for (upb_oneof_begin(&fit, oneof); !upb_oneof_done(&fit);
- upb_oneof_next(&fit)) {
- const upb_fielddef* field = upb_oneof_iter_field(&fit);
- layout->fields[upb_fielddef_index(field)].offset = off;
-
-#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
- zend_class_entry* old_scope = EG(scope);
- EG(scope) = desc->klass;
-#else
- zend_class_entry* old_scope = EG(fake_scope);
- EG(fake_scope) = desc->klass;
-#endif
-
-#if PHP_MAJOR_VERSION < 7
- zval member;
- ZVAL_STRINGL(&member, oneofname, strlen(oneofname), 0);
- zend_property_info* property_info =
- zend_get_property_info(desc->klass, &member, true TSRMLS_CC);
-#else
- zend_string* member = zend_string_init(oneofname, strlen(oneofname), 1);
- zend_property_info* property_info =
- zend_get_property_info(desc->klass, member, true);
- zend_string_release(member);
-#endif
-
-#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
- EG(scope) = old_scope;
-#else
- EG(fake_scope) = old_scope;
-#endif
-
- layout->fields[upb_fielddef_index(field)].cache_index =
- property_info->offset;
- }
- i++;
- off += field_size;
- }
-
- // Now the case offset.
- for (upb_msg_oneof_begin(&oit, msgdef); !upb_msg_oneof_done(&oit);
- upb_msg_oneof_next(&oit)) {
- const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
- upb_oneof_iter fit;
-
- size_t field_size = sizeof(uint32_t);
- // Align the offset .
- off = (off + field_size - 1) & ~(field_size - 1);
- // Assign all fields in the oneof this same offset.
- for (upb_oneof_begin(&fit, oneof); !upb_oneof_done(&fit);
- upb_oneof_next(&fit)) {
- const upb_fielddef* field = upb_oneof_iter_field(&fit);
- layout->fields[upb_fielddef_index(field)].case_offset = off;
- }
- off += field_size;
- }
-
- layout->size = off;
- layout->msgdef = msgdef;
-
- // Create the empty message template.
- layout->empty_template = SYS_MALLOC_N(char, layout->size);
- memset(layout->empty_template, 0, layout->size);
-
- return layout;
-}
-
-void free_layout(MessageLayout* layout) {
- SYS_FREE(layout->empty_template);
- SYS_FREE(layout->fields);
- SYS_FREE(layout);
-}
-
-void layout_init(MessageLayout* layout, void* storage,
- zend_object* object PHP_PROTO_TSRMLS_DC) {
- memcpy(storage, layout->empty_template, layout->size);
-}
-
-// Switch memory for processing for singular fields based on field type.
-// * primitive fields: memory
-// * others (string, bytes and message): cache (the correspond zval
-// property)
-static void* value_memory(
- upb_fieldtype_t type, void* memory, CACHED_VALUE* cache) {
- switch (type) {
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES:
- case UPB_TYPE_MESSAGE:
- return cache;
- default:
- // No operation
- break;
- }
- return memory;
-}
-
-CACHED_VALUE* find_zval_property(
- MessageHeader* header, const upb_fielddef* field) {
- int property_cache_index =
- header->descriptor->layout->fields[upb_fielddef_index(field)]
- .cache_index;
- return OBJ_PROP(&header->std, property_cache_index);
-}
-
-zval* layout_get(MessageLayout* layout, MessageHeader* header,
- const upb_fielddef* field, CACHED_VALUE* cache TSRMLS_DC) {
- const void* storage = message_data(header);
- void* memory = slot_memory(layout, storage, field);
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
-
- if (upb_fielddef_containingoneof(field)) {
- if (*oneof_case != upb_fielddef_number(field)) {
- native_slot_get_default(upb_fielddef_type(field), cache TSRMLS_CC);
- return CACHED_PTR_TO_ZVAL_PTR(cache);
- }
- // Intentional fall through to be handled as a signuarl field.
- } else if (is_map_field(field)) {
- map_field_ensure_created(field, cache PHP_PROTO_TSRMLS_CC);
- return CACHED_PTR_TO_ZVAL_PTR(cache);
- } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
- repeated_field_ensure_created(field, cache PHP_PROTO_TSRMLS_CC);
- return CACHED_PTR_TO_ZVAL_PTR(cache);
- }
-
- CACHED_VALUE* stored_cache = find_zval_property(header, field);
-
- if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE &&
- is_wrapper_msg(upb_fielddef_msgsubdef(field))) {
- zval * cached_zval = CACHED_PTR_TO_ZVAL_PTR(stored_cache);
-#if PHP_MAJOR_VERSION >= 7
- zend_object* obj;
-#endif
- if (Z_TYPE_P(cached_zval) != IS_OBJECT &&
- Z_TYPE_P(cached_zval) != IS_NULL) {
- // Needs to expand value to wrapper.
- const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
- const upb_fielddef* value_field = upb_msgdef_itof(submsgdef, 1);
- MessageHeader* submsg;
- DescriptorInternal* subdesc = get_msgdef_desc(submsgdef);
- register_class(subdesc, false TSRMLS_CC);
- zend_class_entry* subklass = subdesc->klass;
-#if PHP_MAJOR_VERSION < 7
- zval* val = NULL;
- MAKE_STD_ZVAL(val);
- ZVAL_OBJ(val, subklass->create_object(subklass TSRMLS_CC));
- submsg = UNBOX(MessageHeader, val);
-#else
- obj = subklass->create_object(subklass TSRMLS_CC);
- submsg = (MessageHeader*)((char*)obj - XtOffsetOf(MessageHeader, std));
-#endif
- custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
-
- layout_set(subdesc->layout, submsg, value_field, cached_zval TSRMLS_CC);
-#if PHP_MAJOR_VERSION < 7
- ZVAL_ZVAL(cached_zval, val, 1, 1);
-#else
- ZVAL_OBJ(cached_zval, obj);
-#endif
- }
- if (stored_cache != cache) {
- ZVAL_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cache), cached_zval, 1, 0);
- }
- } else {
- upb_fieldtype_t type = upb_fielddef_type(field);
- native_slot_get(type, value_memory(type, memory, stored_cache),
- cache TSRMLS_CC);
- }
- return CACHED_PTR_TO_ZVAL_PTR(cache);
-}
-
-void layout_set(MessageLayout* layout, MessageHeader* header,
- const upb_fielddef* field, zval* val TSRMLS_DC) {
- void* storage = message_data(header);
- void* memory = slot_memory(layout, storage, field);
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
-
- if (upb_fielddef_containingoneof(field)) {
- *oneof_case = upb_fielddef_number(field);
- } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
- // Works for both repeated and map fields
- CACHED_VALUE* cached = find_zval_property(header, field);
- zval* property_ptr = CACHED_PTR_TO_ZVAL_PTR(cached);
-
- if (EXPECTED(property_ptr != val)) {
- zend_class_entry *subce = NULL;
- zval converted_value;
-
- if (upb_fielddef_ismap(field)) {
- const upb_msgdef* mapmsg = upb_fielddef_msgsubdef(field);
- const upb_fielddef* keyfield = upb_msgdef_ntof(mapmsg, "key", 3);
- const upb_fielddef* valuefield = upb_msgdef_ntof(mapmsg, "value", 5);
- if (upb_fielddef_descriptortype(valuefield) ==
- UPB_DESCRIPTOR_TYPE_MESSAGE) {
- const upb_msgdef* submsg = upb_fielddef_msgsubdef(valuefield);
- DescriptorInternal* subdesc = get_msgdef_desc(submsg);
- register_class(subdesc, false TSRMLS_CC);
- subce = subdesc->klass;
- }
- check_map_field(subce, upb_fielddef_descriptortype(keyfield),
- upb_fielddef_descriptortype(valuefield), val,
- &converted_value);
- } else {
- if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
- const upb_msgdef* submsg = upb_fielddef_msgsubdef(field);
- DescriptorInternal* subdesc = get_msgdef_desc(submsg);
- register_class(subdesc, false TSRMLS_CC);
- subce = subdesc->klass;
- }
-
- check_repeated_field(subce, upb_fielddef_descriptortype(field), val,
- &converted_value);
- }
-#if PHP_MAJOR_VERSION < 7
- REPLACE_ZVAL_VALUE((zval**)cached, &converted_value, 1);
-#else
- php_proto_zval_ptr_dtor(property_ptr);
- ZVAL_ZVAL(property_ptr, &converted_value, 1, 0);
-#endif
- zval_dtor(&converted_value);
- }
- return;
- }
-
- 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);
- DescriptorInternal* desc = get_msgdef_desc(msg);
- register_class(desc, false TSRMLS_CC);
- ce = desc->klass;
- }
- CACHED_VALUE* cache = find_zval_property(header, field);
- native_slot_set(
- type, ce, value_memory(upb_fielddef_type(field), memory, cache),
- val TSRMLS_CC);
-}
-
-static void 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, to_memory,
- CACHED_PTR_TO_ZVAL_PTR(from_memory) PHP_PROTO_TSRMLS_CC);
- break;
- case UPB_TYPE_MESSAGE: {
- const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
- DescriptorInternal* desc = get_msgdef_desc(msg);
- register_class(desc, false TSRMLS_CC);
- ce = desc->klass;
- if (native_slot_is_default(type, to_memory)) {
-#if PHP_MAJOR_VERSION < 7
- SEPARATE_ZVAL_IF_NOT_REF((zval**)to_memory);
-#endif
- CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(
- CACHED_PTR_TO_ZVAL_PTR(to_memory), ce);
- MessageHeader* submsg =
- UNBOX(MessageHeader, CACHED_PTR_TO_ZVAL_PTR(to_memory));
- custom_data_init(ce, submsg PHP_PROTO_TSRMLS_CC);
- }
-
- MessageHeader* sub_from =
- UNBOX(MessageHeader,
- CACHED_PTR_TO_ZVAL_PTR(from_memory));
- MessageHeader* sub_to =
- UNBOX(MessageHeader,
- CACHED_PTR_TO_ZVAL_PTR(to_memory));
-
- layout_merge(desc->layout, sub_from, sub_to PHP_PROTO_TSRMLS_CC);
- break;
- }
- }
- }
-}
-
-static void 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: {
- DescriptorInternal* desc = get_msgdef_desc(upb_fielddef_msgsubdef(field));
- register_class(desc, false TSRMLS_CC);
- 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) {
- int i, j;
- upb_msg_field_iter it;
-
- for (upb_msg_field_begin(&it, layout->msgdef), i = 0; !upb_msg_field_done(&it);
- upb_msg_field_next(&it), i++) {
- const upb_fielddef* field = upb_msg_iter_field(&it);
-
- void* to_memory = slot_memory(layout, message_data(to), field);
- void* from_memory = slot_memory(layout, message_data(from), field);
-
- if (upb_fielddef_containingoneof(field)) {
- uint32_t oneof_case_offset =
- layout->fields[upb_fielddef_index(field)].case_offset;
- // 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) !=
- upb_fielddef_number(field)) {
- continue;
- }
- uint32_t* from_oneof_case = slot_oneof_case(layout, message_data(from), field);
- uint32_t* to_oneof_case = slot_oneof_case(layout, message_data(to), field);
-
- // For non-singular fields, the related memory needs to point to the
- // actual zval in properties table first.
- switch (upb_fielddef_type(field)) {
- case UPB_TYPE_MESSAGE:
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES: {
- int property_cache_index =
- layout->fields[upb_fielddef_index(field)].cache_index;
- DEREF(to_memory, CACHED_VALUE*) =
- OBJ_PROP(&to->std, property_cache_index);
- break;
- }
- default:
- break;
- }
-
- *to_oneof_case = *from_oneof_case;
-
- // Otherwise, fall through to the appropriate singular-field handler
- // below.
- }
-
- if (is_map_field(field)) {
- int size, key_length, value_length;
- MapIter map_it;
-
- CACHED_VALUE* from_cache = find_zval_property(from, field);
- CACHED_VALUE* to_cache = find_zval_property(to, field);
-
- if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(from_cache)) == IS_NULL) {
- continue;
- }
- map_field_ensure_created(field, to_cache PHP_PROTO_TSRMLS_CC);
-
- zval* to_map_php = CACHED_PTR_TO_ZVAL_PTR(to_cache);
- zval* from_map_php = CACHED_PTR_TO_ZVAL_PTR(from_cache);
-
- Map* to_map = UNBOX(Map, to_map_php);
- Map* from_map = UNBOX(Map, from_map_php);
-
- 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));
-
- 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);
- }
-
- } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
- CACHED_VALUE* from_cache = find_zval_property(from, field);
- CACHED_VALUE* to_cache = find_zval_property(to, field);
-
- if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(from_cache)) == IS_NULL) {
- continue;
- }
- repeated_field_ensure_created(field, to_cache PHP_PROTO_TSRMLS_CC);
-
- zval* to_array_php = CACHED_PTR_TO_ZVAL_PTR(to_cache);
- zval* from_array_php = CACHED_PTR_TO_ZVAL_PTR(from_cache);
- RepeatedField* to_array = UNBOX(RepeatedField, to_array_php);
- RepeatedField* from_array = UNBOX(RepeatedField, from_array_php);
-
- int size = zend_hash_num_elements(PHP_PROTO_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)));
-
- if (to_array->type == UPB_TYPE_MESSAGE) {
- php_proto_zend_hash_index_find_zval(
- PHP_PROTO_HASH_OF(from_array->array), j, (void**)&from_memory);
-#if PHP_MAJOR_VERSION >= 7
- from_memory = &Z_OBJ_P((zval*)from_memory);
-#endif
- } else {
- php_proto_zend_hash_index_find_mem(
- 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);
- }
- }
- } else {
- switch (upb_fielddef_type(field)) {
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES:
- case UPB_TYPE_MESSAGE: {
- CACHED_VALUE* from_cache = find_zval_property(from, field);
- CACHED_VALUE* to_cache = find_zval_property(to, field);
- native_slot_merge(field, from_cache, to_cache PHP_PROTO_TSRMLS_CC);
- break;
- }
- default:
- native_slot_merge(field, from_memory, to_memory PHP_PROTO_TSRMLS_CC);
- break;
- }
- }
- }
-}
-
-const char* layout_get_oneof_case(MessageLayout* layout, const void* storage,
- const upb_oneofdef* oneof TSRMLS_DC) {
- upb_oneof_iter i;
- const upb_fielddef* first_field = NULL;
-
- // Oneof is guaranteed to have at least one field. Get the first field.
- for(upb_oneof_begin(&i, oneof); !upb_oneof_done(&i); upb_oneof_next(&i)) {
- first_field = upb_oneof_iter_field(&i);
- break;
- }
-
- uint32_t* oneof_case = slot_oneof_case(layout, storage, first_field);
- if (*oneof_case == 0) {
- return "";
- }
- const upb_fielddef* field = upb_oneofdef_itof(oneof, *oneof_case);
- return upb_fielddef_name(field);
-}
diff --git a/php/ext/google/protobuf/type_check.c b/php/ext/google/protobuf/type_check.c
deleted file mode 100644
index 84d06be7ef..0000000000
--- a/php/ext/google/protobuf/type_check.c
+++ /dev/null
@@ -1,680 +0,0 @@
-// 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.
-
-// The Zend Engine License, version 2.00
-// Copyright (c) 1999-2002 Zend Technologies Ltd. All rights reserved.
-// --------------------------------------------------------------------
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, is permitted provided that the following conditions
-// are met:
-//
-// 1. Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//
-// 2. 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.
-//
-// 3. The names "Zend" and "Zend Engine" must not be used to endorse
-// or promote products derived from this software without prior
-// permission from Zend Technologies Ltd. For written permission,
-// please contact license@zend.com.
-//
-// 4. Zend Technologies Ltd. may publish revised and/or new versions
-// of the license from time to time. Each version will be given a
-// distinguishing version number.
-// Once covered code has been published under a particular version
-// of the license, you may always continue to use it under the
-// terms of that version. You may also choose to use such covered
-// code under the terms of any subsequent version of the license
-// published by Zend Technologies Ltd. No one other than Zend
-// Technologies Ltd. has the right to modify the terms applicable
-// to covered code created under this License.
-//
-// 5. Redistributions of any form whatsoever must retain the following
-// acknowledgment:
-// "This product includes the Zend Engine, freely available at
-// http://www.zend.com"
-//
-// 6. All advertising materials mentioning features or use of this
-// software must display the following acknowledgment:
-// "The Zend Engine is freely available at http://www.zend.com"
-//
-// THIS SOFTWARE IS PROVIDED BY ZEND TECHNOLOGIES LTD. ``AS IS'' AND
-// ANY EXPRESSED 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 ZEND
-// TECHNOLOGIES LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-// SUCH DAMAGE.
-
-#include
-#include
-
-#include "protobuf.h"
-#include "utf8.h"
-
-static zend_class_entry* util_type;
-static const char int64_min_digits[] = "9223372036854775808";
-
-ZEND_BEGIN_ARG_INFO_EX(arg_check_optional, 0, 0, 1)
- ZEND_ARG_INFO(1, val)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arg_check_message, 0, 0, 2)
- ZEND_ARG_INFO(1, val)
- ZEND_ARG_INFO(0, klass)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arg_check_repeated, 0, 0, 2)
- ZEND_ARG_INFO(1, val)
- ZEND_ARG_INFO(0, type)
- ZEND_ARG_INFO(0, klass)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arg_check_map, 0, 0, 3)
- ZEND_ARG_INFO(1, val)
- ZEND_ARG_INFO(0, key_type)
- ZEND_ARG_INFO(0, value_type)
- ZEND_ARG_INFO(0, klass)
-ZEND_END_ARG_INFO()
-
-static zend_function_entry util_methods[] = {
- PHP_ME(Util, checkInt32, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Util, checkUint32, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Util, checkInt64, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Util, checkUint64, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Util, checkEnum, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Util, checkFloat, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Util, checkDouble, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Util, checkBool, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Util, checkString, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Util, checkBytes, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Util, checkMessage, arg_check_message, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Util, checkMapField, arg_check_map, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- PHP_ME(Util, checkRepeatedField, arg_check_repeated,
- ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
- ZEND_FE_END
-};
-
-void util_init(TSRMLS_D) {
- zend_class_entry class_type;
- INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBUtil",
- util_methods);
- util_type = zend_register_internal_class(&class_type TSRMLS_CC);
-}
-
-// -----------------------------------------------------------------------------
-// Type checking/conversion.
-// -----------------------------------------------------------------------------
-
-// This is modified from is_numeric_string in zend_operators.h. The behavior of
-// this function is the same as is_numeric_string, except that this takes
-// int64_t as input instead of long.
-static zend_uchar convert_numeric_string(
- const char *str, int length, int64_t *lval, double *dval) {
- const char *ptr;
- int base = 10, digits = 0, dp_or_e = 0;
- double local_dval = 0.0;
- zend_uchar type;
-
- if (length == 0) {
- return IS_NULL;
- }
-
- while (*str == ' ' || *str == '\t' || *str == '\n' ||
- *str == '\r' || *str == '\v' || *str == '\f') {
- str++;
- length--;
- }
- ptr = str;
-
- if (*ptr == '-' || *ptr == '+') {
- ptr++;
- }
-
- if (ZEND_IS_DIGIT(*ptr)) {
- // Handle hex numbers
- // str is used instead of ptr to disallow signs and keep old behavior.
- if (length > 2 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) {
- base = 16;
- ptr += 2;
- }
-
- // Skip any leading 0s.
- while (*ptr == '0') {
- ptr++;
- }
-
- // Count the number of digits. If a decimal point/exponent is found,
- // it's a double. Otherwise, if there's a dval or no need to check for
- // a full match, stop when there are too many digits for a int64 */
- for (type = IS_LONG;
- !(digits >= MAX_LENGTH_OF_INT64 && dval);
- digits++, ptr++) {
-check_digits:
- if (ZEND_IS_DIGIT(*ptr) || (base == 16 && ZEND_IS_XDIGIT(*ptr))) {
- continue;
- } else if (base == 10) {
- if (*ptr == '.' && dp_or_e < 1) {
- goto process_double;
- } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {
- const char *e = ptr + 1;
-
- if (*e == '-' || *e == '+') {
- ptr = e++;
- }
- if (ZEND_IS_DIGIT(*e)) {
- goto process_double;
- }
- }
- }
- break;
- }
-
- if (base == 10) {
- if (digits >= MAX_LENGTH_OF_INT64) {
- dp_or_e = -1;
- goto process_double;
- }
- } else if (!(digits < SIZEOF_INT64 * 2 ||
- (digits == SIZEOF_INT64 * 2 && ptr[-digits] <= '7'))) {
- if (dval) {
- local_dval = zend_hex_strtod(str, &ptr);
- }
- type = IS_DOUBLE;
- }
- } else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) {
-process_double:
- type = IS_DOUBLE;
-
- // If there's a dval, do the conversion; else continue checking
- // the digits if we need to check for a full match.
- if (dval) {
- local_dval = zend_strtod(str, &ptr);
- } else if (dp_or_e != -1) {
- dp_or_e = (*ptr++ == '.') ? 1 : 2;
- goto check_digits;
- }
- } else {
- return IS_NULL;
- }
- if (ptr != str + length) {
- zend_error(E_NOTICE, "A non well formed numeric value encountered");
- return 0;
- }
-
- if (type == IS_LONG) {
- if (digits == MAX_LENGTH_OF_INT64 - 1) {
- int cmp = strcmp(&ptr[-digits], int64_min_digits);
-
- if (!(cmp < 0 || (cmp == 0 && *str == '-'))) {
- if (dval) {
- *dval = zend_strtod(str, NULL);
- }
-
- return IS_DOUBLE;
- }
- }
- if (lval) {
- *lval = strtoll(str, NULL, base);
- }
- return IS_LONG;
- } else {
- if (dval) {
- *dval = local_dval;
- }
- return IS_DOUBLE;
- }
-}
-
-#define CONVERT_TO_INTEGER(type) \
- static bool convert_int64_to_##type(int64_t val, type##_t* type##_value) { \
- *type##_value = (type##_t)val; \
- return true; \
- } \
- \
- static bool convert_double_to_##type(double val, type##_t* type##_value) { \
- *type##_value = (type##_t)zend_dval_to_lval(val); \
- return true; \
- } \
- \
- static bool convert_string_to_##type(const char* val, int len, \
- type##_t* type##_value) { \
- int64_t lval; \
- double dval; \
- TSRMLS_FETCH(); \
- switch (convert_numeric_string(val, len, &lval, &dval)) { \
- case IS_DOUBLE: { \
- return convert_double_to_##type(dval, type##_value); \
- } \
- case IS_LONG: { \
- return convert_int64_to_##type(lval, type##_value); \
- } \
- default: \
- zend_throw_exception(NULL, \
- "Given string value cannot be converted to integer.", \
- 0 TSRMLS_CC); \
- return false; \
- } \
- } \
- \
- bool protobuf_convert_to_##type(zval* from, type##_t* to) { \
- TSRMLS_FETCH(); \
- switch (Z_TYPE_P(from)) { \
- case IS_LONG: { \
- return convert_int64_to_##type(Z_LVAL_P(from), to); \
- } \
- case IS_DOUBLE: { \
- return convert_double_to_##type(Z_DVAL_P(from), to); \
- } \
- case IS_STRING: { \
- return convert_string_to_##type(Z_STRVAL_P(from), Z_STRLEN_P(from), \
- to); \
- } \
- default: { \
- zend_throw_exception(NULL, \
- "Given value cannot be converted to integer.", \
- 0 TSRMLS_CC); \
- return false; \
- } \
- } \
- return false; \
- }
-
-CONVERT_TO_INTEGER(int32);
-CONVERT_TO_INTEGER(uint32);
-CONVERT_TO_INTEGER(int64);
-CONVERT_TO_INTEGER(uint64);
-
-#undef CONVERT_TO_INTEGER
-
-#define CONVERT_TO_FLOAT(type) \
- static bool convert_int64_to_##type(int64_t val, type* type##_value) { \
- *type##_value = (type)val; \
- return true; \
- } \
- \
- static bool convert_double_to_##type(double val, type* type##_value) { \
- *type##_value = (type)val; \
- return true; \
- } \
- \
- static bool convert_string_to_##type(const char* val, int len, \
- type* type##_value) { \
- int64_t lval; \
- double dval; \
- \
- TSRMLS_FETCH(); \
- switch (convert_numeric_string(val, len, &lval, &dval)) { \
- case IS_DOUBLE: { \
- *type##_value = (type)dval; \
- return true; \
- } \
- case IS_LONG: { \
- *type##_value = (type)lval; \
- return true; \
- } \
- default: \
- zend_throw_exception(NULL, \
- "Given string value cannot be converted to integer.", \
- 0 TSRMLS_CC); \
- return false; \
- } \
- } \
- \
- bool protobuf_convert_to_##type(zval* from, type* to) { \
- TSRMLS_FETCH(); \
- switch (Z_TYPE_P(from)) { \
- case IS_LONG: { \
- return convert_int64_to_##type(Z_LVAL_P(from), to); \
- } \
- case IS_DOUBLE: { \
- return convert_double_to_##type(Z_DVAL_P(from), to); \
- } \
- case IS_STRING: { \
- return convert_string_to_##type(Z_STRVAL_P(from), Z_STRLEN_P(from), \
- to); \
- } \
- default: { \
- zend_throw_exception(NULL, \
- "Given value cannot be converted to integer.", \
- 0 TSRMLS_CC); \
- return false; \
- } \
- } \
- return false; \
- }
-
-CONVERT_TO_FLOAT(float);
-CONVERT_TO_FLOAT(double);
-
-#undef CONVERT_TO_FLOAT
-
-bool protobuf_convert_to_bool(zval* from, int8_t* to) {
- TSRMLS_FETCH();
- 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;
- case IS_DOUBLE:
- *to = (int8_t)(Z_LVAL_P(from) != 0);
- break;
- case IS_STRING: {
- if (Z_STRLEN_P(from) == 0 ||
- (Z_STRLEN_P(from) == 1 && Z_STRVAL_P(from)[0] == '0')) {
- *to = 0;
- } else {
- *to = 1;
- }
- } break;
- default: {
- zend_throw_exception(
- NULL, "Given value cannot be converted to bool.",
- 0 TSRMLS_CC);
- return false;
- }
- }
- return true;
-}
-
-bool protobuf_convert_to_string(zval* from) {
-#if PHP_MAJOR_VERSION >= 7
- if (Z_ISREF_P(from)) {
- ZVAL_DEREF(from);
- }
-#endif
- TSRMLS_FETCH();
- switch (Z_TYPE_P(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: {
- zval tmp;
- php_proto_zend_make_printable_zval(from, &tmp);
- ZVAL_COPY_VALUE(from, &tmp);
- return true;
- }
- default:
- zend_throw_exception(
- NULL, "Given value cannot be converted to string.",
- 0 TSRMLS_CC);
- return false;
- }
-}
-
-// -----------------------------------------------------------------------------
-// PHP Functions.
-// -----------------------------------------------------------------------------
-
-// The implementation of type checking for primitive fields is empty. This is
-// because type checking is done when direct assigning message fields (e.g.,
-// foo->a = 1). Functions defined here are place holders in generated code for
-// pure PHP implementation (c extension and pure PHP share the same generated
-// code).
-#define PHP_TYPE_CHECK(type) \
- PHP_METHOD(Util, check##type) {}
-
-PHP_TYPE_CHECK(Int32)
-PHP_TYPE_CHECK(Uint32)
-PHP_TYPE_CHECK(Int64)
-PHP_TYPE_CHECK(Uint64)
-PHP_TYPE_CHECK(Enum)
-PHP_TYPE_CHECK(Float)
-PHP_TYPE_CHECK(Double)
-PHP_TYPE_CHECK(Bool)
-PHP_TYPE_CHECK(String)
-PHP_TYPE_CHECK(Bytes)
-
-#undef PHP_TYPE_CHECK
-
-PHP_METHOD(Util, checkMessage) {
- zval* val;
- zend_class_entry* klass = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!C", &val, &klass) ==
- FAILURE) {
- return;
- }
- if (val == NULL) {
- RETURN_NULL();
- }
- if (!instanceof_function(Z_OBJCE_P(val), klass TSRMLS_CC)) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
- "Given value is not an instance of %s.",
-#if PHP_MAJOR_VERSION < 7
- klass->name);
-#else
- ZSTR_VAL(klass->name));
-#endif
- return;
- }
- RETURN_ZVAL(val, 1, 0);
-}
-
-void check_repeated_field(const zend_class_entry* klass, PHP_PROTO_LONG type,
- zval* val, zval* return_value) {
-#if PHP_MAJOR_VERSION >= 7
- if (Z_ISREF_P(val)) {
- ZVAL_DEREF(val);
- }
-#endif
-
- TSRMLS_FETCH();
- if (Z_TYPE_P(val) == IS_ARRAY) {
- HashTable* table = HASH_OF(val);
- HashPosition pointer;
- 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);
-
- for (zend_hash_internal_pointer_reset_ex(table, &pointer);
- php_proto_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);
- }
-
- RETURN_ZVAL(CACHED_TO_ZVAL_PTR(repeated_field), 1, 1);
-
- } else if (Z_TYPE_P(val) == IS_OBJECT) {
- if (!instanceof_function(Z_OBJCE_P(val), repeated_field_type TSRMLS_CC)) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
- "Given value is not an instance of %s.",
-#if PHP_MAJOR_VERSION < 7
- repeated_field_type->name);
-#else
- ZSTR_VAL(repeated_field_type->name));
-#endif
- return;
- }
- RepeatedField* intern = UNBOX(RepeatedField, val);
- if (to_fieldtype(type) != intern->type) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
- "Incorrect repeated field type.");
- return;
- }
- if (klass != NULL && intern->msg_ce != klass) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
- "Expect a repeated field of %s, but %s is given.",
-#if PHP_MAJOR_VERSION < 7
- klass->name, intern->msg_ce->name);
-#else
- ZSTR_VAL(klass->name),
- ZSTR_VAL(intern->msg_ce->name));
-#endif
- return;
- }
- RETURN_ZVAL(val, 1, 0);
- } else {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
- "Incorrect repeated field type.");
- return;
- }
-}
-
-PHP_METHOD(Util, checkRepeatedField) {
- zval* val;
- PHP_PROTO_LONG type;
- const zend_class_entry* klass = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl|C", &val, &type,
- &klass) == FAILURE) {
- return;
- }
- RETURN_ZVAL(val, 1, 0);
-}
-
-void check_map_field(const zend_class_entry* klass, PHP_PROTO_LONG key_type,
- PHP_PROTO_LONG value_type, zval* val, zval* return_value) {
-#if PHP_MAJOR_VERSION >= 7
- if (Z_ISREF_P(val)) {
- ZVAL_DEREF(val);
- }
-#endif
-
- TSRMLS_FETCH();
- if (Z_TYPE_P(val) == IS_ARRAY) {
- HashTable* table = Z_ARRVAL_P(val);
- HashPosition pointer;
- zval key;
- 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);
-
- for (zend_hash_internal_pointer_reset_ex(table, &pointer);
- php_proto_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);
- zval_dtor(&key);
- }
-
- RETURN_ZVAL(CACHED_TO_ZVAL_PTR(map_field), 1, 1);
- } else if (Z_TYPE_P(val) == IS_OBJECT) {
- if (!instanceof_function(Z_OBJCE_P(val), map_field_type TSRMLS_CC)) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
- "Given value is not an instance of %s.",
-#if PHP_MAJOR_VERSION < 7
- map_field_type->name);
-#else
- ZSTR_VAL(map_field_type->name));
-#endif
- return;
- }
- Map* intern = UNBOX(Map, val);
- if (to_fieldtype(key_type) != intern->key_type) {
- zend_throw_exception(
- NULL, "Incorrect map field key type.",
- 0 TSRMLS_CC);
- return;
- }
- if (to_fieldtype(value_type) != intern->value_type) {
- zend_throw_exception(
- NULL, "Incorrect map field value type.",
- 0 TSRMLS_CC);
- return;
- }
- if (klass != NULL && intern->msg_ce != klass) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC,
- "Expect a map field of %s, but %s is given.",
-#if PHP_MAJOR_VERSION < 7
- klass->name, intern->msg_ce->name);
-#else
- ZSTR_VAL(klass->name),
- ZSTR_VAL(intern->msg_ce->name));
-#endif
- return;
- }
- RETURN_ZVAL(val, 1, 0);
- } else {
- zend_throw_exception(
- NULL, "Incorrect map field type.",
- 0 TSRMLS_CC);
- return;
- }
-}
-
-PHP_METHOD(Util, checkMapField) {
- zval* val;
- PHP_PROTO_LONG key_type, value_type;
- const zend_class_entry* klass = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zll|C", &val, &key_type,
- &value_type, &klass) == FAILURE) {
- return;
- }
- RETURN_ZVAL(val, 1, 0);
-}
diff --git a/php/ext/google/protobuf/upb.c b/php/ext/google/protobuf/upb.c
deleted file mode 100644
index cf27432f03..0000000000
--- a/php/ext/google/protobuf/upb.c
+++ /dev/null
@@ -1,13840 +0,0 @@
-/* Amalgamated source file */
-#include "upb.h"
-/*
-* This is where we define macros used across upb.
-*
-* All of these macros are undef'd in port_undef.inc to avoid leaking them to
-* users.
-*
-* The correct usage is:
-*
-* #include "upb/foobar.h"
-* #include "upb/baz.h"
-*
-* // MUST be last included header.
-* #include "upb/port_def.inc"
-*
-* // Code for this file.
-* // <...>
-*
-* // Can be omitted for .c files, required for .h.
-* #include "upb/port_undef.inc"
-*
-* This file is private and must not be included by users!
-*/
-#include
-#include
-
-#if UINTPTR_MAX == 0xffffffff
-#define UPB_SIZE(size32, size64) size32
-#else
-#define UPB_SIZE(size32, size64) size64
-#endif
-
-/* If we always read/write as a consistent type to each address, this shouldn't
- * violate aliasing.
- */
-#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs)))
-
-#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
- *UPB_PTR_AT(msg, case_offset, int) == case_val \
- ? *UPB_PTR_AT(msg, offset, fieldtype) \
- : default
-
-#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
- *UPB_PTR_AT(msg, case_offset, int) = case_val; \
- *UPB_PTR_AT(msg, offset, fieldtype) = value;
-
-#define UPB_MAPTYPE_STRING 0
-
-/* UPB_INLINE: inline if possible, emit standalone code if required. */
-#ifdef __cplusplus
-#define UPB_INLINE inline
-#elif defined (__GNUC__) || defined(__clang__)
-#define UPB_INLINE static __inline__
-#else
-#define UPB_INLINE static
-#endif
-
-#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align))
-#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align))
-#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16)
-#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member)
-
-/* Hints to the compiler about likely/unlikely branches. */
-#if defined (__GNUC__) || defined(__clang__)
-#define UPB_LIKELY(x) __builtin_expect((x),1)
-#define UPB_UNLIKELY(x) __builtin_expect((x),0)
-#else
-#define UPB_LIKELY(x) (x)
-#define UPB_UNLIKELY(x) (x)
-#endif
-
-/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler
- * doesn't provide these preprocessor symbols. */
-#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
-#define UPB_BIG_ENDIAN
-#endif
-
-/* Macros for function attributes on compilers that support them. */
-#ifdef __GNUC__
-#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
-#define UPB_NOINLINE __attribute__((noinline))
-#define UPB_NORETURN __attribute__((__noreturn__))
-#else /* !defined(__GNUC__) */
-#define UPB_FORCEINLINE
-#define UPB_NOINLINE
-#define UPB_NORETURN
-#endif
-
-#if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L
-/* C99/C++11 versions. */
-#include
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined(_MSC_VER)
-/* Microsoft C/C++ versions. */
-#include
-#include
-#if _MSC_VER < 1900
-int msvc_snprintf(char* s, size_t n, const char* format, ...);
-int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg);
-#define UPB_MSVC_VSNPRINTF
-#define _upb_snprintf msvc_snprintf
-#define _upb_vsnprintf msvc_vsnprintf
-#else
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#endif
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined __GNUC__
-/* A few hacky workarounds for functions not in C89.
- * For internal use only!
- * TODO(haberman): fix these by including our own implementations, or finding
- * another workaround.
- */
-#define _upb_snprintf __builtin_snprintf
-#define _upb_vsnprintf __builtin_vsnprintf
-#define _upb_va_copy(a, b) __va_copy(a, b)
-#else
-#error Need implementations of [v]snprintf and va_copy
-#endif
-
-#ifdef __cplusplus
-#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \
- (defined(_MSC_VER) && _MSC_VER >= 1900)
-/* C++11 is present */
-#else
-#error upb requires C++11 for C++ support
-#endif
-#endif
-
-#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
-#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
-
-#define UPB_UNUSED(var) (void)var
-
-/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
- */
-#ifdef NDEBUG
-#ifdef __GNUC__
-#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable()
-#else
-#define UPB_ASSUME(expr) do {} if (false && (expr))
-#endif
-#else
-#define UPB_ASSUME(expr) assert(expr)
-#endif
-
-/* UPB_ASSERT(): in release mode, we use the expression without letting it be
- * evaluated. This prevents "unused variable" warnings. */
-#ifdef NDEBUG
-#define UPB_ASSERT(expr) do {} while (false && (expr))
-#else
-#define UPB_ASSERT(expr) assert(expr)
-#endif
-
-/* UPB_ASSERT_DEBUGVAR(): assert that uses functions or variables that only
- * exist in debug mode. This turns into regular assert. */
-#define UPB_ASSERT_DEBUGVAR(expr) assert(expr)
-
-#if defined(__GNUC__) || defined(__clang__)
-#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
-#else
-#define UPB_UNREACHABLE() do { assert(0); } while(0)
-#endif
-
-/* UPB_INFINITY representing floating-point positive infinity. */
-#include
-#ifdef INFINITY
-#define UPB_INFINITY INFINITY
-#else
-#define UPB_INFINITY (1.0 / 0.0)
-#endif
-
-#include
-#include
-
-
-
-/* Maps descriptor type -> upb field type. */
-static const uint8_t desctype_to_fieldtype[] = {
- -1, /* invalid descriptor type */
- UPB_TYPE_DOUBLE, /* DOUBLE */
- UPB_TYPE_FLOAT, /* FLOAT */
- UPB_TYPE_INT64, /* INT64 */
- UPB_TYPE_UINT64, /* UINT64 */
- UPB_TYPE_INT32, /* INT32 */
- UPB_TYPE_UINT64, /* FIXED64 */
- UPB_TYPE_UINT32, /* FIXED32 */
- UPB_TYPE_BOOL, /* BOOL */
- UPB_TYPE_STRING, /* STRING */
- UPB_TYPE_MESSAGE, /* GROUP */
- UPB_TYPE_MESSAGE, /* MESSAGE */
- UPB_TYPE_BYTES, /* BYTES */
- UPB_TYPE_UINT32, /* UINT32 */
- UPB_TYPE_ENUM, /* ENUM */
- UPB_TYPE_INT32, /* SFIXED32 */
- UPB_TYPE_INT64, /* SFIXED64 */
- UPB_TYPE_INT32, /* SINT32 */
- UPB_TYPE_INT64, /* SINT64 */
-};
-
-/* Maps descriptor type -> upb map size. */
-static const uint8_t desctype_to_mapsize[] = {
- -1, /* invalid descriptor type */
- 8, /* DOUBLE */
- 4, /* FLOAT */
- 8, /* INT64 */
- 8, /* UINT64 */
- 4, /* INT32 */
- 8, /* FIXED64 */
- 4, /* FIXED32 */
- 1, /* BOOL */
- UPB_MAPTYPE_STRING, /* STRING */
- sizeof(void *), /* GROUP */
- sizeof(void *), /* MESSAGE */
- UPB_MAPTYPE_STRING, /* BYTES */
- 4, /* UINT32 */
- 4, /* ENUM */
- 4, /* SFIXED32 */
- 8, /* SFIXED64 */
- 4, /* SINT32 */
- 8, /* SINT64 */
-};
-
-static const unsigned fixed32_ok = (1 << UPB_DTYPE_FLOAT) |
- (1 << UPB_DTYPE_FIXED32) |
- (1 << UPB_DTYPE_SFIXED32);
-
-static const unsigned fixed64_ok = (1 << UPB_DTYPE_DOUBLE) |
- (1 << UPB_DTYPE_FIXED64) |
- (1 << UPB_DTYPE_SFIXED64);
-
-/* Op: an action to be performed for a wire-type/field-type combination. */
-#define OP_SCALAR_LG2(n) (n)
-#define OP_FIXPCK_LG2(n) (n + 4)
-#define OP_VARPCK_LG2(n) (n + 8)
-#define OP_STRING 4
-#define OP_SUBMSG 5
-
-static const int8_t varint_ops[19] = {
- -1, /* field not found */
- -1, /* DOUBLE */
- -1, /* FLOAT */
- OP_SCALAR_LG2(3), /* INT64 */
- OP_SCALAR_LG2(3), /* UINT64 */
- OP_SCALAR_LG2(2), /* INT32 */
- -1, /* FIXED64 */
- -1, /* FIXED32 */
- OP_SCALAR_LG2(0), /* BOOL */
- -1, /* STRING */
- -1, /* GROUP */
- -1, /* MESSAGE */
- -1, /* BYTES */
- OP_SCALAR_LG2(2), /* UINT32 */
- OP_SCALAR_LG2(2), /* ENUM */
- -1, /* SFIXED32 */
- -1, /* SFIXED64 */
- OP_SCALAR_LG2(2), /* SINT32 */
- OP_SCALAR_LG2(3), /* SINT64 */
-};
-
-static const int8_t delim_ops[37] = {
- /* For non-repeated field type. */
- -1, /* field not found */
- -1, /* DOUBLE */
- -1, /* FLOAT */
- -1, /* INT64 */
- -1, /* UINT64 */
- -1, /* INT32 */
- -1, /* FIXED64 */
- -1, /* FIXED32 */
- -1, /* BOOL */
- OP_STRING, /* STRING */
- -1, /* GROUP */
- OP_SUBMSG, /* MESSAGE */
- OP_STRING, /* BYTES */
- -1, /* UINT32 */
- -1, /* ENUM */
- -1, /* SFIXED32 */
- -1, /* SFIXED64 */
- -1, /* SINT32 */
- -1, /* SINT64 */
- /* For repeated field type. */
- OP_FIXPCK_LG2(3), /* REPEATED DOUBLE */
- OP_FIXPCK_LG2(2), /* REPEATED FLOAT */
- OP_VARPCK_LG2(3), /* REPEATED INT64 */
- OP_VARPCK_LG2(3), /* REPEATED UINT64 */
- OP_VARPCK_LG2(2), /* REPEATED INT32 */
- OP_FIXPCK_LG2(3), /* REPEATED FIXED64 */
- OP_FIXPCK_LG2(2), /* REPEATED FIXED32 */
- OP_VARPCK_LG2(0), /* REPEATED BOOL */
- OP_STRING, /* REPEATED STRING */
- OP_SUBMSG, /* REPEATED GROUP */
- OP_SUBMSG, /* REPEATED MESSAGE */
- OP_STRING, /* REPEATED BYTES */
- OP_VARPCK_LG2(2), /* REPEATED UINT32 */
- OP_VARPCK_LG2(2), /* REPEATED ENUM */
- OP_FIXPCK_LG2(2), /* REPEATED SFIXED32 */
- OP_FIXPCK_LG2(3), /* REPEATED SFIXED64 */
- OP_VARPCK_LG2(2), /* REPEATED SINT32 */
- OP_VARPCK_LG2(3), /* REPEATED SINT64 */
-};
-
-/* Data pertaining to the parse. */
-typedef struct {
- const char *limit; /* End of delimited region or end of buffer. */
- upb_arena *arena;
- int depth;
- uint32_t end_group; /* Set to field number of END_GROUP tag, if any. */
- jmp_buf err;
-} upb_decstate;
-
-typedef union {
- bool bool_val;
- int32_t int32_val;
- int64_t int64_val;
- uint32_t uint32_val;
- uint64_t uint64_val;
- upb_strview str_val;
-} wireval;
-
-static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
- const upb_msglayout *layout);
-
-UPB_NORETURN static void decode_err(upb_decstate *d) { longjmp(d->err, 1); }
-
-static bool decode_reserve(upb_decstate *d, upb_array *arr, int elem) {
- bool need_realloc = arr->size - arr->len < elem;
- if (need_realloc && !_upb_array_realloc(arr, arr->len + elem, d->arena)) {
- decode_err(d);
- }
- return need_realloc;
-}
-
-UPB_NOINLINE
-static const char *decode_longvarint64(upb_decstate *d, const char *ptr,
- const char *limit, uint64_t *val) {
- uint8_t byte;
- int bitpos = 0;
- uint64_t out = 0;
-
- do {
- if (bitpos >= 70 || ptr == limit) decode_err(d);
- byte = *ptr;
- out |= (uint64_t)(byte & 0x7F) << bitpos;
- ptr++;
- bitpos += 7;
- } while (byte & 0x80);
-
- *val = out;
- return ptr;
-}
-
-UPB_FORCEINLINE
-static const char *decode_varint64(upb_decstate *d, const char *ptr,
- const char *limit, uint64_t *val) {
- if (UPB_LIKELY(ptr < limit && (*ptr & 0x80) == 0)) {
- *val = (uint8_t)*ptr;
- return ptr + 1;
- } else {
- return decode_longvarint64(d, ptr, limit, val);
- }
-}
-
-static const char *decode_varint32(upb_decstate *d, const char *ptr,
- const char *limit, uint32_t *val) {
- uint64_t u64;
- ptr = decode_varint64(d, ptr, limit, &u64);
- if (u64 > UINT32_MAX) decode_err(d);
- *val = (uint32_t)u64;
- return ptr;
-}
-
-static void decode_munge(int type, wireval *val) {
- switch (type) {
- case UPB_DESCRIPTOR_TYPE_BOOL:
- val->bool_val = val->uint64_val != 0;
- break;
- case UPB_DESCRIPTOR_TYPE_SINT32: {
- uint32_t n = val->uint32_val;
- val->int32_val = (n >> 1) ^ -(int32_t)(n & 1);
- break;
- }
- case UPB_DESCRIPTOR_TYPE_SINT64: {
- uint64_t n = val->uint64_val;
- val->int64_val = (n >> 1) ^ -(int64_t)(n & 1);
- break;
- }
- }
-}
-
-static const upb_msglayout_field *upb_find_field(const upb_msglayout *l,
- uint32_t field_number) {
- static upb_msglayout_field none = {0};
-
- /* Lots of optimization opportunities here. */
- int i;
- if (l == NULL) return &none;
- for (i = 0; i < l->field_count; i++) {
- if (l->fields[i].number == field_number) {
- return &l->fields[i];
- }
- }
-
- return &none; /* Unknown field. */
-}
-
-static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout,
- const upb_msglayout_field *field) {
- const upb_msglayout *subl = layout->submsgs[field->submsg_index];
- return _upb_msg_new(subl, d->arena);
-}
-
-static void decode_tosubmsg(upb_decstate *d, upb_msg *submsg,
- const upb_msglayout *layout,
- const upb_msglayout_field *field, upb_strview val) {
- const upb_msglayout *subl = layout->submsgs[field->submsg_index];
- const char *saved_limit = d->limit;
- if (--d->depth < 0) decode_err(d);
- d->limit = val.data + val.size;
- decode_msg(d, val.data, submsg, subl);
- d->limit = saved_limit;
- if (d->end_group != 0) decode_err(d);
- d->depth++;
-}
-
-static const char *decode_group(upb_decstate *d, const char *ptr,
- upb_msg *submsg, const upb_msglayout *subl,
- uint32_t number) {
- if (--d->depth < 0) decode_err(d);
- ptr = decode_msg(d, ptr, submsg, subl);
- if (d->end_group != number) decode_err(d);
- d->end_group = 0;
- d->depth++;
- return ptr;
-}
-
-static const char *decode_togroup(upb_decstate *d, const char *ptr,
- upb_msg *submsg, const upb_msglayout *layout,
- const upb_msglayout_field *field) {
- const upb_msglayout *subl = layout->submsgs[field->submsg_index];
- return decode_group(d, ptr, submsg, subl, field->number);
-}
-
-static const char *decode_toarray(upb_decstate *d, const char *ptr,
- upb_msg *msg, const upb_msglayout *layout,
- const upb_msglayout_field *field, wireval val,
- int op) {
- upb_array **arrp = UPB_PTR_AT(msg, field->offset, void);
- upb_array *arr = *arrp;
- void *mem;
-
- if (!arr) {
- upb_fieldtype_t type = desctype_to_fieldtype[field->descriptortype];
- arr = _upb_array_new(d->arena, type);
- if (!arr) decode_err(d);
- *arrp = arr;
- }
-
- decode_reserve(d, arr, 1);
-
- switch (op) {
- case OP_SCALAR_LG2(0):
- case OP_SCALAR_LG2(2):
- case OP_SCALAR_LG2(3):
- /* Append scalar value. */
- mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << op, void);
- arr->len++;
- memcpy(mem, &val, 1 << op);
- return ptr;
- case OP_STRING:
- /* Append string. */
- mem =
- UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(upb_strview), void);
- arr->len++;
- memcpy(mem, &val, sizeof(upb_strview));
- return ptr;
- case OP_SUBMSG: {
- /* Append submessage / group. */
- upb_msg *submsg = decode_newsubmsg(d, layout, field);
- *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void *), upb_msg *) =
- submsg;
- arr->len++;
- if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) {
- ptr = decode_togroup(d, ptr, submsg, layout, field);
- } else {
- decode_tosubmsg(d, submsg, layout, field, val.str_val);
- }
- return ptr;
- }
- case OP_FIXPCK_LG2(2):
- case OP_FIXPCK_LG2(3): {
- /* Fixed packed. */
- int lg2 = op - OP_FIXPCK_LG2(0);
- int mask = (1 << lg2) - 1;
- int count = val.str_val.size >> lg2;
- if ((val.str_val.size & mask) != 0) {
- decode_err(d); /* Length isn't a round multiple of elem size. */
- }
- decode_reserve(d, arr, count);
- mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
- arr->len += count;
- memcpy(mem, val.str_val.data, val.str_val.size);
- return ptr;
- }
- case OP_VARPCK_LG2(0):
- case OP_VARPCK_LG2(2):
- case OP_VARPCK_LG2(3): {
- /* Varint packed. */
- int lg2 = op - OP_VARPCK_LG2(0);
- int scale = 1 << lg2;
- const char *ptr = val.str_val.data;
- const char *end = ptr + val.str_val.size;
- char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
- while (ptr < end) {
- wireval elem;
- ptr = decode_varint64(d, ptr, end, &elem.uint64_val);
- decode_munge(field->descriptortype, &elem);
- if (decode_reserve(d, arr, 1)) {
- out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
- }
- arr->len++;
- memcpy(out, &elem, scale);
- out += scale;
- }
- if (ptr != end) decode_err(d);
- return ptr;
- }
- default:
- UPB_UNREACHABLE();
- }
-}
-
-static void decode_tomap(upb_decstate *d, upb_msg *msg,
- const upb_msglayout *layout,
- const upb_msglayout_field *field, wireval val) {
- upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *);
- upb_map *map = *map_p;
- upb_map_entry ent;
- const upb_msglayout *entry = layout->submsgs[field->submsg_index];
-
- if (!map) {
- /* Lazily create map. */
- const upb_msglayout *entry = layout->submsgs[field->submsg_index];
- const upb_msglayout_field *key_field = &entry->fields[0];
- const upb_msglayout_field *val_field = &entry->fields[1];
- char key_size = desctype_to_mapsize[key_field->descriptortype];
- char val_size = desctype_to_mapsize[val_field->descriptortype];
- UPB_ASSERT(key_field->offset == 0);
- UPB_ASSERT(val_field->offset == sizeof(upb_strview));
- map = _upb_map_new(d->arena, key_size, val_size);
- *map_p = map;
- }
-
- /* Parse map entry. */
- memset(&ent, 0, sizeof(ent));
-
- if (entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
- entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_GROUP) {
- /* Create proactively to handle the case where it doesn't appear. */
- ent.v.val.val = (uint64_t)_upb_msg_new(entry->submsgs[0], d->arena);
- }
-
- decode_tosubmsg(d, &ent.k, layout, field, val.str_val);
-
- /* Insert into map. */
- _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, d->arena);
-}
-
-static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
- const upb_msglayout *layout,
- const upb_msglayout_field *field, wireval val,
- int op) {
- void *mem = UPB_PTR_AT(msg, field->offset, void);
- int type = field->descriptortype;
-
- /* Set presence if necessary. */
- if (field->presence < 0) {
- /* Oneof case */
- *UPB_PTR_AT(msg, -field->presence, int32_t) = field->number;
- } else if (field->presence > 0) {
- /* Hasbit */
- uint32_t hasbit = field->presence;
- *UPB_PTR_AT(msg, hasbit / 8, uint8_t) |= (1 << (hasbit % 8));
- }
-
- /* Store into message. */
- switch (op) {
- case OP_SUBMSG: {
- upb_msg **submsgp = mem;
- upb_msg *submsg = *submsgp;
- if (!submsg) {
- submsg = decode_newsubmsg(d, layout, field);
- *submsgp = submsg;
- }
- if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) {
- ptr = decode_togroup(d, ptr, submsg, layout, field);
- } else {
- decode_tosubmsg(d, submsg, layout, field, val.str_val);
- }
- break;
- }
- case OP_STRING:
- memcpy(mem, &val, sizeof(upb_strview));
- break;
- case OP_SCALAR_LG2(3):
- memcpy(mem, &val, 8);
- break;
- case OP_SCALAR_LG2(2):
- memcpy(mem, &val, 4);
- break;
- case OP_SCALAR_LG2(0):
- memcpy(mem, &val, 1);
- break;
- default:
- UPB_UNREACHABLE();
- }
-
- return ptr;
-}
-
-static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
- const upb_msglayout *layout) {
- while (ptr < d->limit) {
- uint32_t tag;
- const upb_msglayout_field *field;
- int field_number;
- int wire_type;
- const char *field_start = ptr;
- wireval val;
- int op;
-
- ptr = decode_varint32(d, ptr, d->limit, &tag);
- field_number = tag >> 3;
- wire_type = tag & 7;
-
- field = upb_find_field(layout, field_number);
-
- switch (wire_type) {
- case UPB_WIRE_TYPE_VARINT:
- ptr = decode_varint64(d, ptr, d->limit, &val.uint64_val);
- op = varint_ops[field->descriptortype];
- decode_munge(field->descriptortype, &val);
- break;
- case UPB_WIRE_TYPE_32BIT:
- if (d->limit - ptr < 4) decode_err(d);
- memcpy(&val, ptr, 4);
- ptr += 4;
- op = OP_SCALAR_LG2(2);
- if (((1 << field->descriptortype) & fixed32_ok) == 0) goto unknown;
- break;
- case UPB_WIRE_TYPE_64BIT:
- if (d->limit - ptr < 8) decode_err(d);
- memcpy(&val, ptr, 8);
- ptr += 8;
- op = OP_SCALAR_LG2(3);
- if (((1 << field->descriptortype) & fixed64_ok) == 0) goto unknown;
- break;
- case UPB_WIRE_TYPE_DELIMITED: {
- uint32_t size;
- int ndx = field->descriptortype;
- if (_upb_isrepeated(field)) ndx += 18;
- ptr = decode_varint32(d, ptr, d->limit, &size);
- if (size >= INT32_MAX || (size_t)(d->limit - ptr) < size) {
- decode_err(d); /* Length overflow. */
- }
- val.str_val.data = ptr;
- val.str_val.size = size;
- ptr += size;
- op = delim_ops[ndx];
- break;
- }
- case UPB_WIRE_TYPE_START_GROUP:
- val.int32_val = field_number;
- op = OP_SUBMSG;
- if (field->descriptortype != UPB_DTYPE_GROUP) goto unknown;
- break;
- case UPB_WIRE_TYPE_END_GROUP:
- d->end_group = field_number;
- return ptr;
- default:
- decode_err(d);
- }
-
- if (op >= 0) {
- /* Parse, using op for dispatch. */
- switch (field->label) {
- case UPB_LABEL_REPEATED:
- case _UPB_LABEL_PACKED:
- ptr = decode_toarray(d, ptr, msg, layout, field, val, op);
- break;
- case _UPB_LABEL_MAP:
- decode_tomap(d, msg, layout, field, val);
- break;
- default:
- ptr = decode_tomsg(d, ptr, msg, layout, field, val, op);
- break;
- }
- } else {
- unknown:
- /* Skip unknown field. */
- if (field_number == 0) decode_err(d);
- if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
- ptr = decode_group(d, ptr, NULL, NULL, field_number);
- }
- if (msg) {
- if (!_upb_msg_addunknown(msg, field_start, ptr - field_start,
- d->arena)) {
- decode_err(d);
- }
- }
- }
- }
-
- if (ptr != d->limit) decode_err(d);
- return ptr;
-}
-
-bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l,
- upb_arena *arena) {
- upb_decstate state;
- state.limit = buf + size;
- state.arena = arena;
- state.depth = 64;
- state.end_group = 0;
-
- if (setjmp(state.err)) return false;
-
- if (size == 0) return true;
- decode_msg(&state, buf, msg, l);
-
- return state.end_group == 0;
-}
-
-#undef OP_SCALAR_LG2
-#undef OP_FIXPCK_LG2
-#undef OP_VARPCK_LG2
-#undef OP_STRING
-#undef OP_SUBMSG
-/* We encode backwards, to avoid pre-computing lengths (one-pass encode). */
-
-
-#include
-
-
-
-#define UPB_PB_VARINT_MAX_LEN 10
-#define CHK(x) do { if (!(x)) { return false; } } while(0)
-
-static size_t upb_encode_varint(uint64_t val, char *buf) {
- size_t i;
- if (val < 128) { buf[0] = val; return 1; }
- i = 0;
- while (val) {
- uint8_t byte = val & 0x7fU;
- val >>= 7;
- if (val) byte |= 0x80U;
- buf[i++] = byte;
- }
- return i;
-}
-
-static uint32_t upb_zzencode_32(int32_t n) { return ((uint32_t)n << 1) ^ (n >> 31); }
-static uint64_t upb_zzencode_64(int64_t n) { return ((uint64_t)n << 1) ^ (n >> 63); }
-
-typedef struct {
- upb_alloc *alloc;
- char *buf, *ptr, *limit;
-} upb_encstate;
-
-static size_t upb_roundup_pow2(size_t bytes) {
- size_t ret = 128;
- while (ret < bytes) {
- ret *= 2;
- }
- return ret;
-}
-
-static bool upb_encode_growbuffer(upb_encstate *e, size_t bytes) {
- size_t old_size = e->limit - e->buf;
- size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr));
- char *new_buf = upb_realloc(e->alloc, e->buf, old_size, new_size);
- CHK(new_buf);
-
- /* We want previous data at the end, realloc() put it at the beginning. */
- if (old_size > 0) {
- memmove(new_buf + new_size - old_size, e->buf, old_size);
- }
-
- e->ptr = new_buf + new_size - (e->limit - e->ptr);
- e->limit = new_buf + new_size;
- e->buf = new_buf;
- return true;
-}
-
-/* Call to ensure that at least "bytes" bytes are available for writing at
- * e->ptr. Returns false if the bytes could not be allocated. */
-static bool upb_encode_reserve(upb_encstate *e, size_t bytes) {
- CHK(UPB_LIKELY((size_t)(e->ptr - e->buf) >= bytes) ||
- upb_encode_growbuffer(e, bytes));
-
- e->ptr -= bytes;
- return true;
-}
-
-/* Writes the given bytes to the buffer, handling reserve/advance. */
-static bool upb_put_bytes(upb_encstate *e, const void *data, size_t len) {
- if (len == 0) return true;
- CHK(upb_encode_reserve(e, len));
- memcpy(e->ptr, data, len);
- return true;
-}
-
-static bool upb_put_fixed64(upb_encstate *e, uint64_t val) {
- /* TODO(haberman): byte-swap for big endian. */
- return upb_put_bytes(e, &val, sizeof(uint64_t));
-}
-
-static bool upb_put_fixed32(upb_encstate *e, uint32_t val) {
- /* TODO(haberman): byte-swap for big endian. */
- return upb_put_bytes(e, &val, sizeof(uint32_t));
-}
-
-static bool upb_put_varint(upb_encstate *e, uint64_t val) {
- size_t len;
- char *start;
- CHK(upb_encode_reserve(e, UPB_PB_VARINT_MAX_LEN));
- len = upb_encode_varint(val, e->ptr);
- start = e->ptr + UPB_PB_VARINT_MAX_LEN - len;
- memmove(start, e->ptr, len);
- e->ptr = start;
- return true;
-}
-
-static bool upb_put_double(upb_encstate *e, double d) {
- uint64_t u64;
- UPB_ASSERT(sizeof(double) == sizeof(uint64_t));
- memcpy(&u64, &d, sizeof(uint64_t));
- return upb_put_fixed64(e, u64);
-}
-
-static bool upb_put_float(upb_encstate *e, float d) {
- uint32_t u32;
- UPB_ASSERT(sizeof(float) == sizeof(uint32_t));
- memcpy(&u32, &d, sizeof(uint32_t));
- return upb_put_fixed32(e, u32);
-}
-
-static uint32_t upb_readcase(const char *msg, const upb_msglayout_field *f) {
- uint32_t ret;
- memcpy(&ret, msg - f->presence, sizeof(ret));
- return ret;
-}
-
-static bool upb_readhasbit(const char *msg, const upb_msglayout_field *f) {
- uint32_t hasbit = f->presence;
- UPB_ASSERT(f->presence > 0);
- return (*UPB_PTR_AT(msg, hasbit / 8, uint8_t)) & (1 << (hasbit % 8));
-}
-
-static bool upb_put_tag(upb_encstate *e, int field_number, int wire_type) {
- return upb_put_varint(e, (field_number << 3) | wire_type);
-}
-
-static bool upb_put_fixedarray(upb_encstate *e, const upb_array *arr,
- size_t elem_size, uint32_t tag) {
- size_t bytes = arr->len * elem_size;
- const char* data = _upb_array_constptr(arr);
- const char* ptr = data + bytes - elem_size;
- if (tag) {
- while (true) {
- CHK(upb_put_bytes(e, ptr, elem_size) && upb_put_varint(e, tag));
- if (ptr == data) break;
- ptr -= elem_size;
- }
- return true;
- } else {
- return upb_put_bytes(e, data, bytes) && upb_put_varint(e, bytes);
- }
-}
-
-bool upb_encode_message(upb_encstate *e, const char *msg,
- const upb_msglayout *m, size_t *size);
-
-static bool upb_encode_scalarfield(upb_encstate *e, const void *_field_mem,
- const upb_msglayout *m,
- const upb_msglayout_field *f,
- bool skip_zero_value) {
- const char *field_mem = _field_mem;
-#define CASE(ctype, type, wire_type, encodeval) do { \
- ctype val = *(ctype*)field_mem; \
- if (skip_zero_value && val == 0) { \
- return true; \
- } \
- return upb_put_ ## type(e, encodeval) && \
- upb_put_tag(e, f->number, wire_type); \
-} while(0)
-
- switch (f->descriptortype) {
- case UPB_DESCRIPTOR_TYPE_DOUBLE:
- CASE(double, double, UPB_WIRE_TYPE_64BIT, val);
- case UPB_DESCRIPTOR_TYPE_FLOAT:
- CASE(float, float, UPB_WIRE_TYPE_32BIT, val);
- case UPB_DESCRIPTOR_TYPE_INT64:
- case UPB_DESCRIPTOR_TYPE_UINT64:
- CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val);
- case UPB_DESCRIPTOR_TYPE_UINT32:
- CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val);
- case UPB_DESCRIPTOR_TYPE_INT32:
- case UPB_DESCRIPTOR_TYPE_ENUM:
- CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, (int64_t)val);
- case UPB_DESCRIPTOR_TYPE_SFIXED64:
- case UPB_DESCRIPTOR_TYPE_FIXED64:
- CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val);
- case UPB_DESCRIPTOR_TYPE_FIXED32:
- case UPB_DESCRIPTOR_TYPE_SFIXED32:
- CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val);
- case UPB_DESCRIPTOR_TYPE_BOOL:
- CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val);
- case UPB_DESCRIPTOR_TYPE_SINT32:
- CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_32(val));
- case UPB_DESCRIPTOR_TYPE_SINT64:
- CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_64(val));
- case UPB_DESCRIPTOR_TYPE_STRING:
- case UPB_DESCRIPTOR_TYPE_BYTES: {
- upb_strview view = *(upb_strview*)field_mem;
- if (skip_zero_value && view.size == 0) {
- return true;
- }
- return upb_put_bytes(e, view.data, view.size) &&
- upb_put_varint(e, view.size) &&
- upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
- }
- case UPB_DESCRIPTOR_TYPE_GROUP: {
- size_t size;
- void *submsg = *(void **)field_mem;
- const upb_msglayout *subm = m->submsgs[f->submsg_index];
- if (submsg == NULL) {
- return true;
- }
- return upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) &&
- upb_encode_message(e, submsg, subm, &size) &&
- upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP);
- }
- case UPB_DESCRIPTOR_TYPE_MESSAGE: {
- size_t size;
- void *submsg = *(void **)field_mem;
- const upb_msglayout *subm = m->submsgs[f->submsg_index];
- if (submsg == NULL) {
- return true;
- }
- return upb_encode_message(e, submsg, subm, &size) &&
- upb_put_varint(e, size) &&
- upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
- }
- }
-#undef CASE
- UPB_UNREACHABLE();
-}
-
-static bool upb_encode_array(upb_encstate *e, const char *field_mem,
- const upb_msglayout *m,
- const upb_msglayout_field *f) {
- const upb_array *arr = *(const upb_array**)field_mem;
- bool packed = f->label == _UPB_LABEL_PACKED;
-
- if (arr == NULL || arr->len == 0) {
- return true;
- }
-
-#define VARINT_CASE(ctype, encode) \
- { \
- const ctype *start = _upb_array_constptr(arr); \
- const ctype *ptr = start + arr->len; \
- size_t pre_len = e->limit - e->ptr; \
- uint32_t tag = packed ? 0 : (f->number << 3) | UPB_WIRE_TYPE_VARINT; \
- do { \
- ptr--; \
- CHK(upb_put_varint(e, encode)); \
- if (tag) CHK(upb_put_varint(e, tag)); \
- } while (ptr != start); \
- if (!tag) CHK(upb_put_varint(e, e->limit - e->ptr - pre_len)); \
- } \
- break; \
- do { \
- ; \
- } while (0)
-
-#define TAG(wire_type) (packed ? 0 : (f->number << 3 | wire_type))
-
- switch (f->descriptortype) {
- case UPB_DESCRIPTOR_TYPE_DOUBLE:
- CHK(upb_put_fixedarray(e, arr, sizeof(double), TAG(UPB_WIRE_TYPE_64BIT)));
- break;
- case UPB_DESCRIPTOR_TYPE_FLOAT:
- CHK(upb_put_fixedarray(e, arr, sizeof(float), TAG(UPB_WIRE_TYPE_32BIT)));
- break;
- case UPB_DESCRIPTOR_TYPE_SFIXED64:
- case UPB_DESCRIPTOR_TYPE_FIXED64:
- CHK(upb_put_fixedarray(e, arr, sizeof(uint64_t), TAG(UPB_WIRE_TYPE_64BIT)));
- break;
- case UPB_DESCRIPTOR_TYPE_FIXED32:
- case UPB_DESCRIPTOR_TYPE_SFIXED32:
- CHK(upb_put_fixedarray(e, arr, sizeof(uint32_t), TAG(UPB_WIRE_TYPE_32BIT)));
- break;
- case UPB_DESCRIPTOR_TYPE_INT64:
- case UPB_DESCRIPTOR_TYPE_UINT64:
- VARINT_CASE(uint64_t, *ptr);
- case UPB_DESCRIPTOR_TYPE_UINT32:
- VARINT_CASE(uint32_t, *ptr);
- case UPB_DESCRIPTOR_TYPE_INT32:
- case UPB_DESCRIPTOR_TYPE_ENUM:
- VARINT_CASE(int32_t, (int64_t)*ptr);
- case UPB_DESCRIPTOR_TYPE_BOOL:
- VARINT_CASE(bool, *ptr);
- case UPB_DESCRIPTOR_TYPE_SINT32:
- VARINT_CASE(int32_t, upb_zzencode_32(*ptr));
- case UPB_DESCRIPTOR_TYPE_SINT64:
- VARINT_CASE(int64_t, upb_zzencode_64(*ptr));
- case UPB_DESCRIPTOR_TYPE_STRING:
- case UPB_DESCRIPTOR_TYPE_BYTES: {
- const upb_strview *start = _upb_array_constptr(arr);
- const upb_strview *ptr = start + arr->len;
- do {
- ptr--;
- CHK(upb_put_bytes(e, ptr->data, ptr->size) &&
- upb_put_varint(e, ptr->size) &&
- upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
- } while (ptr != start);
- return true;
- }
- case UPB_DESCRIPTOR_TYPE_GROUP: {
- const void *const*start = _upb_array_constptr(arr);
- const void *const*ptr = start + arr->len;
- const upb_msglayout *subm = m->submsgs[f->submsg_index];
- do {
- size_t size;
- ptr--;
- CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) &&
- upb_encode_message(e, *ptr, subm, &size) &&
- upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP));
- } while (ptr != start);
- return true;
- }
- case UPB_DESCRIPTOR_TYPE_MESSAGE: {
- const void *const*start = _upb_array_constptr(arr);
- const void *const*ptr = start + arr->len;
- const upb_msglayout *subm = m->submsgs[f->submsg_index];
- do {
- size_t size;
- ptr--;
- CHK(upb_encode_message(e, *ptr, subm, &size) &&
- upb_put_varint(e, size) &&
- upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
- } while (ptr != start);
- return true;
- }
- }
-#undef VARINT_CASE
-
- if (packed) {
- CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
- }
- return true;
-}
-
-static bool upb_encode_map(upb_encstate *e, const char *field_mem,
- const upb_msglayout *m,
- const upb_msglayout_field *f) {
- const upb_map *map = *(const upb_map**)field_mem;
- const upb_msglayout *entry = m->submsgs[f->submsg_index];
- const upb_msglayout_field *key_field = &entry->fields[0];
- const upb_msglayout_field *val_field = &entry->fields[1];
- upb_strtable_iter i;
- if (map == NULL) {
- return true;
- }
-
- upb_strtable_begin(&i, &map->table);
- for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
- size_t pre_len = e->limit - e->ptr;
- size_t size;
- upb_strview key = upb_strtable_iter_key(&i);
- const upb_value val = upb_strtable_iter_value(&i);
- const void *keyp =
- map->key_size == UPB_MAPTYPE_STRING ? (void *)&key : key.data;
- const void *valp =
- map->val_size == UPB_MAPTYPE_STRING ? upb_value_getptr(val) : &val;
-
- CHK(upb_encode_scalarfield(e, valp, entry, val_field, false));
- CHK(upb_encode_scalarfield(e, keyp, entry, key_field, false));
- size = (e->limit - e->ptr) - pre_len;
- CHK(upb_put_varint(e, size));
- CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
- }
-
- return true;
-}
-
-
-bool upb_encode_message(upb_encstate *e, const char *msg,
- const upb_msglayout *m, size_t *size) {
- int i;
- size_t pre_len = e->limit - e->ptr;
- const char *unknown;
- size_t unknown_size;
-
- unknown = upb_msg_getunknown(msg, &unknown_size);
-
- if (unknown) {
- upb_put_bytes(e, unknown, unknown_size);
- }
-
- for (i = m->field_count - 1; i >= 0; i--) {
- const upb_msglayout_field *f = &m->fields[i];
-
- if (_upb_isrepeated(f)) {
- CHK(upb_encode_array(e, msg + f->offset, m, f));
- } else if (f->label == _UPB_LABEL_MAP) {
- CHK(upb_encode_map(e, msg + f->offset, m, f));
- } else {
- bool skip_empty = false;
- if (f->presence == 0) {
- /* Proto3 presence. */
- skip_empty = true;
- } else if (f->presence > 0) {
- /* Proto2 presence: hasbit. */
- if (!upb_readhasbit(msg, f)) {
- continue;
- }
- } else {
- /* Field is in a oneof. */
- if (upb_readcase(msg, f) != f->number) {
- continue;
- }
- }
- CHK(upb_encode_scalarfield(e, msg + f->offset, m, f, skip_empty));
- }
- }
-
- *size = (e->limit - e->ptr) - pre_len;
- return true;
-}
-
-char *upb_encode(const void *msg, const upb_msglayout *m, upb_arena *arena,
- size_t *size) {
- upb_encstate e;
- e.alloc = upb_arena_alloc(arena);
- e.buf = NULL;
- e.limit = NULL;
- e.ptr = NULL;
-
- if (!upb_encode_message(&e, msg, m, size)) {
- *size = 0;
- return NULL;
- }
-
- *size = e.limit - e.ptr;
-
- if (*size == 0) {
- static char ch;
- return &ch;
- } else {
- UPB_ASSERT(e.ptr);
- return e.ptr;
- }
-}
-
-#undef CHK
-
-
-
-
-/** upb_msg *******************************************************************/
-
-static const char _upb_fieldtype_to_sizelg2[12] = {
- 0,
- 0, /* UPB_TYPE_BOOL */
- 2, /* UPB_TYPE_FLOAT */
- 2, /* UPB_TYPE_INT32 */
- 2, /* UPB_TYPE_UINT32 */
- 2, /* UPB_TYPE_ENUM */
- UPB_SIZE(2, 3), /* UPB_TYPE_MESSAGE */
- 3, /* UPB_TYPE_DOUBLE */
- 3, /* UPB_TYPE_INT64 */
- 3, /* UPB_TYPE_UINT64 */
- UPB_SIZE(3, 4), /* UPB_TYPE_STRING */
- UPB_SIZE(3, 4), /* UPB_TYPE_BYTES */
-};
-
-static uintptr_t tag_arrptr(void* ptr, int elem_size_lg2) {
- UPB_ASSERT(elem_size_lg2 <= 4);
- return (uintptr_t)ptr | elem_size_lg2;
-}
-
-static int upb_msg_internalsize(const upb_msglayout *l) {
- return sizeof(upb_msg_internal) - l->extendable * sizeof(void *);
-}
-
-static size_t upb_msg_sizeof(const upb_msglayout *l) {
- return l->size + upb_msg_internalsize(l);
-}
-
-static upb_msg_internal *upb_msg_getinternal(upb_msg *msg) {
- return UPB_PTR_AT(msg, -sizeof(upb_msg_internal), upb_msg_internal);
-}
-
-static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) {
- return UPB_PTR_AT(msg, -sizeof(upb_msg_internal), upb_msg_internal);
-}
-
-static upb_msg_internal_withext *upb_msg_getinternalwithext(
- upb_msg *msg, const upb_msglayout *l) {
- UPB_ASSERT(l->extendable);
- return UPB_PTR_AT(msg, -sizeof(upb_msg_internal_withext),
- upb_msg_internal_withext);
-}
-
-upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a) {
- void *mem = upb_arena_malloc(a, upb_msg_sizeof(l));
- upb_msg_internal *in;
- upb_msg *msg;
-
- if (!mem) {
- return NULL;
- }
-
- msg = UPB_PTR_AT(mem, upb_msg_internalsize(l), upb_msg);
-
- /* Initialize normal members. */
- memset(msg, 0, l->size);
-
- /* Initialize internal members. */
- in = upb_msg_getinternal(msg);
- in->unknown = NULL;
- in->unknown_len = 0;
- in->unknown_size = 0;
-
- if (l->extendable) {
- upb_msg_getinternalwithext(msg, l)->extdict = NULL;
- }
-
- return msg;
-}
-
-bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
- upb_arena *arena) {
- upb_msg_internal *in = upb_msg_getinternal(msg);
- if (len > in->unknown_size - in->unknown_len) {
- upb_alloc *alloc = upb_arena_alloc(arena);
- size_t need = in->unknown_size + len;
- size_t newsize = UPB_MAX(in->unknown_size * 2, need);
- void *mem = upb_realloc(alloc, in->unknown, in->unknown_size, newsize);
- if (!mem) return false;
- in->unknown = mem;
- in->unknown_size = newsize;
- }
- memcpy(in->unknown + in->unknown_len, data, len);
- in->unknown_len += len;
- return true;
-}
-
-const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) {
- const upb_msg_internal *in = upb_msg_getinternal_const(msg);
- *len = in->unknown_len;
- return in->unknown;
-}
-
-/** upb_array *****************************************************************/
-
-upb_array *_upb_array_new(upb_arena *a, upb_fieldtype_t type) {
- upb_array *arr = upb_arena_malloc(a, sizeof(upb_array));
-
- if (!arr) {
- return NULL;
- }
-
- arr->data = tag_arrptr(NULL, _upb_fieldtype_to_sizelg2[type]);
- arr->len = 0;
- arr->size = 0;
-
- return arr;
-}
-
-bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena) {
- size_t new_size = UPB_MAX(arr->size, 4);
- int elem_size_lg2 = arr->data & 7;
- size_t old_bytes = arr->size << elem_size_lg2;
- size_t new_bytes;
- void* ptr = _upb_array_ptr(arr);
-
- /* Log2 ceiling of size. */
- while (new_size < min_size) new_size *= 2;
-
- new_bytes = new_size << elem_size_lg2;
- ptr = upb_arena_realloc(arena, ptr, old_bytes, new_bytes);
-
- if (!ptr) {
- return false;
- }
-
- arr->data = tag_arrptr(ptr, elem_size_lg2);
- arr->size = new_size;
- return true;
-}
-
-static upb_array *getorcreate_array(upb_array **arr_ptr, upb_fieldtype_t type,
- upb_arena *arena) {
- upb_array *arr = *arr_ptr;
- if (!arr) {
- arr = _upb_array_new(arena, type);
- if (!arr) return NULL;
- *arr_ptr = arr;
- }
- return arr;
-}
-
-static bool resize_array(upb_array *arr, size_t size, upb_arena *arena) {
- if (size > arr->size && !_upb_array_realloc(arr, size, arena)) {
- return false;
- }
-
- arr->len = size;
- return true;
-}
-
-void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
- upb_fieldtype_t type, upb_arena *arena) {
- upb_array *arr = getorcreate_array(arr_ptr, type, arena);
- return arr && resize_array(arr, size, arena) ? _upb_array_ptr(arr) : NULL;
-}
-
-bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
- upb_fieldtype_t type, upb_arena *arena) {
- upb_array *arr = getorcreate_array(arr_ptr, type, arena);
- size_t elem = arr->len;
- int lg2 = _upb_fieldtype_to_sizelg2[type];
- char *data;
-
- if (!arr || !resize_array(arr, elem + 1, arena)) return false;
-
- data = _upb_array_ptr(arr);
- memcpy(data + (elem << lg2), value, 1 << lg2);
- return true;
-}
-
-/** upb_map *******************************************************************/
-
-upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) {
- upb_map *map = upb_arena_malloc(a, sizeof(upb_map));
-
- if (!map) {
- return NULL;
- }
-
- upb_strtable_init2(&map->table, UPB_CTYPE_INT32, upb_arena_alloc(a));
- map->key_size = key_size;
- map->val_size = value_size;
-
- return map;
-}
-/*
-** upb_table Implementation
-**
-** Implementation is heavily inspired by Lua's ltable.c.
-*/
-
-
-#include
-
-
-#define UPB_MAXARRSIZE 16 /* 64k. */
-
-/* From Chromium. */
-#define ARRAY_SIZE(x) \
- ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
-
-static const double MAX_LOAD = 0.85;
-
-/* The minimum utilization of the array part of a mixed hash/array table. This
- * is a speed/memory-usage tradeoff (though it's not straightforward because of
- * cache effects). The lower this is, the more memory we'll use. */
-static const double MIN_DENSITY = 0.1;
-
-bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
-
-int log2ceil(uint64_t v) {
- int ret = 0;
- bool pow2 = is_pow2(v);
- while (v >>= 1) ret++;
- ret = pow2 ? ret : ret + 1; /* Ceiling. */
- return UPB_MIN(UPB_MAXARRSIZE, ret);
-}
-
-char *upb_strdup(const char *s, upb_alloc *a) {
- return upb_strdup2(s, strlen(s), a);
-}
-
-char *upb_strdup2(const char *s, size_t len, upb_alloc *a) {
- size_t n;
- char *p;
-
- /* Prevent overflow errors. */
- if (len == SIZE_MAX) return NULL;
- /* Always null-terminate, even if binary data; but don't rely on the input to
- * have a null-terminating byte since it may be a raw binary buffer. */
- n = len + 1;
- p = upb_malloc(a, n);
- if (p) {
- memcpy(p, s, len);
- p[len] = 0;
- }
- return p;
-}
-
-/* A type to represent the lookup key of either a strtable or an inttable. */
-typedef union {
- uintptr_t num;
- struct {
- const char *str;
- size_t len;
- } str;
-} lookupkey_t;
-
-static lookupkey_t strkey2(const char *str, size_t len) {
- lookupkey_t k;
- k.str.str = str;
- k.str.len = len;
- return k;
-}
-
-static lookupkey_t intkey(uintptr_t key) {
- lookupkey_t k;
- k.num = key;
- return k;
-}
-
-typedef uint32_t hashfunc_t(upb_tabkey key);
-typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2);
-
-/* Base table (shared code) ***************************************************/
-
-/* For when we need to cast away const. */
-static upb_tabent *mutable_entries(upb_table *t) {
- return (upb_tabent*)t->entries;
-}
-
-static bool isfull(upb_table *t) {
- if (upb_table_size(t) == 0) {
- return true;
- } else {
- return ((double)(t->count + 1) / upb_table_size(t)) > MAX_LOAD;
- }
-}
-
-static bool init(upb_table *t, uint8_t size_lg2, upb_alloc *a) {
- size_t bytes;
-
- t->count = 0;
- t->size_lg2 = size_lg2;
- t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
- bytes = upb_table_size(t) * sizeof(upb_tabent);
- if (bytes > 0) {
- t->entries = upb_malloc(a, bytes);
- if (!t->entries) return false;
- memset(mutable_entries(t), 0, bytes);
- } else {
- t->entries = NULL;
- }
- return true;
-}
-
-static void uninit(upb_table *t, upb_alloc *a) {
- upb_free(a, mutable_entries(t));
-}
-
-static upb_tabent *emptyent(upb_table *t) {
- upb_tabent *e = mutable_entries(t) + upb_table_size(t);
- while (1) { if (upb_tabent_isempty(--e)) return e; UPB_ASSERT(e > t->entries); }
-}
-
-static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) {
- return (upb_tabent*)upb_getentry(t, hash);
-}
-
-static const upb_tabent *findentry(const upb_table *t, lookupkey_t key,
- uint32_t hash, eqlfunc_t *eql) {
- const upb_tabent *e;
-
- if (t->size_lg2 == 0) return NULL;
- e = upb_getentry(t, hash);
- if (upb_tabent_isempty(e)) return NULL;
- while (1) {
- if (eql(e->key, key)) return e;
- if ((e = e->next) == NULL) return NULL;
- }
-}
-
-static upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key,
- uint32_t hash, eqlfunc_t *eql) {
- return (upb_tabent*)findentry(t, key, hash, eql);
-}
-
-static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v,
- uint32_t hash, eqlfunc_t *eql) {
- const upb_tabent *e = findentry(t, key, hash, eql);
- if (e) {
- if (v) {
- _upb_value_setval(v, e->val.val);
- }
- return true;
- } else {
- return false;
- }
-}
-
-/* The given key must not already exist in the table. */
-static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
- upb_value val, uint32_t hash,
- hashfunc_t *hashfunc, eqlfunc_t *eql) {
- upb_tabent *mainpos_e;
- upb_tabent *our_e;
-
- UPB_ASSERT(findentry(t, key, hash, eql) == NULL);
-
- t->count++;
- mainpos_e = getentry_mutable(t, hash);
- our_e = mainpos_e;
-
- if (upb_tabent_isempty(mainpos_e)) {
- /* Our main position is empty; use it. */
- our_e->next = NULL;
- } else {
- /* Collision. */
- upb_tabent *new_e = emptyent(t);
- /* Head of collider's chain. */
- upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key));
- if (chain == mainpos_e) {
- /* Existing ent is in its main posisiton (it has the same hash as us, and
- * is the head of our chain). Insert to new ent and append to this chain. */
- new_e->next = mainpos_e->next;
- mainpos_e->next = new_e;
- our_e = new_e;
- } else {
- /* Existing ent is not in its main position (it is a node in some other
- * chain). This implies that no existing ent in the table has our hash.
- * Evict it (updating its chain) and use its ent for head of our chain. */
- *new_e = *mainpos_e; /* copies next. */
- while (chain->next != mainpos_e) {
- chain = (upb_tabent*)chain->next;
- UPB_ASSERT(chain);
- }
- chain->next = new_e;
- our_e = mainpos_e;
- our_e->next = NULL;
- }
- }
- our_e->key = tabkey;
- our_e->val.val = val.val;
- UPB_ASSERT(findentry(t, key, hash, eql) == our_e);
-}
-
-static bool rm(upb_table *t, lookupkey_t key, upb_value *val,
- upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) {
- upb_tabent *chain = getentry_mutable(t, hash);
- if (upb_tabent_isempty(chain)) return false;
- if (eql(chain->key, key)) {
- /* Element to remove is at the head of its chain. */
- t->count--;
- if (val) _upb_value_setval(val, chain->val.val);
- if (removed) *removed = chain->key;
- if (chain->next) {
- upb_tabent *move = (upb_tabent*)chain->next;
- *chain = *move;
- move->key = 0; /* Make the slot empty. */
- } else {
- chain->key = 0; /* Make the slot empty. */
- }
- return true;
- } else {
- /* Element to remove is either in a non-head position or not in the
- * table. */
- while (chain->next && !eql(chain->next->key, key)) {
- chain = (upb_tabent*)chain->next;
- }
- if (chain->next) {
- /* Found element to remove. */
- upb_tabent *rm = (upb_tabent*)chain->next;
- t->count--;
- if (val) _upb_value_setval(val, chain->next->val.val);
- if (removed) *removed = rm->key;
- rm->key = 0; /* Make the slot empty. */
- chain->next = rm->next;
- return true;
- } else {
- /* Element to remove is not in the table. */
- return false;
- }
- }
-}
-
-static size_t next(const upb_table *t, size_t i) {
- do {
- if (++i >= upb_table_size(t))
- return SIZE_MAX;
- } while(upb_tabent_isempty(&t->entries[i]));
-
- return i;
-}
-
-static size_t begin(const upb_table *t) {
- return next(t, -1);
-}
-
-
-/* upb_strtable ***************************************************************/
-
-/* A simple "subclass" of upb_table that only adds a hash function for strings. */
-
-static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) {
- uint32_t len = (uint32_t) k2.str.len;
- char *str = upb_malloc(a, k2.str.len + sizeof(uint32_t) + 1);
- if (str == NULL) return 0;
- memcpy(str, &len, sizeof(uint32_t));
- memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len);
- str[sizeof(uint32_t) + k2.str.len] = '\0';
- return (uintptr_t)str;
-}
-
-static uint32_t strhash(upb_tabkey key) {
- uint32_t len;
- char *str = upb_tabstr(key, &len);
- return upb_murmur_hash2(str, len, 0);
-}
-
-static bool streql(upb_tabkey k1, lookupkey_t k2) {
- uint32_t len;
- char *str = upb_tabstr(k1, &len);
- return len == k2.str.len && memcmp(str, k2.str.str, len) == 0;
-}
-
-bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) {
- return init(&t->t, 2, a);
-}
-
-void upb_strtable_clear(upb_strtable *t) {
- size_t bytes = upb_table_size(&t->t) * sizeof(upb_tabent);
- t->t.count = 0;
- memset((char*)t->t.entries, 0, bytes);
-}
-
-void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) {
- size_t i;
- for (i = 0; i < upb_table_size(&t->t); i++)
- upb_free(a, (void*)t->t.entries[i].key);
- uninit(&t->t, a);
-}
-
-bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) {
- upb_strtable new_table;
- upb_strtable_iter i;
-
- if (!init(&new_table.t, size_lg2, a))
- return false;
- upb_strtable_begin(&i, t);
- for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) {
- upb_strview key = upb_strtable_iter_key(&i);
- upb_strtable_insert3(
- &new_table, key.data, key.size,
- upb_strtable_iter_value(&i), a);
- }
- upb_strtable_uninit2(t, a);
- *t = new_table;
- return true;
-}
-
-bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len,
- upb_value v, upb_alloc *a) {
- lookupkey_t key;
- upb_tabkey tabkey;
- uint32_t hash;
-
- if (isfull(&t->t)) {
- /* Need to resize. New table of double the size, add old elements to it. */
- if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) {
- return false;
- }
- }
-
- key = strkey2(k, len);
- tabkey = strcopy(key, a);
- if (tabkey == 0) return false;
-
- hash = upb_murmur_hash2(key.str.str, key.str.len, 0);
- insert(&t->t, key, tabkey, v, hash, &strhash, &streql);
- return true;
-}
-
-bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
- upb_value *v) {
- uint32_t hash = upb_murmur_hash2(key, len, 0);
- return lookup(&t->t, strkey2(key, len), v, hash, &streql);
-}
-
-bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
- upb_value *val, upb_alloc *alloc) {
- uint32_t hash = upb_murmur_hash2(key, len, 0);
- upb_tabkey tabkey;
- if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) {
- if (alloc) {
- /* Arena-based allocs don't need to free and won't pass this. */
- upb_free(alloc, (void*)tabkey);
- }
- return true;
- } else {
- return false;
- }
-}
-
-/* Iteration */
-
-void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) {
- i->t = t;
- i->index = begin(&t->t);
-}
-
-void upb_strtable_next(upb_strtable_iter *i) {
- i->index = next(&i->t->t, i->index);
-}
-
-bool upb_strtable_done(const upb_strtable_iter *i) {
- if (!i->t) return true;
- return i->index >= upb_table_size(&i->t->t) ||
- upb_tabent_isempty(str_tabent(i));
-}
-
-upb_strview upb_strtable_iter_key(const upb_strtable_iter *i) {
- upb_strview key;
- uint32_t len;
- UPB_ASSERT(!upb_strtable_done(i));
- key.data = upb_tabstr(str_tabent(i)->key, &len);
- key.size = len;
- return key;
-}
-
-upb_value upb_strtable_iter_value(const upb_strtable_iter *i) {
- UPB_ASSERT(!upb_strtable_done(i));
- return _upb_value_val(str_tabent(i)->val.val);
-}
-
-void upb_strtable_iter_setdone(upb_strtable_iter *i) {
- i->t = NULL;
- i->index = SIZE_MAX;
-}
-
-bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
- const upb_strtable_iter *i2) {
- if (upb_strtable_done(i1) && upb_strtable_done(i2))
- return true;
- return i1->t == i2->t && i1->index == i2->index;
-}
-
-
-/* upb_inttable ***************************************************************/
-
-/* For inttables we use a hybrid structure where small keys are kept in an
- * array and large keys are put in the hash table. */
-
-static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); }
-
-static bool inteql(upb_tabkey k1, lookupkey_t k2) {
- return k1 == k2.num;
-}
-
-static upb_tabval *mutable_array(upb_inttable *t) {
- return (upb_tabval*)t->array;
-}
-
-static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) {
- if (key < t->array_size) {
- return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL;
- } else {
- upb_tabent *e =
- findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql);
- return e ? &e->val : NULL;
- }
-}
-
-static const upb_tabval *inttable_val_const(const upb_inttable *t,
- uintptr_t key) {
- return inttable_val((upb_inttable*)t, key);
-}
-
-size_t upb_inttable_count(const upb_inttable *t) {
- return t->t.count + t->array_count;
-}
-
-static void check(upb_inttable *t) {
- UPB_UNUSED(t);
-#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
- {
- /* This check is very expensive (makes inserts/deletes O(N)). */
- size_t count = 0;
- upb_inttable_iter i;
- upb_inttable_begin(&i, t);
- for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) {
- UPB_ASSERT(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL));
- }
- UPB_ASSERT(count == upb_inttable_count(t));
- }
-#endif
-}
-
-bool upb_inttable_sizedinit(upb_inttable *t, size_t asize, int hsize_lg2,
- upb_alloc *a) {
- size_t array_bytes;
-
- if (!init(&t->t, hsize_lg2, a)) return false;
- /* Always make the array part at least 1 long, so that we know key 0
- * won't be in the hash part, which simplifies things. */
- t->array_size = UPB_MAX(1, asize);
- t->array_count = 0;
- array_bytes = t->array_size * sizeof(upb_value);
- t->array = upb_malloc(a, array_bytes);
- if (!t->array) {
- uninit(&t->t, a);
- return false;
- }
- memset(mutable_array(t), 0xff, array_bytes);
- check(t);
- return true;
-}
-
-bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) {
- return upb_inttable_sizedinit(t, 0, 4, a);
-}
-
-void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) {
- uninit(&t->t, a);
- upb_free(a, mutable_array(t));
-}
-
-bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
- upb_alloc *a) {
- upb_tabval tabval;
- tabval.val = val.val;
- UPB_ASSERT(upb_arrhas(tabval)); /* This will reject (uint64_t)-1. Fix this. */
-
- if (key < t->array_size) {
- UPB_ASSERT(!upb_arrhas(t->array[key]));
- t->array_count++;
- mutable_array(t)[key].val = val.val;
- } else {
- if (isfull(&t->t)) {
- /* Need to resize the hash part, but we re-use the array part. */
- size_t i;
- upb_table new_table;
-
- if (!init(&new_table, t->t.size_lg2 + 1, a)) {
- return false;
- }
-
- for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
- const upb_tabent *e = &t->t.entries[i];
- uint32_t hash;
- upb_value v;
-
- _upb_value_setval(&v, e->val.val);
- hash = upb_inthash(e->key);
- insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql);
- }
-
- UPB_ASSERT(t->t.count == new_table.count);
-
- uninit(&t->t, a);
- t->t = new_table;
- }
- insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql);
- }
- check(t);
- return true;
-}
-
-bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) {
- const upb_tabval *table_v = inttable_val_const(t, key);
- if (!table_v) return false;
- if (v) _upb_value_setval(v, table_v->val);
- return true;
-}
-
-bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) {
- upb_tabval *table_v = inttable_val(t, key);
- if (!table_v) return false;
- table_v->val = val.val;
- return true;
-}
-
-bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
- bool success;
- if (key < t->array_size) {
- if (upb_arrhas(t->array[key])) {
- upb_tabval empty = UPB_TABVALUE_EMPTY_INIT;
- t->array_count--;
- if (val) {
- _upb_value_setval(val, t->array[key].val);
- }
- mutable_array(t)[key] = empty;
- success = true;
- } else {
- success = false;
- }
- } else {
- success = rm(&t->t, intkey(key), val, NULL, upb_inthash(key), &inteql);
- }
- check(t);
- return success;
-}
-
-bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a) {
- return upb_inttable_insert2(t, upb_inttable_count(t), val, a);
-}
-
-upb_value upb_inttable_pop(upb_inttable *t) {
- upb_value val;
- bool ok = upb_inttable_remove(t, upb_inttable_count(t) - 1, &val);
- UPB_ASSERT(ok);
- return val;
-}
-
-bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
- upb_alloc *a) {
- return upb_inttable_insert2(t, (uintptr_t)key, val, a);
-}
-
-bool upb_inttable_lookupptr(const upb_inttable *t, const void *key,
- upb_value *v) {
- return upb_inttable_lookup(t, (uintptr_t)key, v);
-}
-
-bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) {
- return upb_inttable_remove(t, (uintptr_t)key, val);
-}
-
-void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) {
- /* A power-of-two histogram of the table keys. */
- size_t counts[UPB_MAXARRSIZE + 1] = {0};
-
- /* The max key in each bucket. */
- uintptr_t max[UPB_MAXARRSIZE + 1] = {0};
-
- upb_inttable_iter i;
- size_t arr_count;
- int size_lg2;
- upb_inttable new_t;
-
- upb_inttable_begin(&i, t);
- for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- uintptr_t key = upb_inttable_iter_key(&i);
- int bucket = log2ceil(key);
- max[bucket] = UPB_MAX(max[bucket], key);
- counts[bucket]++;
- }
-
- /* Find the largest power of two that satisfies the MIN_DENSITY
- * definition (while actually having some keys). */
- arr_count = upb_inttable_count(t);
-
- for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) {
- if (counts[size_lg2] == 0) {
- /* We can halve again without losing any entries. */
- continue;
- } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) {
- break;
- }
-
- arr_count -= counts[size_lg2];
- }
-
- UPB_ASSERT(arr_count <= upb_inttable_count(t));
-
- {
- /* Insert all elements into new, perfectly-sized table. */
- size_t arr_size = max[size_lg2] + 1; /* +1 so arr[max] will fit. */
- size_t hash_count = upb_inttable_count(t) - arr_count;
- size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
- int hashsize_lg2 = log2ceil(hash_size);
-
- upb_inttable_sizedinit(&new_t, arr_size, hashsize_lg2, a);
- upb_inttable_begin(&i, t);
- for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- uintptr_t k = upb_inttable_iter_key(&i);
- upb_inttable_insert2(&new_t, k, upb_inttable_iter_value(&i), a);
- }
- UPB_ASSERT(new_t.array_size == arr_size);
- UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2);
- }
- upb_inttable_uninit2(t, a);
- *t = new_t;
-}
-
-/* Iteration. */
-
-static const upb_tabent *int_tabent(const upb_inttable_iter *i) {
- UPB_ASSERT(!i->array_part);
- return &i->t->t.entries[i->index];
-}
-
-static upb_tabval int_arrent(const upb_inttable_iter *i) {
- UPB_ASSERT(i->array_part);
- return i->t->array[i->index];
-}
-
-void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) {
- i->t = t;
- i->index = -1;
- i->array_part = true;
- upb_inttable_next(i);
-}
-
-void upb_inttable_next(upb_inttable_iter *iter) {
- const upb_inttable *t = iter->t;
- if (iter->array_part) {
- while (++iter->index < t->array_size) {
- if (upb_arrhas(int_arrent(iter))) {
- return;
- }
- }
- iter->array_part = false;
- iter->index = begin(&t->t);
- } else {
- iter->index = next(&t->t, iter->index);
- }
-}
-
-bool upb_inttable_done(const upb_inttable_iter *i) {
- if (!i->t) return true;
- if (i->array_part) {
- return i->index >= i->t->array_size ||
- !upb_arrhas(int_arrent(i));
- } else {
- return i->index >= upb_table_size(&i->t->t) ||
- upb_tabent_isempty(int_tabent(i));
- }
-}
-
-uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) {
- UPB_ASSERT(!upb_inttable_done(i));
- return i->array_part ? i->index : int_tabent(i)->key;
-}
-
-upb_value upb_inttable_iter_value(const upb_inttable_iter *i) {
- UPB_ASSERT(!upb_inttable_done(i));
- return _upb_value_val(
- i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val);
-}
-
-void upb_inttable_iter_setdone(upb_inttable_iter *i) {
- i->t = NULL;
- i->index = SIZE_MAX;
- i->array_part = false;
-}
-
-bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
- const upb_inttable_iter *i2) {
- if (upb_inttable_done(i1) && upb_inttable_done(i2))
- return true;
- return i1->t == i2->t && i1->index == i2->index &&
- i1->array_part == i2->array_part;
-}
-
-#if defined(UPB_UNALIGNED_READS_OK) || defined(__s390x__)
-/* -----------------------------------------------------------------------------
- * MurmurHash2, by Austin Appleby (released as public domain).
- * Reformatted and C99-ified by Joshua Haberman.
- * Note - This code makes a few assumptions about how your machine behaves -
- * 1. We can read a 4-byte value from any address without crashing
- * 2. sizeof(int) == 4 (in upb this limitation is removed by using uint32_t
- * And it has a few limitations -
- * 1. It will not work incrementally.
- * 2. It will not produce the same results on little-endian and big-endian
- * machines. */
-uint32_t upb_murmur_hash2(const void *key, size_t len, uint32_t seed) {
- /* 'm' and 'r' are mixing constants generated offline.
- * They're not really 'magic', they just happen to work well. */
- const uint32_t m = 0x5bd1e995;
- const int32_t r = 24;
-
- /* Initialize the hash to a 'random' value */
- uint32_t h = seed ^ len;
-
- /* Mix 4 bytes at a time into the hash */
- const uint8_t * data = (const uint8_t *)key;
- while(len >= 4) {
- uint32_t k;
- memcpy(&k, data, sizeof(k));
-
- k *= m;
- k ^= k >> r;
- k *= m;
-
- h *= m;
- h ^= k;
-
- data += 4;
- len -= 4;
- }
-
- /* Handle the last few bytes of the input array */
- switch(len) {
- case 3: h ^= data[2] << 16;
- case 2: h ^= data[1] << 8;
- case 1: h ^= data[0]; h *= m;
- };
-
- /* Do a few final mixes of the hash to ensure the last few
- * bytes are well-incorporated. */
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
-
- return h;
-}
-
-#else /* !UPB_UNALIGNED_READS_OK */
-
-/* -----------------------------------------------------------------------------
- * MurmurHashAligned2, by Austin Appleby
- * Same algorithm as MurmurHash2, but only does aligned reads - should be safer
- * on certain platforms.
- * Performance will be lower than MurmurHash2 */
-
-#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
-
-uint32_t upb_murmur_hash2(const void * key, size_t len, uint32_t seed) {
- const uint32_t m = 0x5bd1e995;
- const int32_t r = 24;
- const uint8_t * data = (const uint8_t *)key;
- uint32_t h = (uint32_t)(seed ^ len);
- uint8_t align = (uintptr_t)data & 3;
-
- if(align && (len >= 4)) {
- /* Pre-load the temp registers */
- uint32_t t = 0, d = 0;
- int32_t sl;
- int32_t sr;
-
- switch(align) {
- case 1: t |= data[2] << 16;
- case 2: t |= data[1] << 8;
- case 3: t |= data[0];
- }
-
- t <<= (8 * align);
-
- data += 4-align;
- len -= 4-align;
-
- sl = 8 * (4-align);
- sr = 8 * align;
-
- /* Mix */
-
- while(len >= 4) {
- uint32_t k;
-
- d = *(uint32_t *)data;
- t = (t >> sr) | (d << sl);
-
- k = t;
-
- MIX(h,k,m);
-
- t = d;
-
- data += 4;
- len -= 4;
- }
-
- /* Handle leftover data in temp registers */
-
- d = 0;
-
- if(len >= align) {
- uint32_t k;
-
- switch(align) {
- case 3: d |= data[2] << 16;
- case 2: d |= data[1] << 8;
- case 1: d |= data[0];
- }
-
- k = (t >> sr) | (d << sl);
- MIX(h,k,m);
-
- data += align;
- len -= align;
-
- /* ----------
- * Handle tail bytes */
-
- switch(len) {
- case 3: h ^= data[2] << 16;
- case 2: h ^= data[1] << 8;
- case 1: h ^= data[0]; h *= m;
- };
- } else {
- switch(len) {
- case 3: d |= data[2] << 16;
- case 2: d |= data[1] << 8;
- case 1: d |= data[0];
- case 0: h ^= (t >> sr) | (d << sl); h *= m;
- }
- }
-
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
-
- return h;
- } else {
- while(len >= 4) {
- uint32_t k = *(uint32_t *)data;
-
- MIX(h,k,m);
-
- data += 4;
- len -= 4;
- }
-
- /* ----------
- * Handle tail bytes */
-
- switch(len) {
- case 3: h ^= data[2] << 16;
- case 2: h ^= data[1] << 8;
- case 1: h ^= data[0]; h *= m;
- };
-
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
-
- return h;
- }
-}
-#undef MIX
-
-#endif /* UPB_UNALIGNED_READS_OK */
-
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-/* upb_status *****************************************************************/
-
-void upb_status_clear(upb_status *status) {
- if (!status) return;
- status->ok = true;
- status->msg[0] = '\0';
-}
-
-bool upb_ok(const upb_status *status) { return status->ok; }
-
-const char *upb_status_errmsg(const upb_status *status) { return status->msg; }
-
-void upb_status_seterrmsg(upb_status *status, const char *msg) {
- if (!status) return;
- status->ok = false;
- strncpy(status->msg, msg, UPB_STATUS_MAX_MESSAGE - 1);
- status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
-}
-
-void upb_status_seterrf(upb_status *status, const char *fmt, ...) {
- va_list args;
- va_start(args, fmt);
- upb_status_vseterrf(status, fmt, args);
- va_end(args);
-}
-
-void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) {
- if (!status) return;
- status->ok = false;
- _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args);
- status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
-}
-
-/* upb_alloc ******************************************************************/
-
-static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize,
- size_t size) {
- UPB_UNUSED(alloc);
- UPB_UNUSED(oldsize);
- if (size == 0) {
- free(ptr);
- return NULL;
- } else {
- return realloc(ptr, size);
- }
-}
-
-upb_alloc upb_alloc_global = {&upb_global_allocfunc};
-
-/* upb_arena ******************************************************************/
-
-/* Be conservative and choose 16 in case anyone is using SSE. */
-
-typedef struct mem_block {
- struct mem_block *next;
- uint32_t size;
- uint32_t cleanups;
- /* Data follows. */
-} mem_block;
-
-typedef struct cleanup_ent {
- upb_cleanup_func *cleanup;
- void *ud;
-} cleanup_ent;
-
-struct upb_arena {
- _upb_arena_head head;
- uint32_t *cleanups;
-
- /* Allocator to allocate arena blocks. We are responsible for freeing these
- * when we are destroyed. */
- upb_alloc *block_alloc;
- uint32_t last_size;
-
- /* When multiple arenas are fused together, each arena points to a parent
- * arena (root points to itself). The root tracks how many live arenas
- * reference it. */
- uint32_t refcount; /* Only used when a->parent == a */
- struct upb_arena *parent;
-
- /* Linked list of blocks to free/cleanup. */
- mem_block *freelist, *freelist_tail;
-};
-
-static const size_t memblock_reserve = UPB_ALIGN_UP(sizeof(mem_block), 16);
-
-static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size) {
- mem_block *block = ptr;
-
- block->next = a->freelist;
- block->size = size;
- block->cleanups = 0;
- a->freelist = block;
- a->last_size = size;
- if (!a->freelist_tail) a->freelist_tail = block;
-
- a->head.ptr = UPB_PTR_AT(block, memblock_reserve, char);
- a->head.end = UPB_PTR_AT(block, size, char);
- a->cleanups = &block->cleanups;
-
- /* TODO(haberman): ASAN poison. */
-}
-
-static bool upb_arena_allocblock(upb_arena *a, size_t size) {
- size_t block_size = UPB_MAX(size, a->last_size * 2) + memblock_reserve;
- mem_block *block = upb_malloc(a->block_alloc, block_size);
-
- if (!block) return false;
- upb_arena_addblock(a, block, block_size);
- return true;
-}
-
-static bool arena_has(upb_arena *a, size_t size) {
- _upb_arena_head *h = (_upb_arena_head*)a;
- return (size_t)(h->end - h->ptr) >= size;
-}
-
-void *_upb_arena_slowmalloc(upb_arena *a, size_t size) {
- if (!upb_arena_allocblock(a, size)) return NULL; /* Out of memory. */
- UPB_ASSERT(arena_has(a, size));
- return upb_arena_malloc(a, size);
-}
-
-static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize,
- size_t size) {
- upb_arena *a = (upb_arena*)alloc; /* upb_alloc is initial member. */
- return upb_arena_realloc(a, ptr, oldsize, size);
-}
-
-static upb_arena *arena_findroot(upb_arena *a) {
- /* Path splitting keeps time complexity down, see:
- * https://en.wikipedia.org/wiki/Disjoint-set_data_structure */
- while (a->parent != a) {
- upb_arena *next = a->parent;
- a->parent = next->parent;
- a = next;
- }
- return a;
-}
-
-/* Public Arena API ***********************************************************/
-
-upb_arena *arena_initslow(void *mem, size_t n, upb_alloc *alloc) {
- const size_t first_block_overhead = sizeof(upb_arena) + memblock_reserve;
- upb_arena *a;
-
- /* We need to malloc the initial block. */
- n = first_block_overhead + 256;
- if (!alloc || !(mem = upb_malloc(alloc, n))) {
- return NULL;
- }
-
- a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena);
- n -= sizeof(*a);
-
- a->head.alloc.func = &upb_arena_doalloc;
- a->block_alloc = alloc;
- a->parent = a;
- a->refcount = 1;
- a->freelist = NULL;
- a->freelist_tail = NULL;
-
- upb_arena_addblock(a, mem, n);
-
- return a;
-}
-
-upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) {
- upb_arena *a;
-
- /* Round block size down to alignof(*a) since we will allocate the arena
- * itself at the end. */
- n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_arena));
-
- if (UPB_UNLIKELY(n < sizeof(upb_arena))) {
- return arena_initslow(mem, n, alloc);
- }
-
- a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena);
- n -= sizeof(*a);
-
- a->head.alloc.func = &upb_arena_doalloc;
- a->block_alloc = alloc;
- a->parent = a;
- a->refcount = 1;
- a->last_size = 128;
- a->head.ptr = mem;
- a->head.end = UPB_PTR_AT(mem, n, char);
- a->freelist = NULL;
- a->cleanups = NULL;
-
- return a;
-}
-
-static void arena_dofree(upb_arena *a) {
- mem_block *block = a->freelist;
- UPB_ASSERT(a->parent == a);
- UPB_ASSERT(a->refcount == 0);
-
- while (block) {
- /* Load first since we are deleting block. */
- mem_block *next = block->next;
-
- if (block->cleanups > 0) {
- cleanup_ent *end = UPB_PTR_AT(block, block->size, void);
- cleanup_ent *ptr = end - block->cleanups;
-
- for (; ptr < end; ptr++) {
- ptr->cleanup(ptr->ud);
- }
- }
-
- upb_free(a->block_alloc, block);
- block = next;
- }
-}
-
-void upb_arena_free(upb_arena *a) {
- a = arena_findroot(a);
- if (--a->refcount == 0) arena_dofree(a);
-}
-
-bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) {
- cleanup_ent *ent;
-
- if (!a->cleanups || !arena_has(a, sizeof(cleanup_ent))) {
- if (!upb_arena_allocblock(a, 128)) return false; /* Out of memory. */
- UPB_ASSERT(arena_has(a, sizeof(cleanup_ent)));
- }
-
- a->head.end -= sizeof(cleanup_ent);
- ent = (cleanup_ent*)a->head.end;
- (*a->cleanups)++;
-
- ent->cleanup = func;
- ent->ud = ud;
-
- return true;
-}
-
-void upb_arena_fuse(upb_arena *a1, upb_arena *a2) {
- upb_arena *r1 = arena_findroot(a1);
- upb_arena *r2 = arena_findroot(a2);
-
- if (r1 == r2) return; /* Already fused. */
-
- /* We want to join the smaller tree to the larger tree.
- * So swap first if they are backwards. */
- if (r1->refcount < r2->refcount) {
- upb_arena *tmp = r1;
- r1 = r2;
- r2 = tmp;
- }
-
- /* r1 takes over r2's freelist and refcount. */
- r1->refcount += r2->refcount;
- if (r2->freelist_tail) {
- UPB_ASSERT(r2->freelist_tail->next == NULL);
- r2->freelist_tail->next = r1->freelist;
- r1->freelist = r2->freelist;
- }
- r2->parent = r1;
-}
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- * google/protobuf/descriptor.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#include
-
-
-static const upb_msglayout *const google_protobuf_FileDescriptorSet_submsgs[1] = {
- &google_protobuf_FileDescriptorProto_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FileDescriptorSet__fields[1] = {
- {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_FileDescriptorSet_msginit = {
- &google_protobuf_FileDescriptorSet_submsgs[0],
- &google_protobuf_FileDescriptorSet__fields[0],
- UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] = {
- &google_protobuf_DescriptorProto_msginit,
- &google_protobuf_EnumDescriptorProto_msginit,
- &google_protobuf_FieldDescriptorProto_msginit,
- &google_protobuf_FileOptions_msginit,
- &google_protobuf_ServiceDescriptorProto_msginit,
- &google_protobuf_SourceCodeInfo_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12] = {
- {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
- {2, UPB_SIZE(12, 24), 2, 0, 9, 1},
- {3, UPB_SIZE(36, 72), 0, 0, 9, 3},
- {4, UPB_SIZE(40, 80), 0, 0, 11, 3},
- {5, UPB_SIZE(44, 88), 0, 1, 11, 3},
- {6, UPB_SIZE(48, 96), 0, 4, 11, 3},
- {7, UPB_SIZE(52, 104), 0, 2, 11, 3},
- {8, UPB_SIZE(28, 56), 4, 3, 11, 1},
- {9, UPB_SIZE(32, 64), 5, 5, 11, 1},
- {10, UPB_SIZE(56, 112), 0, 0, 5, 3},
- {11, UPB_SIZE(60, 120), 0, 0, 5, 3},
- {12, UPB_SIZE(20, 40), 3, 0, 9, 1},
-};
-
-const upb_msglayout google_protobuf_FileDescriptorProto_msginit = {
- &google_protobuf_FileDescriptorProto_submsgs[0],
- &google_protobuf_FileDescriptorProto__fields[0],
- UPB_SIZE(64, 128), 12, false,
-};
-
-static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[8] = {
- &google_protobuf_DescriptorProto_msginit,
- &google_protobuf_DescriptorProto_ExtensionRange_msginit,
- &google_protobuf_DescriptorProto_ReservedRange_msginit,
- &google_protobuf_EnumDescriptorProto_msginit,
- &google_protobuf_FieldDescriptorProto_msginit,
- &google_protobuf_MessageOptions_msginit,
- &google_protobuf_OneofDescriptorProto_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = {
- {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
- {2, UPB_SIZE(16, 32), 0, 4, 11, 3},
- {3, UPB_SIZE(20, 40), 0, 0, 11, 3},
- {4, UPB_SIZE(24, 48), 0, 3, 11, 3},
- {5, UPB_SIZE(28, 56), 0, 1, 11, 3},
- {6, UPB_SIZE(32, 64), 0, 4, 11, 3},
- {7, UPB_SIZE(12, 24), 2, 5, 11, 1},
- {8, UPB_SIZE(36, 72), 0, 6, 11, 3},
- {9, UPB_SIZE(40, 80), 0, 2, 11, 3},
- {10, UPB_SIZE(44, 88), 0, 0, 9, 3},
-};
-
-const upb_msglayout google_protobuf_DescriptorProto_msginit = {
- &google_protobuf_DescriptorProto_submsgs[0],
- &google_protobuf_DescriptorProto__fields[0],
- UPB_SIZE(48, 96), 10, false,
-};
-
-static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = {
- &google_protobuf_ExtensionRangeOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_DescriptorProto_ExtensionRange__fields[3] = {
- {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
- {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
- {3, UPB_SIZE(12, 16), 3, 0, 11, 1},
-};
-
-const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit = {
- &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0],
- &google_protobuf_DescriptorProto_ExtensionRange__fields[0],
- UPB_SIZE(16, 24), 3, false,
-};
-
-static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__fields[2] = {
- {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
- {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
-};
-
-const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit = {
- NULL,
- &google_protobuf_DescriptorProto_ReservedRange__fields[0],
- UPB_SIZE(12, 12), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[1] = {
- &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_ExtensionRangeOptions__fields[1] = {
- {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit = {
- &google_protobuf_ExtensionRangeOptions_submsgs[0],
- &google_protobuf_ExtensionRangeOptions__fields[0],
- UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1] = {
- &google_protobuf_FieldOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = {
- {1, UPB_SIZE(36, 40), 6, 0, 9, 1},
- {2, UPB_SIZE(44, 56), 7, 0, 9, 1},
- {3, UPB_SIZE(24, 24), 3, 0, 5, 1},
- {4, UPB_SIZE(8, 8), 1, 0, 14, 1},
- {5, UPB_SIZE(16, 16), 2, 0, 14, 1},
- {6, UPB_SIZE(52, 72), 8, 0, 9, 1},
- {7, UPB_SIZE(60, 88), 9, 0, 9, 1},
- {8, UPB_SIZE(76, 120), 11, 0, 11, 1},
- {9, UPB_SIZE(28, 28), 4, 0, 5, 1},
- {10, UPB_SIZE(68, 104), 10, 0, 9, 1},
- {17, UPB_SIZE(32, 32), 5, 0, 8, 1},
-};
-
-const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = {
- &google_protobuf_FieldDescriptorProto_submsgs[0],
- &google_protobuf_FieldDescriptorProto__fields[0],
- UPB_SIZE(80, 128), 11, false,
-};
-
-static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = {
- &google_protobuf_OneofOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2] = {
- {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
- {2, UPB_SIZE(12, 24), 2, 0, 11, 1},
-};
-
-const upb_msglayout google_protobuf_OneofDescriptorProto_msginit = {
- &google_protobuf_OneofDescriptorProto_submsgs[0],
- &google_protobuf_OneofDescriptorProto__fields[0],
- UPB_SIZE(16, 32), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] = {
- &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit,
- &google_protobuf_EnumOptions_msginit,
- &google_protobuf_EnumValueDescriptorProto_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5] = {
- {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
- {2, UPB_SIZE(16, 32), 0, 2, 11, 3},
- {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
- {4, UPB_SIZE(20, 40), 0, 0, 11, 3},
- {5, UPB_SIZE(24, 48), 0, 0, 9, 3},
-};
-
-const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = {
- &google_protobuf_EnumDescriptorProto_submsgs[0],
- &google_protobuf_EnumDescriptorProto__fields[0],
- UPB_SIZE(32, 64), 5, false,
-};
-
-static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = {
- {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
- {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
-};
-
-const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = {
- NULL,
- &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0],
- UPB_SIZE(12, 12), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_submsgs[1] = {
- &google_protobuf_EnumValueOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__fields[3] = {
- {1, UPB_SIZE(8, 8), 2, 0, 9, 1},
- {2, UPB_SIZE(4, 4), 1, 0, 5, 1},
- {3, UPB_SIZE(16, 24), 3, 0, 11, 1},
-};
-
-const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit = {
- &google_protobuf_EnumValueDescriptorProto_submsgs[0],
- &google_protobuf_EnumValueDescriptorProto__fields[0],
- UPB_SIZE(24, 32), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs[2] = {
- &google_protobuf_MethodDescriptorProto_msginit,
- &google_protobuf_ServiceOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[3] = {
- {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
- {2, UPB_SIZE(16, 32), 0, 0, 11, 3},
- {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
-};
-
-const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit = {
- &google_protobuf_ServiceDescriptorProto_submsgs[0],
- &google_protobuf_ServiceDescriptorProto__fields[0],
- UPB_SIZE(24, 48), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[1] = {
- &google_protobuf_MethodOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_MethodDescriptorProto__fields[6] = {
- {1, UPB_SIZE(4, 8), 3, 0, 9, 1},
- {2, UPB_SIZE(12, 24), 4, 0, 9, 1},
- {3, UPB_SIZE(20, 40), 5, 0, 9, 1},
- {4, UPB_SIZE(28, 56), 6, 0, 11, 1},
- {5, UPB_SIZE(1, 1), 1, 0, 8, 1},
- {6, UPB_SIZE(2, 2), 2, 0, 8, 1},
-};
-
-const upb_msglayout google_protobuf_MethodDescriptorProto_msginit = {
- &google_protobuf_MethodDescriptorProto_submsgs[0],
- &google_protobuf_MethodDescriptorProto__fields[0],
- UPB_SIZE(32, 64), 6, false,
-};
-
-static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = {
- &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = {
- {1, UPB_SIZE(28, 32), 11, 0, 9, 1},
- {8, UPB_SIZE(36, 48), 12, 0, 9, 1},
- {9, UPB_SIZE(8, 8), 1, 0, 14, 1},
- {10, UPB_SIZE(16, 16), 2, 0, 8, 1},
- {11, UPB_SIZE(44, 64), 13, 0, 9, 1},
- {16, UPB_SIZE(17, 17), 3, 0, 8, 1},
- {17, UPB_SIZE(18, 18), 4, 0, 8, 1},
- {18, UPB_SIZE(19, 19), 5, 0, 8, 1},
- {20, UPB_SIZE(20, 20), 6, 0, 8, 1},
- {23, UPB_SIZE(21, 21), 7, 0, 8, 1},
- {27, UPB_SIZE(22, 22), 8, 0, 8, 1},
- {31, UPB_SIZE(23, 23), 9, 0, 8, 1},
- {36, UPB_SIZE(52, 80), 14, 0, 9, 1},
- {37, UPB_SIZE(60, 96), 15, 0, 9, 1},
- {39, UPB_SIZE(68, 112), 16, 0, 9, 1},
- {40, UPB_SIZE(76, 128), 17, 0, 9, 1},
- {41, UPB_SIZE(84, 144), 18, 0, 9, 1},
- {42, UPB_SIZE(24, 24), 10, 0, 8, 1},
- {44, UPB_SIZE(92, 160), 19, 0, 9, 1},
- {45, UPB_SIZE(100, 176), 20, 0, 9, 1},
- {999, UPB_SIZE(108, 192), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_FileOptions_msginit = {
- &google_protobuf_FileOptions_submsgs[0],
- &google_protobuf_FileOptions__fields[0],
- UPB_SIZE(112, 208), 21, false,
-};
-
-static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = {
- &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_MessageOptions__fields[5] = {
- {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
- {2, UPB_SIZE(2, 2), 2, 0, 8, 1},
- {3, UPB_SIZE(3, 3), 3, 0, 8, 1},
- {7, UPB_SIZE(4, 4), 4, 0, 8, 1},
- {999, UPB_SIZE(8, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_MessageOptions_msginit = {
- &google_protobuf_MessageOptions_submsgs[0],
- &google_protobuf_MessageOptions__fields[0],
- UPB_SIZE(12, 16), 5, false,
-};
-
-static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = {
- &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FieldOptions__fields[7] = {
- {1, UPB_SIZE(8, 8), 1, 0, 14, 1},
- {2, UPB_SIZE(24, 24), 3, 0, 8, 1},
- {3, UPB_SIZE(25, 25), 4, 0, 8, 1},
- {5, UPB_SIZE(26, 26), 5, 0, 8, 1},
- {6, UPB_SIZE(16, 16), 2, 0, 14, 1},
- {10, UPB_SIZE(27, 27), 6, 0, 8, 1},
- {999, UPB_SIZE(28, 32), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_FieldOptions_msginit = {
- &google_protobuf_FieldOptions_submsgs[0],
- &google_protobuf_FieldOptions__fields[0],
- UPB_SIZE(32, 40), 7, false,
-};
-
-static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = {
- &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_OneofOptions__fields[1] = {
- {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_OneofOptions_msginit = {
- &google_protobuf_OneofOptions_submsgs[0],
- &google_protobuf_OneofOptions__fields[0],
- UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = {
- &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumOptions__fields[3] = {
- {2, UPB_SIZE(1, 1), 1, 0, 8, 1},
- {3, UPB_SIZE(2, 2), 2, 0, 8, 1},
- {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_EnumOptions_msginit = {
- &google_protobuf_EnumOptions_submsgs[0],
- &google_protobuf_EnumOptions__fields[0],
- UPB_SIZE(8, 16), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] = {
- &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumValueOptions__fields[2] = {
- {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
- {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_EnumValueOptions_msginit = {
- &google_protobuf_EnumValueOptions_submsgs[0],
- &google_protobuf_EnumValueOptions__fields[0],
- UPB_SIZE(8, 16), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = {
- &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_ServiceOptions__fields[2] = {
- {33, UPB_SIZE(1, 1), 1, 0, 8, 1},
- {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_ServiceOptions_msginit = {
- &google_protobuf_ServiceOptions_submsgs[0],
- &google_protobuf_ServiceOptions__fields[0],
- UPB_SIZE(8, 16), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = {
- &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_MethodOptions__fields[3] = {
- {33, UPB_SIZE(16, 16), 2, 0, 8, 1},
- {34, UPB_SIZE(8, 8), 1, 0, 14, 1},
- {999, UPB_SIZE(20, 24), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_MethodOptions_msginit = {
- &google_protobuf_MethodOptions_submsgs[0],
- &google_protobuf_MethodOptions__fields[0],
- UPB_SIZE(24, 32), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] = {
- &google_protobuf_UninterpretedOption_NamePart_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7] = {
- {2, UPB_SIZE(56, 80), 0, 0, 11, 3},
- {3, UPB_SIZE(32, 32), 4, 0, 9, 1},
- {4, UPB_SIZE(8, 8), 1, 0, 4, 1},
- {5, UPB_SIZE(16, 16), 2, 0, 3, 1},
- {6, UPB_SIZE(24, 24), 3, 0, 1, 1},
- {7, UPB_SIZE(40, 48), 5, 0, 12, 1},
- {8, UPB_SIZE(48, 64), 6, 0, 9, 1},
-};
-
-const upb_msglayout google_protobuf_UninterpretedOption_msginit = {
- &google_protobuf_UninterpretedOption_submsgs[0],
- &google_protobuf_UninterpretedOption__fields[0],
- UPB_SIZE(64, 96), 7, false,
-};
-
-static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = {
- {1, UPB_SIZE(4, 8), 2, 0, 9, 2},
- {2, UPB_SIZE(1, 1), 1, 0, 8, 2},
-};
-
-const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit = {
- NULL,
- &google_protobuf_UninterpretedOption_NamePart__fields[0],
- UPB_SIZE(16, 32), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = {
- &google_protobuf_SourceCodeInfo_Location_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_SourceCodeInfo__fields[1] = {
- {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_SourceCodeInfo_msginit = {
- &google_protobuf_SourceCodeInfo_submsgs[0],
- &google_protobuf_SourceCodeInfo__fields[0],
- UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = {
- {1, UPB_SIZE(20, 40), 0, 0, 5, _UPB_LABEL_PACKED},
- {2, UPB_SIZE(24, 48), 0, 0, 5, _UPB_LABEL_PACKED},
- {3, UPB_SIZE(4, 8), 1, 0, 9, 1},
- {4, UPB_SIZE(12, 24), 2, 0, 9, 1},
- {6, UPB_SIZE(28, 56), 0, 0, 9, 3},
-};
-
-const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = {
- NULL,
- &google_protobuf_SourceCodeInfo_Location__fields[0],
- UPB_SIZE(32, 64), 5, false,
-};
-
-static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] = {
- &google_protobuf_GeneratedCodeInfo_Annotation_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_GeneratedCodeInfo__fields[1] = {
- {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = {
- &google_protobuf_GeneratedCodeInfo_submsgs[0],
- &google_protobuf_GeneratedCodeInfo__fields[0],
- UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = {
- {1, UPB_SIZE(20, 32), 0, 0, 5, _UPB_LABEL_PACKED},
- {2, UPB_SIZE(12, 16), 3, 0, 9, 1},
- {3, UPB_SIZE(4, 4), 1, 0, 5, 1},
- {4, UPB_SIZE(8, 8), 2, 0, 5, 1},
-};
-
-const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit = {
- NULL,
- &google_protobuf_GeneratedCodeInfo_Annotation__fields[0],
- UPB_SIZE(24, 48), 4, false,
-};
-
-
-
-
-#include
-#include
-#include
-#include
-
-
-typedef struct {
- size_t len;
- char str[1]; /* Null-terminated string data follows. */
-} str_t;
-
-static str_t *newstr(upb_alloc *alloc, const char *data, size_t len) {
- str_t *ret = upb_malloc(alloc, sizeof(*ret) + len);
- if (!ret) return NULL;
- ret->len = len;
- memcpy(ret->str, data, len);
- ret->str[len] = '\0';
- return ret;
-}
-
-struct upb_fielddef {
- const upb_filedef *file;
- const upb_msgdef *msgdef;
- const char *full_name;
- const char *json_name;
- union {
- int64_t sint;
- uint64_t uint;
- double dbl;
- float flt;
- bool boolean;
- str_t *str;
- } defaultval;
- const upb_oneofdef *oneof;
- union {
- const upb_msgdef *msgdef;
- const upb_enumdef *enumdef;
- const google_protobuf_FieldDescriptorProto *unresolved;
- } sub;
- uint32_t number_;
- uint16_t index_;
- uint16_t layout_index;
- uint32_t selector_base; /* Used to index into a upb::Handlers table. */
- bool is_extension_;
- bool lazy_;
- bool packed_;
- bool proto3_optional_;
- upb_descriptortype_t type_;
- upb_label_t label_;
-};
-
-struct upb_msgdef {
- const upb_msglayout *layout;
- const upb_filedef *file;
- const char *full_name;
- uint32_t selector_count;
- uint32_t submsg_field_count;
-
- /* Tables for looking up fields by number and name. */
- upb_inttable itof;
- upb_strtable ntof;
-
- const upb_fielddef *fields;
- const upb_oneofdef *oneofs;
- int field_count;
- int oneof_count;
- int real_oneof_count;
-
- /* Is this a map-entry message? */
- bool map_entry;
- upb_wellknowntype_t well_known_type;
-
- /* TODO(haberman): proper extension ranges (there can be multiple). */
-};
-
-struct upb_enumdef {
- const upb_filedef *file;
- const char *full_name;
- upb_strtable ntoi;
- upb_inttable iton;
- int32_t defaultval;
-};
-
-struct upb_oneofdef {
- const upb_msgdef *parent;
- const char *full_name;
- uint32_t index;
- upb_strtable ntof;
- upb_inttable itof;
-};
-
-struct upb_filedef {
- const char *name;
- const char *package;
- const char *phpprefix;
- const char *phpnamespace;
- upb_syntax_t syntax;
-
- const upb_filedef **deps;
- const upb_msgdef *msgs;
- const upb_enumdef *enums;
- const upb_fielddef *exts;
-
- int dep_count;
- int msg_count;
- int enum_count;
- int ext_count;
-};
-
-struct upb_symtab {
- upb_arena *arena;
- upb_strtable syms; /* full_name -> packed def ptr */
- upb_strtable files; /* file_name -> upb_filedef* */
-};
-
-/* Inside a symtab we store tagged pointers to specific def types. */
-typedef enum {
- UPB_DEFTYPE_FIELD = 0,
-
- /* Only inside symtab table. */
- UPB_DEFTYPE_MSG = 1,
- UPB_DEFTYPE_ENUM = 2,
-
- /* Only inside message table. */
- UPB_DEFTYPE_ONEOF = 1,
- UPB_DEFTYPE_FIELD_JSONNAME = 2
-} upb_deftype_t;
-
-static const void *unpack_def(upb_value v, upb_deftype_t type) {
- uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
- return (num & 3) == type ? (const void*)(num & ~3) : NULL;
-}
-
-static upb_value pack_def(const void *ptr, upb_deftype_t type) {
- uintptr_t num = (uintptr_t)ptr | type;
- return upb_value_constptr((const void*)num);
-}
-
-/* isalpha() etc. from are locale-dependent, which we don't want. */
-static bool upb_isbetween(char c, char low, char high) {
- return c >= low && c <= high;
-}
-
-static bool upb_isletter(char c) {
- return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_';
-}
-
-static bool upb_isalphanum(char c) {
- return upb_isletter(c) || upb_isbetween(c, '0', '9');
-}
-
-static bool upb_isident(upb_strview name, bool full, upb_status *s) {
- const char *str = name.data;
- size_t len = name.size;
- bool start = true;
- size_t i;
- for (i = 0; i < len; i++) {
- char c = str[i];
- if (c == '.') {
- if (start || !full) {
- upb_status_seterrf(s, "invalid name: unexpected '.' (%s)", str);
- return false;
- }
- start = true;
- } else if (start) {
- if (!upb_isletter(c)) {
- upb_status_seterrf(
- s, "invalid name: path components must start with a letter (%s)",
- str);
- return false;
- }
- start = false;
- } else {
- if (!upb_isalphanum(c)) {
- upb_status_seterrf(s, "invalid name: non-alphanumeric character (%s)",
- str);
- return false;
- }
- }
- }
- return !start;
-}
-
-static const char *shortdefname(const char *fullname) {
- const char *p;
-
- if (fullname == NULL) {
- return NULL;
- } else if ((p = strrchr(fullname, '.')) == NULL) {
- /* No '.' in the name, return the full string. */
- return fullname;
- } else {
- /* Return one past the last '.'. */
- return p + 1;
- }
-}
-
-/* All submessage fields are lower than all other fields.
- * Secondly, fields are increasing in order. */
-uint32_t field_rank(const upb_fielddef *f) {
- uint32_t ret = upb_fielddef_number(f);
- const uint32_t high_bit = 1 << 30;
- UPB_ASSERT(ret < high_bit);
- if (!upb_fielddef_issubmsg(f))
- ret |= high_bit;
- return ret;
-}
-
-int cmp_fields(const void *p1, const void *p2) {
- const upb_fielddef *f1 = *(upb_fielddef*const*)p1;
- const upb_fielddef *f2 = *(upb_fielddef*const*)p2;
- return field_rank(f1) - field_rank(f2);
-}
-
-/* A few implementation details of handlers. We put these here to avoid
- * a def -> handlers dependency. */
-
-#define UPB_STATIC_SELECTOR_COUNT 3 /* Warning: also in upb/handlers.h. */
-
-static uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
- return upb_fielddef_isseq(f) ? 2 : 0;
-}
-
-static uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
- uint32_t ret = 1;
- if (upb_fielddef_isseq(f)) ret += 2; /* STARTSEQ/ENDSEQ */
- if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */
- if (upb_fielddef_issubmsg(f)) {
- /* ENDSUBMSG (STARTSUBMSG is at table beginning) */
- ret += 0;
- if (upb_fielddef_lazy(f)) {
- /* STARTSTR/ENDSTR/STRING (for lazy) */
- ret += 3;
- }
- }
- return ret;
-}
-
-static void upb_status_setoom(upb_status *status) {
- upb_status_seterrmsg(status, "out of memory");
-}
-
-static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
- /* Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the
- * lowest indexes, but we do not publicly guarantee this. */
- upb_msg_field_iter j;
- int i;
- uint32_t selector;
- int n = upb_msgdef_numfields(m);
- upb_fielddef **fields;
-
- if (n == 0) {
- m->selector_count = UPB_STATIC_SELECTOR_COUNT;
- m->submsg_field_count = 0;
- return true;
- }
-
- fields = upb_gmalloc(n * sizeof(*fields));
- if (!fields) {
- upb_status_setoom(s);
- return false;
- }
-
- m->submsg_field_count = 0;
- for(i = 0, upb_msg_field_begin(&j, m);
- !upb_msg_field_done(&j);
- upb_msg_field_next(&j), i++) {
- upb_fielddef *f = upb_msg_iter_field(&j);
- UPB_ASSERT(f->msgdef == m);
- if (upb_fielddef_issubmsg(f)) {
- m->submsg_field_count++;
- }
- fields[i] = f;
- }
-
- qsort(fields, n, sizeof(*fields), cmp_fields);
-
- selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count;
- for (i = 0; i < n; i++) {
- upb_fielddef *f = fields[i];
- f->index_ = i;
- f->selector_base = selector + upb_handlers_selectorbaseoffset(f);
- selector += upb_handlers_selectorcount(f);
- }
- m->selector_count = selector;
-
- upb_gfree(fields);
- return true;
-}
-
-static bool check_oneofs(upb_msgdef *m, upb_status *s) {
- int i;
- int first_synthetic = -1;
- upb_oneofdef *mutable_oneofs = (upb_oneofdef*)m->oneofs;
-
- for (i = 0; i < m->oneof_count; i++) {
- mutable_oneofs[i].index = i;
-
- if (upb_oneofdef_issynthetic(&mutable_oneofs[i])) {
- if (first_synthetic == -1) {
- first_synthetic = i;
- }
- } else {
- if (first_synthetic != -1) {
- upb_status_seterrf(
- s, "Synthetic oneofs must be after all other oneofs: %s",
- upb_oneofdef_name(&mutable_oneofs[i]));
- return false;
- }
- }
- }
-
- if (first_synthetic == -1) {
- m->real_oneof_count = m->oneof_count;
- } else {
- m->real_oneof_count = first_synthetic;
- }
-
- return true;
-}
-
-static void assign_msg_wellknowntype(upb_msgdef *m) {
- const char *name = upb_msgdef_fullname(m);
- if (name == NULL) {
- m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
- return;
- }
- if (!strcmp(name, "google.protobuf.Any")) {
- m->well_known_type = UPB_WELLKNOWN_ANY;
- } else if (!strcmp(name, "google.protobuf.FieldMask")) {
- m->well_known_type = UPB_WELLKNOWN_FIELDMASK;
- } else if (!strcmp(name, "google.protobuf.Duration")) {
- m->well_known_type = UPB_WELLKNOWN_DURATION;
- } else if (!strcmp(name, "google.protobuf.Timestamp")) {
- m->well_known_type = UPB_WELLKNOWN_TIMESTAMP;
- } else if (!strcmp(name, "google.protobuf.DoubleValue")) {
- m->well_known_type = UPB_WELLKNOWN_DOUBLEVALUE;
- } else if (!strcmp(name, "google.protobuf.FloatValue")) {
- m->well_known_type = UPB_WELLKNOWN_FLOATVALUE;
- } else if (!strcmp(name, "google.protobuf.Int64Value")) {
- m->well_known_type = UPB_WELLKNOWN_INT64VALUE;
- } else if (!strcmp(name, "google.protobuf.UInt64Value")) {
- m->well_known_type = UPB_WELLKNOWN_UINT64VALUE;
- } else if (!strcmp(name, "google.protobuf.Int32Value")) {
- m->well_known_type = UPB_WELLKNOWN_INT32VALUE;
- } else if (!strcmp(name, "google.protobuf.UInt32Value")) {
- m->well_known_type = UPB_WELLKNOWN_UINT32VALUE;
- } else if (!strcmp(name, "google.protobuf.BoolValue")) {
- m->well_known_type = UPB_WELLKNOWN_BOOLVALUE;
- } else if (!strcmp(name, "google.protobuf.StringValue")) {
- m->well_known_type = UPB_WELLKNOWN_STRINGVALUE;
- } else if (!strcmp(name, "google.protobuf.BytesValue")) {
- m->well_known_type = UPB_WELLKNOWN_BYTESVALUE;
- } else if (!strcmp(name, "google.protobuf.Value")) {
- m->well_known_type = UPB_WELLKNOWN_VALUE;
- } else if (!strcmp(name, "google.protobuf.ListValue")) {
- m->well_known_type = UPB_WELLKNOWN_LISTVALUE;
- } else if (!strcmp(name, "google.protobuf.Struct")) {
- m->well_known_type = UPB_WELLKNOWN_STRUCT;
- } else {
- m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
- }
-}
-
-
-/* upb_enumdef ****************************************************************/
-
-const char *upb_enumdef_fullname(const upb_enumdef *e) {
- return e->full_name;
-}
-
-const char *upb_enumdef_name(const upb_enumdef *e) {
- return shortdefname(e->full_name);
-}
-
-const upb_filedef *upb_enumdef_file(const upb_enumdef *e) {
- return e->file;
-}
-
-int32_t upb_enumdef_default(const upb_enumdef *e) {
- UPB_ASSERT(upb_enumdef_iton(e, e->defaultval));
- return e->defaultval;
-}
-
-int upb_enumdef_numvals(const upb_enumdef *e) {
- return (int)upb_strtable_count(&e->ntoi);
-}
-
-void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) {
- /* We iterate over the ntoi table, to account for duplicate numbers. */
- upb_strtable_begin(i, &e->ntoi);
-}
-
-void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); }
-bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); }
-
-bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name,
- size_t len, int32_t *num) {
- upb_value v;
- if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) {
- return false;
- }
- if (num) *num = upb_value_getint32(v);
- return true;
-}
-
-const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) {
- upb_value v;
- return upb_inttable_lookup32(&def->iton, num, &v) ?
- upb_value_getcstr(v) : NULL;
-}
-
-const char *upb_enum_iter_name(upb_enum_iter *iter) {
- return upb_strtable_iter_key(iter).data;
-}
-
-int32_t upb_enum_iter_number(upb_enum_iter *iter) {
- return upb_value_getint32(upb_strtable_iter_value(iter));
-}
-
-
-/* upb_fielddef ***************************************************************/
-
-const char *upb_fielddef_fullname(const upb_fielddef *f) {
- return f->full_name;
-}
-
-upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) {
- switch (f->type_) {
- case UPB_DESCRIPTOR_TYPE_DOUBLE:
- return UPB_TYPE_DOUBLE;
- case UPB_DESCRIPTOR_TYPE_FLOAT:
- return UPB_TYPE_FLOAT;
- case UPB_DESCRIPTOR_TYPE_INT64:
- case UPB_DESCRIPTOR_TYPE_SINT64:
- case UPB_DESCRIPTOR_TYPE_SFIXED64:
- return UPB_TYPE_INT64;
- case UPB_DESCRIPTOR_TYPE_INT32:
- case UPB_DESCRIPTOR_TYPE_SFIXED32:
- case UPB_DESCRIPTOR_TYPE_SINT32:
- return UPB_TYPE_INT32;
- case UPB_DESCRIPTOR_TYPE_UINT64:
- case UPB_DESCRIPTOR_TYPE_FIXED64:
- return UPB_TYPE_UINT64;
- case UPB_DESCRIPTOR_TYPE_UINT32:
- case UPB_DESCRIPTOR_TYPE_FIXED32:
- return UPB_TYPE_UINT32;
- case UPB_DESCRIPTOR_TYPE_ENUM:
- return UPB_TYPE_ENUM;
- case UPB_DESCRIPTOR_TYPE_BOOL:
- return UPB_TYPE_BOOL;
- case UPB_DESCRIPTOR_TYPE_STRING:
- return UPB_TYPE_STRING;
- case UPB_DESCRIPTOR_TYPE_BYTES:
- return UPB_TYPE_BYTES;
- case UPB_DESCRIPTOR_TYPE_GROUP:
- case UPB_DESCRIPTOR_TYPE_MESSAGE:
- return UPB_TYPE_MESSAGE;
- }
- UPB_UNREACHABLE();
-}
-
-upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
- return f->type_;
-}
-
-uint32_t upb_fielddef_index(const upb_fielddef *f) {
- return f->index_;
-}
-
-upb_label_t upb_fielddef_label(const upb_fielddef *f) {
- return f->label_;
-}
-
-uint32_t upb_fielddef_number(const upb_fielddef *f) {
- return f->number_;
-}
-
-bool upb_fielddef_isextension(const upb_fielddef *f) {
- return f->is_extension_;
-}
-
-bool upb_fielddef_lazy(const upb_fielddef *f) {
- return f->lazy_;
-}
-
-bool upb_fielddef_packed(const upb_fielddef *f) {
- return f->packed_;
-}
-
-const char *upb_fielddef_name(const upb_fielddef *f) {
- return shortdefname(f->full_name);
-}
-
-const char *upb_fielddef_jsonname(const upb_fielddef *f) {
- return f->json_name;
-}
-
-uint32_t upb_fielddef_selectorbase(const upb_fielddef *f) {
- return f->selector_base;
-}
-
-const upb_filedef *upb_fielddef_file(const upb_fielddef *f) {
- return f->file;
-}
-
-const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
- return f->msgdef;
-}
-
-const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) {
- return f->oneof;
-}
-
-const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f) {
- if (!f->oneof || upb_oneofdef_issynthetic(f->oneof)) return NULL;
- return f->oneof;
-}
-
-static void chkdefaulttype(const upb_fielddef *f, int ctype) {
- UPB_UNUSED(f);
- UPB_UNUSED(ctype);
-}
-
-int64_t upb_fielddef_defaultint64(const upb_fielddef *f) {
- chkdefaulttype(f, UPB_TYPE_INT64);
- return f->defaultval.sint;
-}
-
-int32_t upb_fielddef_defaultint32(const upb_fielddef *f) {
- chkdefaulttype(f, UPB_TYPE_INT32);
- return (int32_t)f->defaultval.sint;
-}
-
-uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) {
- chkdefaulttype(f, UPB_TYPE_UINT64);
- return f->defaultval.uint;
-}
-
-uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) {
- chkdefaulttype(f, UPB_TYPE_UINT32);
- return (uint32_t)f->defaultval.uint;
-}
-
-bool upb_fielddef_defaultbool(const upb_fielddef *f) {
- chkdefaulttype(f, UPB_TYPE_BOOL);
- return f->defaultval.boolean;
-}
-
-float upb_fielddef_defaultfloat(const upb_fielddef *f) {
- chkdefaulttype(f, UPB_TYPE_FLOAT);
- return f->defaultval.flt;
-}
-
-double upb_fielddef_defaultdouble(const upb_fielddef *f) {
- chkdefaulttype(f, UPB_TYPE_DOUBLE);
- return f->defaultval.dbl;
-}
-
-const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
- str_t *str = f->defaultval.str;
- UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_STRING ||
- upb_fielddef_type(f) == UPB_TYPE_BYTES ||
- upb_fielddef_type(f) == UPB_TYPE_ENUM);
- if (str) {
- if (len) *len = str->len;
- return str->str;
- } else {
- if (len) *len = 0;
- return NULL;
- }
-}
-
-const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) {
- UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_MESSAGE);
- return f->sub.msgdef;
-}
-
-const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) {
- UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_ENUM);
- return f->sub.enumdef;
-}
-
-const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f) {
- return &f->msgdef->layout->fields[f->layout_index];
-}
-
-bool upb_fielddef_issubmsg(const upb_fielddef *f) {
- return upb_fielddef_type(f) == UPB_TYPE_MESSAGE;
-}
-
-bool upb_fielddef_isstring(const upb_fielddef *f) {
- return upb_fielddef_type(f) == UPB_TYPE_STRING ||
- upb_fielddef_type(f) == UPB_TYPE_BYTES;
-}
-
-bool upb_fielddef_isseq(const upb_fielddef *f) {
- return upb_fielddef_label(f) == UPB_LABEL_REPEATED;
-}
-
-bool upb_fielddef_isprimitive(const upb_fielddef *f) {
- return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f);
-}
-
-bool upb_fielddef_ismap(const upb_fielddef *f) {
- return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) &&
- upb_msgdef_mapentry(upb_fielddef_msgsubdef(f));
-}
-
-bool upb_fielddef_hassubdef(const upb_fielddef *f) {
- return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM;
-}
-
-bool upb_fielddef_haspresence(const upb_fielddef *f) {
- if (upb_fielddef_isseq(f)) return false;
- return upb_fielddef_issubmsg(f) || upb_fielddef_containingoneof(f) ||
- f->file->syntax == UPB_SYNTAX_PROTO2;
-}
-
-static bool between(int32_t x, int32_t low, int32_t high) {
- return x >= low && x <= high;
-}
-
-bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); }
-bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); }
-bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); }
-
-bool upb_fielddef_checkdescriptortype(int32_t type) {
- return between(type, 1, 18);
-}
-
-/* upb_msgdef *****************************************************************/
-
-const char *upb_msgdef_fullname(const upb_msgdef *m) {
- return m->full_name;
-}
-
-const upb_filedef *upb_msgdef_file(const upb_msgdef *m) {
- return m->file;
-}
-
-const char *upb_msgdef_name(const upb_msgdef *m) {
- return shortdefname(m->full_name);
-}
-
-upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) {
- return m->file->syntax;
-}
-
-size_t upb_msgdef_selectorcount(const upb_msgdef *m) {
- return m->selector_count;
-}
-
-uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m) {
- return m->submsg_field_count;
-}
-
-const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
- upb_value val;
- return upb_inttable_lookup32(&m->itof, i, &val) ?
- upb_value_getconstptr(val) : NULL;
-}
-
-const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
- size_t len) {
- upb_value val;
-
- if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
- return NULL;
- }
-
- return unpack_def(val, UPB_DEFTYPE_FIELD);
-}
-
-const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
- size_t len) {
- upb_value val;
-
- if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
- return NULL;
- }
-
- return unpack_def(val, UPB_DEFTYPE_ONEOF);
-}
-
-bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
- const upb_fielddef **f, const upb_oneofdef **o) {
- upb_value val;
-
- if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
- return false;
- }
-
- *o = unpack_def(val, UPB_DEFTYPE_ONEOF);
- *f = unpack_def(val, UPB_DEFTYPE_FIELD);
- return *o || *f; /* False if this was a JSON name. */
-}
-
-const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m,
- const char *name, size_t len) {
- upb_value val;
- const upb_fielddef* f;
-
- if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
- return NULL;
- }
-
- f = unpack_def(val, UPB_DEFTYPE_FIELD);
- if (!f) f = unpack_def(val, UPB_DEFTYPE_FIELD_JSONNAME);
-
- return f;
-}
-
-int upb_msgdef_numfields(const upb_msgdef *m) {
- return m->field_count;
-}
-
-int upb_msgdef_numoneofs(const upb_msgdef *m) {
- return m->oneof_count;
-}
-
-int upb_msgdef_numrealoneofs(const upb_msgdef *m) {
- return m->real_oneof_count;
-}
-
-const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m) {
- return m->layout;
-}
-
-const upb_fielddef *_upb_msgdef_field(const upb_msgdef *m, int i) {
- if (i >= m->field_count) return NULL;
- return &m->fields[i];
-}
-
-bool upb_msgdef_mapentry(const upb_msgdef *m) {
- return m->map_entry;
-}
-
-upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m) {
- return m->well_known_type;
-}
-
-bool upb_msgdef_isnumberwrapper(const upb_msgdef *m) {
- upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
- return type >= UPB_WELLKNOWN_DOUBLEVALUE &&
- type <= UPB_WELLKNOWN_UINT32VALUE;
-}
-
-void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) {
- upb_inttable_begin(iter, &m->itof);
-}
-
-void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); }
-
-bool upb_msg_field_done(const upb_msg_field_iter *iter) {
- return upb_inttable_done(iter);
-}
-
-upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) {
- return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
-}
-
-void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
- upb_inttable_iter_setdone(iter);
-}
-
-bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
- const upb_msg_field_iter * iter2) {
- return upb_inttable_iter_isequal(iter1, iter2);
-}
-
-void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
- upb_strtable_begin(iter, &m->ntof);
- /* We need to skip past any initial fields. */
- while (!upb_strtable_done(iter) &&
- !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF)) {
- upb_strtable_next(iter);
- }
-}
-
-void upb_msg_oneof_next(upb_msg_oneof_iter *iter) {
- /* We need to skip past fields to return only oneofs. */
- do {
- upb_strtable_next(iter);
- } while (!upb_strtable_done(iter) &&
- !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF));
-}
-
-bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
- return upb_strtable_done(iter);
-}
-
-const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) {
- return unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF);
-}
-
-void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) {
- upb_strtable_iter_setdone(iter);
-}
-
-bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
- const upb_msg_oneof_iter *iter2) {
- return upb_strtable_iter_isequal(iter1, iter2);
-}
-
-/* upb_oneofdef ***************************************************************/
-
-const char *upb_oneofdef_name(const upb_oneofdef *o) {
- return shortdefname(o->full_name);
-}
-
-const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) {
- return o->parent;
-}
-
-int upb_oneofdef_numfields(const upb_oneofdef *o) {
- return (int)upb_strtable_count(&o->ntof);
-}
-
-uint32_t upb_oneofdef_index(const upb_oneofdef *o) {
- return o->index;
-}
-
-bool upb_oneofdef_issynthetic(const upb_oneofdef *o) {
- upb_inttable_iter iter;
- const upb_fielddef *f;
- upb_inttable_begin(&iter, &o->itof);
- if (upb_oneofdef_numfields(o) != 1) return false;
- f = upb_value_getptr(upb_inttable_iter_value(&iter));
- UPB_ASSERT(f);
- return f->proto3_optional_;
-}
-
-const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
- const char *name, size_t length) {
- upb_value val;
- return upb_strtable_lookup2(&o->ntof, name, length, &val) ?
- upb_value_getptr(val) : NULL;
-}
-
-const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) {
- upb_value val;
- return upb_inttable_lookup32(&o->itof, num, &val) ?
- upb_value_getptr(val) : NULL;
-}
-
-void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) {
- upb_inttable_begin(iter, &o->itof);
-}
-
-void upb_oneof_next(upb_oneof_iter *iter) {
- upb_inttable_next(iter);
-}
-
-bool upb_oneof_done(upb_oneof_iter *iter) {
- return upb_inttable_done(iter);
-}
-
-upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) {
- return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
-}
-
-void upb_oneof_iter_setdone(upb_oneof_iter *iter) {
- upb_inttable_iter_setdone(iter);
-}
-
-/* Dynamic Layout Generation. *************************************************/
-
-static size_t div_round_up(size_t n, size_t d) {
- return (n + d - 1) / d;
-}
-
-static size_t upb_msgval_sizeof(upb_fieldtype_t type) {
- switch (type) {
- case UPB_TYPE_DOUBLE:
- case UPB_TYPE_INT64:
- case UPB_TYPE_UINT64:
- return 8;
- case UPB_TYPE_ENUM:
- case UPB_TYPE_INT32:
- case UPB_TYPE_UINT32:
- case UPB_TYPE_FLOAT:
- return 4;
- case UPB_TYPE_BOOL:
- return 1;
- case UPB_TYPE_MESSAGE:
- return sizeof(void*);
- case UPB_TYPE_BYTES:
- case UPB_TYPE_STRING:
- return sizeof(upb_strview);
- }
- UPB_UNREACHABLE();
-}
-
-static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) {
- if (upb_msgdef_mapentry(upb_fielddef_containingtype(f))) {
- upb_map_entry ent;
- UPB_ASSERT(sizeof(ent.k) == sizeof(ent.v));
- return sizeof(ent.k);
- } else if (upb_fielddef_isseq(f)) {
- return sizeof(void*);
- } else {
- return upb_msgval_sizeof(upb_fielddef_type(f));
- }
-}
-
-static uint32_t upb_msglayout_place(upb_msglayout *l, size_t size) {
- uint32_t ret;
-
- l->size = UPB_ALIGN_UP(l->size, size);
- ret = l->size;
- l->size += size;
- return ret;
-}
-
-/* This function is the dynamic equivalent of message_layout.{cc,h} in upbc.
- * It computes a dynamic layout for all of the fields in |m|. */
-static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) {
- upb_msglayout *l = (upb_msglayout*)m->layout;
- upb_msg_field_iter it;
- upb_msg_oneof_iter oit;
- size_t hasbit;
- size_t submsg_count = m->submsg_field_count;
- const upb_msglayout **submsgs;
- upb_msglayout_field *fields;
- upb_alloc *alloc = upb_arena_alloc(symtab->arena);
-
- memset(l, 0, sizeof(*l));
-
- fields = upb_malloc(alloc, upb_msgdef_numfields(m) * sizeof(*fields));
- submsgs = upb_malloc(alloc, submsg_count * sizeof(*submsgs));
-
- if ((!fields && upb_msgdef_numfields(m)) ||
- (!submsgs && submsg_count)) {
- /* OOM. */
- return false;
- }
-
- l->field_count = upb_msgdef_numfields(m);
- l->fields = fields;
- l->submsgs = submsgs;
-
- if (upb_msgdef_mapentry(m)) {
- /* TODO(haberman): refactor this method so this special case is more
- * elegant. */
- const upb_fielddef *key = upb_msgdef_itof(m, 1);
- const upb_fielddef *val = upb_msgdef_itof(m, 2);
- fields[0].number = 1;
- fields[1].number = 2;
- fields[0].label = UPB_LABEL_OPTIONAL;
- fields[1].label = UPB_LABEL_OPTIONAL;
- fields[0].presence = 0;
- fields[1].presence = 0;
- fields[0].descriptortype = upb_fielddef_descriptortype(key);
- fields[1].descriptortype = upb_fielddef_descriptortype(val);
- fields[0].offset = 0;
- fields[1].offset = sizeof(upb_strview);
- fields[1].submsg_index = 0;
-
- if (upb_fielddef_type(val) == UPB_TYPE_MESSAGE) {
- submsgs[0] = upb_fielddef_msgsubdef(val)->layout;
- }
-
- l->field_count = 2;
- l->size = 2 * sizeof(upb_strview);
- l->size = UPB_ALIGN_UP(l->size, 8);
- return true;
- }
-
- /* Allocate data offsets in three stages:
- *
- * 1. hasbits.
- * 2. regular fields.
- * 3. oneof fields.
- *
- * OPT: There is a lot of room for optimization here to minimize the size.
- */
-
- /* Allocate hasbits and set basic field attributes. */
- submsg_count = 0;
- for (upb_msg_field_begin(&it, m), hasbit = 0;
- !upb_msg_field_done(&it);
- upb_msg_field_next(&it)) {
- upb_fielddef* f = upb_msg_iter_field(&it);
- upb_msglayout_field *field = &fields[upb_fielddef_index(f)];
-
- field->number = upb_fielddef_number(f);
- field->descriptortype = upb_fielddef_descriptortype(f);
- field->label = upb_fielddef_label(f);
-
- if (upb_fielddef_ismap(f)) {
- field->label = _UPB_LABEL_MAP;
- } else if (upb_fielddef_packed(f)) {
- field->label = _UPB_LABEL_PACKED;
- }
-
- /* TODO: we probably should sort the fields by field number to match the
- * output of upbc, and to improve search speed for the table parser. */
- f->layout_index = f->index_;
-
- if (upb_fielddef_issubmsg(f)) {
- const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
- field->submsg_index = submsg_count++;
- submsgs[field->submsg_index] = subm->layout;
- }
-
- if (upb_fielddef_haspresence(f) && !upb_fielddef_realcontainingoneof(f)) {
- /* We don't use hasbit 0, so that 0 can indicate "no presence" in the
- * table. This wastes one hasbit, but we don't worry about it for now. */
- field->presence = ++hasbit;
- } else {
- field->presence = 0;
- }
- }
-
- /* Account for space used by hasbits. */
- l->size = div_round_up(hasbit, 8);
-
- /* Allocate non-oneof fields. */
- for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it);
- upb_msg_field_next(&it)) {
- const upb_fielddef* f = upb_msg_iter_field(&it);
- size_t field_size = upb_msg_fielddefsize(f);
- size_t index = upb_fielddef_index(f);
-
- if (upb_fielddef_realcontainingoneof(f)) {
- /* Oneofs are handled separately below. */
- continue;
- }
-
- fields[index].offset = upb_msglayout_place(l, field_size);
- }
-
- /* Allocate oneof fields. Each oneof field consists of a uint32 for the case
- * and space for the actual data. */
- for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit);
- upb_msg_oneof_next(&oit)) {
- const upb_oneofdef* o = upb_msg_iter_oneof(&oit);
- upb_oneof_iter fit;
-
- size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */
- size_t field_size = 0;
- uint32_t case_offset;
- uint32_t data_offset;
-
- if (upb_oneofdef_issynthetic(o)) continue;
-
- /* Calculate field size: the max of all field sizes. */
- for (upb_oneof_begin(&fit, o);
- !upb_oneof_done(&fit);
- upb_oneof_next(&fit)) {
- const upb_fielddef* f = upb_oneof_iter_field(&fit);
- field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f));
- }
-
- /* Align and allocate case offset. */
- case_offset = upb_msglayout_place(l, case_size);
- data_offset = upb_msglayout_place(l, field_size);
-
- for (upb_oneof_begin(&fit, o);
- !upb_oneof_done(&fit);
- upb_oneof_next(&fit)) {
- const upb_fielddef* f = upb_oneof_iter_field(&fit);
- fields[upb_fielddef_index(f)].offset = data_offset;
- fields[upb_fielddef_index(f)].presence = ~case_offset;
- }
- }
-
- /* Size of the entire structure should be a multiple of its greatest
- * alignment. TODO: track overall alignment for real? */
- l->size = UPB_ALIGN_UP(l->size, 8);
-
- return true;
-}
-
-/* Code to build defs from descriptor protos. *********************************/
-
-/* There is a question of how much validation to do here. It will be difficult
- * to perfectly match the amount of validation performed by proto2. But since
- * this code is used to directly build defs from Ruby (for example) we do need
- * to validate important constraints like uniqueness of names and numbers. */
-
-#define CHK(x) if (!(x)) { return false; }
-#define CHK_OOM(x) if (!(x)) { upb_status_setoom(ctx->status); return false; }
-
-typedef struct {
- const upb_symtab *symtab;
- upb_filedef *file; /* File we are building. */
- upb_alloc *alloc; /* Allocate defs here. */
- upb_alloc *tmp; /* Alloc for addtab and any other tmp data. */
- upb_strtable *addtab; /* full_name -> packed def ptr for new defs */
- const upb_msglayout **layouts; /* NULL if we should build layouts. */
- upb_status *status; /* Record errors here. */
-} symtab_addctx;
-
-static char* strviewdup(const symtab_addctx *ctx, upb_strview view) {
- return upb_strdup2(view.data, view.size, ctx->alloc);
-}
-
-static bool streql2(const char *a, size_t n, const char *b) {
- return n == strlen(b) && memcmp(a, b, n) == 0;
-}
-
-static bool streql_view(upb_strview view, const char *b) {
- return streql2(view.data, view.size, b);
-}
-
-static const char *makefullname(const symtab_addctx *ctx, const char *prefix,
- upb_strview name) {
- if (prefix) {
- /* ret = prefix + '.' + name; */
- size_t n = strlen(prefix);
- char *ret = upb_malloc(ctx->alloc, n + name.size + 2);
- CHK_OOM(ret);
- strcpy(ret, prefix);
- ret[n] = '.';
- memcpy(&ret[n + 1], name.data, name.size);
- ret[n + 1 + name.size] = '\0';
- return ret;
- } else {
- return strviewdup(ctx, name);
- }
-}
-
-size_t getjsonname(const char *name, char *buf, size_t len) {
- size_t src, dst = 0;
- bool ucase_next = false;
-
-#define WRITE(byte) \
- ++dst; \
- if (dst < len) buf[dst - 1] = byte; \
- else if (dst == len) buf[dst - 1] = '\0'
-
- if (!name) {
- WRITE('\0');
- return 0;
- }
-
- /* Implement the transformation as described in the spec:
- * 1. upper case all letters after an underscore.
- * 2. remove all underscores.
- */
- for (src = 0; name[src]; src++) {
- if (name[src] == '_') {
- ucase_next = true;
- continue;
- }
-
- if (ucase_next) {
- WRITE(toupper(name[src]));
- ucase_next = false;
- } else {
- WRITE(name[src]);
- }
- }
-
- WRITE('\0');
- return dst;
-
-#undef WRITE
-}
-
-static char* makejsonname(const char* name, upb_alloc *alloc) {
- size_t size = getjsonname(name, NULL, 0);
- char* json_name = upb_malloc(alloc, size);
- getjsonname(name, json_name, size);
- return json_name;
-}
-
-static bool symtab_add(const symtab_addctx *ctx, const char *name,
- upb_value v) {
- upb_value tmp;
- if (upb_strtable_lookup(ctx->addtab, name, &tmp) ||
- upb_strtable_lookup(&ctx->symtab->syms, name, &tmp)) {
- upb_status_seterrf(ctx->status, "duplicate symbol '%s'", name);
- return false;
- }
-
- CHK_OOM(upb_strtable_insert3(ctx->addtab, name, strlen(name), v, ctx->tmp));
- return true;
-}
-
-/* Given a symbol and the base symbol inside which it is defined, find the
- * symbol's definition in t. */
-static bool resolvename(const upb_strtable *t, const upb_fielddef *f,
- const char *base, upb_strview sym,
- upb_deftype_t type, upb_status *status,
- const void **def) {
- if(sym.size == 0) return NULL;
- if(sym.data[0] == '.') {
- /* Symbols starting with '.' are absolute, so we do a single lookup.
- * Slice to omit the leading '.' */
- upb_value v;
- if (!upb_strtable_lookup2(t, sym.data + 1, sym.size - 1, &v)) {
- return false;
- }
-
- *def = unpack_def(v, type);
-
- if (!*def) {
- upb_status_seterrf(status,
- "type mismatch when resolving field %s, name %s",
- f->full_name, sym.data);
- return false;
- }
-
- return true;
- } else {
- /* Remove components from base until we find an entry or run out.
- * TODO: This branch is totally broken, but currently not used. */
- (void)base;
- UPB_ASSERT(false);
- return false;
- }
-}
-
-const void *symtab_resolve(const symtab_addctx *ctx, const upb_fielddef *f,
- const char *base, upb_strview sym,
- upb_deftype_t type) {
- const void *ret;
- if (!resolvename(ctx->addtab, f, base, sym, type, ctx->status, &ret) &&
- !resolvename(&ctx->symtab->syms, f, base, sym, type, ctx->status, &ret)) {
- if (upb_ok(ctx->status)) {
- upb_status_seterrf(ctx->status, "couldn't resolve name '%s'", sym.data);
- }
- return false;
- }
- return ret;
-}
-
-static bool create_oneofdef(
- const symtab_addctx *ctx, upb_msgdef *m,
- const google_protobuf_OneofDescriptorProto *oneof_proto) {
- upb_oneofdef *o;
- upb_strview name = google_protobuf_OneofDescriptorProto_name(oneof_proto);
- upb_value v;
-
- o = (upb_oneofdef*)&m->oneofs[m->oneof_count++];
- o->parent = m;
- o->full_name = makefullname(ctx, m->full_name, name);
-
- v = pack_def(o, UPB_DEFTYPE_ONEOF);
- CHK_OOM(symtab_add(ctx, o->full_name, v));
- CHK_OOM(upb_strtable_insert3(&m->ntof, name.data, name.size, v, ctx->alloc));
-
- CHK_OOM(upb_inttable_init2(&o->itof, UPB_CTYPE_CONSTPTR, ctx->alloc));
- CHK_OOM(upb_strtable_init2(&o->ntof, UPB_CTYPE_CONSTPTR, ctx->alloc));
-
- return true;
-}
-
-static bool parse_default(const symtab_addctx *ctx, const char *str, size_t len,
- upb_fielddef *f) {
- char *end;
- char nullz[64];
- errno = 0;
-
- switch (upb_fielddef_type(f)) {
- case UPB_TYPE_INT32:
- case UPB_TYPE_INT64:
- case UPB_TYPE_UINT32:
- case UPB_TYPE_UINT64:
- case UPB_TYPE_DOUBLE:
- case UPB_TYPE_FLOAT:
- /* Standard C number parsing functions expect null-terminated strings. */
- if (len >= sizeof(nullz) - 1) {
- return false;
- }
- memcpy(nullz, str, len);
- nullz[len] = '\0';
- str = nullz;
- break;
- default:
- break;
- }
-
- switch (upb_fielddef_type(f)) {
- case UPB_TYPE_INT32: {
- long val = strtol(str, &end, 0);
- CHK(val <= INT32_MAX && val >= INT32_MIN && errno != ERANGE && !*end);
- f->defaultval.sint = val;
- break;
- }
- case UPB_TYPE_ENUM: {
- const upb_enumdef *e = f->sub.enumdef;
- int32_t val;
- CHK(upb_enumdef_ntoi(e, str, len, &val));
- f->defaultval.sint = val;
- break;
- }
- case UPB_TYPE_INT64: {
- /* XXX: Need to write our own strtoll, since it's not available in c89. */
- int64_t val = strtol(str, &end, 0);
- CHK(val <= INT64_MAX && val >= INT64_MIN && errno != ERANGE && !*end);
- f->defaultval.sint = val;
- break;
- }
- case UPB_TYPE_UINT32: {
- unsigned long val = strtoul(str, &end, 0);
- CHK(val <= UINT32_MAX && errno != ERANGE && !*end);
- f->defaultval.uint = val;
- break;
- }
- case UPB_TYPE_UINT64: {
- /* XXX: Need to write our own strtoull, since it's not available in c89. */
- uint64_t val = strtoul(str, &end, 0);
- CHK(val <= UINT64_MAX && errno != ERANGE && !*end);
- f->defaultval.uint = val;
- break;
- }
- case UPB_TYPE_DOUBLE: {
- double val = strtod(str, &end);
- CHK(errno != ERANGE && !*end);
- f->defaultval.dbl = val;
- break;
- }
- case UPB_TYPE_FLOAT: {
- /* XXX: Need to write our own strtof, since it's not available in c89. */
- float val = strtod(str, &end);
- CHK(errno != ERANGE && !*end);
- f->defaultval.flt = val;
- break;
- }
- case UPB_TYPE_BOOL: {
- if (streql2(str, len, "false")) {
- f->defaultval.boolean = false;
- } else if (streql2(str, len, "true")) {
- f->defaultval.boolean = true;
- } else {
- return false;
- }
- break;
- }
- case UPB_TYPE_STRING:
- f->defaultval.str = newstr(ctx->alloc, str, len);
- break;
- case UPB_TYPE_BYTES:
- /* XXX: need to interpret the C-escaped value. */
- f->defaultval.str = newstr(ctx->alloc, str, len);
- break;
- case UPB_TYPE_MESSAGE:
- /* Should not have a default value. */
- return false;
- }
- return true;
-}
-
-static void set_default_default(const symtab_addctx *ctx, upb_fielddef *f) {
- switch (upb_fielddef_type(f)) {
- case UPB_TYPE_INT32:
- case UPB_TYPE_INT64:
- case UPB_TYPE_ENUM:
- f->defaultval.sint = 0;
- break;
- case UPB_TYPE_UINT64:
- case UPB_TYPE_UINT32:
- f->defaultval.uint = 0;
- break;
- case UPB_TYPE_DOUBLE:
- case UPB_TYPE_FLOAT:
- f->defaultval.dbl = 0;
- break;
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES:
- f->defaultval.str = newstr(ctx->alloc, NULL, 0);
- break;
- case UPB_TYPE_BOOL:
- f->defaultval.boolean = false;
- break;
- case UPB_TYPE_MESSAGE:
- break;
- }
-}
-
-static bool create_fielddef(
- const symtab_addctx *ctx, const char *prefix, upb_msgdef *m,
- const google_protobuf_FieldDescriptorProto *field_proto) {
- upb_alloc *alloc = ctx->alloc;
- upb_fielddef *f;
- const google_protobuf_FieldOptions *options;
- upb_strview name;
- const char *full_name;
- const char *json_name;
- const char *shortname;
- uint32_t field_number;
-
- if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) {
- upb_status_seterrmsg(ctx->status, "field has no name");
- return false;
- }
-
- name = google_protobuf_FieldDescriptorProto_name(field_proto);
- CHK(upb_isident(name, false, ctx->status));
- full_name = makefullname(ctx, prefix, name);
- shortname = shortdefname(full_name);
-
- if (google_protobuf_FieldDescriptorProto_has_json_name(field_proto)) {
- json_name = strviewdup(
- ctx, google_protobuf_FieldDescriptorProto_json_name(field_proto));
- } else {
- json_name = makejsonname(shortname, ctx->alloc);
- }
-
- field_number = google_protobuf_FieldDescriptorProto_number(field_proto);
-
- if (field_number == 0 || field_number > UPB_MAX_FIELDNUMBER) {
- upb_status_seterrf(ctx->status, "invalid field number (%u)", field_number);
- return false;
- }
-
- if (m) {
- /* direct message field. */
- upb_value v, field_v, json_v;
- size_t json_size;
-
- f = (upb_fielddef*)&m->fields[m->field_count++];
- f->msgdef = m;
- f->is_extension_ = false;
-
- if (upb_strtable_lookup(&m->ntof, shortname, NULL)) {
- upb_status_seterrf(ctx->status, "duplicate field name (%s)", shortname);
- return false;
- }
-
- if (upb_strtable_lookup(&m->ntof, json_name, NULL)) {
- upb_status_seterrf(ctx->status, "duplicate json_name (%s)", json_name);
- return false;
- }
-
- if (upb_inttable_lookup(&m->itof, field_number, NULL)) {
- upb_status_seterrf(ctx->status, "duplicate field number (%u)",
- field_number);
- return false;
- }
-
- field_v = pack_def(f, UPB_DEFTYPE_FIELD);
- json_v = pack_def(f, UPB_DEFTYPE_FIELD_JSONNAME);
- v = upb_value_constptr(f);
- json_size = strlen(json_name);
-
- CHK_OOM(
- upb_strtable_insert3(&m->ntof, name.data, name.size, field_v, alloc));
- CHK_OOM(upb_inttable_insert2(&m->itof, field_number, v, alloc));
-
- if (strcmp(shortname, json_name) != 0) {
- upb_strtable_insert3(&m->ntof, json_name, json_size, json_v, alloc);
- }
-
- if (ctx->layouts) {
- const upb_msglayout_field *fields = m->layout->fields;
- int count = m->layout->field_count;
- bool found = false;
- int i;
- for (i = 0; i < count; i++) {
- if (fields[i].number == field_number) {
- f->layout_index = i;
- found = true;
- break;
- }
- }
- UPB_ASSERT(found);
- }
- } else {
- /* extension field. */
- f = (upb_fielddef*)&ctx->file->exts[ctx->file->ext_count++];
- f->is_extension_ = true;
- CHK_OOM(symtab_add(ctx, full_name, pack_def(f, UPB_DEFTYPE_FIELD)));
- }
-
- f->full_name = full_name;
- f->json_name = json_name;
- f->file = ctx->file;
- f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto);
- f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto);
- f->number_ = field_number;
- f->oneof = NULL;
- f->proto3_optional_ =
- google_protobuf_FieldDescriptorProto_proto3_optional(field_proto);
-
- /* We can't resolve the subdef or (in the case of extensions) the containing
- * message yet, because it may not have been defined yet. We stash a pointer
- * to the field_proto until later when we can properly resolve it. */
- f->sub.unresolved = field_proto;
-
- if (f->label_ == UPB_LABEL_REQUIRED && f->file->syntax == UPB_SYNTAX_PROTO3) {
- upb_status_seterrf(ctx->status, "proto3 fields cannot be required (%s)",
- f->full_name);
- return false;
- }
-
- if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
- int oneof_index =
- google_protobuf_FieldDescriptorProto_oneof_index(field_proto);
- upb_oneofdef *oneof;
- upb_value v = upb_value_constptr(f);
-
- if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) {
- upb_status_seterrf(ctx->status,
- "fields in oneof must have OPTIONAL label (%s)",
- f->full_name);
- return false;
- }
-
- if (!m) {
- upb_status_seterrf(ctx->status,
- "oneof_index provided for extension field (%s)",
- f->full_name);
- return false;
- }
-
- if (oneof_index >= m->oneof_count) {
- upb_status_seterrf(ctx->status, "oneof_index out of range (%s)",
- f->full_name);
- return false;
- }
-
- oneof = (upb_oneofdef*)&m->oneofs[oneof_index];
- f->oneof = oneof;
-
- CHK(upb_inttable_insert2(&oneof->itof, f->number_, v, alloc));
- CHK(upb_strtable_insert3(&oneof->ntof, name.data, name.size, v, alloc));
- } else {
- f->oneof = NULL;
- }
-
- if (google_protobuf_FieldDescriptorProto_has_options(field_proto)) {
- options = google_protobuf_FieldDescriptorProto_options(field_proto);
- f->lazy_ = google_protobuf_FieldOptions_lazy(options);
- f->packed_ = google_protobuf_FieldOptions_packed(options);
- } else {
- f->lazy_ = false;
- f->packed_ = false;
- }
-
- return true;
-}
-
-static bool create_enumdef(
- const symtab_addctx *ctx, const char *prefix,
- const google_protobuf_EnumDescriptorProto *enum_proto) {
- upb_enumdef *e;
- const google_protobuf_EnumValueDescriptorProto *const *values;
- upb_strview name;
- size_t i, n;
-
- name = google_protobuf_EnumDescriptorProto_name(enum_proto);
- CHK(upb_isident(name, false, ctx->status));
-
- e = (upb_enumdef*)&ctx->file->enums[ctx->file->enum_count++];
- e->full_name = makefullname(ctx, prefix, name);
- CHK_OOM(symtab_add(ctx, e->full_name, pack_def(e, UPB_DEFTYPE_ENUM)));
-
- CHK_OOM(upb_strtable_init2(&e->ntoi, UPB_CTYPE_INT32, ctx->alloc));
- CHK_OOM(upb_inttable_init2(&e->iton, UPB_CTYPE_CSTR, ctx->alloc));
-
- e->file = ctx->file;
- e->defaultval = 0;
-
- values = google_protobuf_EnumDescriptorProto_value(enum_proto, &n);
-
- if (n == 0) {
- upb_status_seterrf(ctx->status,
- "enums must contain at least one value (%s)",
- e->full_name);
- return false;
- }
-
- for (i = 0; i < n; i++) {
- const google_protobuf_EnumValueDescriptorProto *value = values[i];
- upb_strview name = google_protobuf_EnumValueDescriptorProto_name(value);
- char *name2 = strviewdup(ctx, name);
- int32_t num = google_protobuf_EnumValueDescriptorProto_number(value);
- upb_value v = upb_value_int32(num);
-
- if (i == 0 && e->file->syntax == UPB_SYNTAX_PROTO3 && num != 0) {
- upb_status_seterrf(ctx->status,
- "for proto3, the first enum value must be zero (%s)",
- e->full_name);
- return false;
- }
-
- if (upb_strtable_lookup(&e->ntoi, name2, NULL)) {
- upb_status_seterrf(ctx->status, "duplicate enum label '%s'", name2);
- return false;
- }
-
- CHK_OOM(name2)
- CHK_OOM(
- upb_strtable_insert3(&e->ntoi, name2, strlen(name2), v, ctx->alloc));
-
- if (!upb_inttable_lookup(&e->iton, num, NULL)) {
- upb_value v = upb_value_cstr(name2);
- CHK_OOM(upb_inttable_insert2(&e->iton, num, v, ctx->alloc));
- }
- }
-
- upb_inttable_compact2(&e->iton, ctx->alloc);
-
- return true;
-}
-
-static bool create_msgdef(symtab_addctx *ctx, const char *prefix,
- const google_protobuf_DescriptorProto *msg_proto) {
- upb_msgdef *m;
- const google_protobuf_MessageOptions *options;
- const google_protobuf_OneofDescriptorProto *const *oneofs;
- const google_protobuf_FieldDescriptorProto *const *fields;
- const google_protobuf_EnumDescriptorProto *const *enums;
- const google_protobuf_DescriptorProto *const *msgs;
- size_t i, n;
- upb_strview name;
-
- name = google_protobuf_DescriptorProto_name(msg_proto);
- CHK(upb_isident(name, false, ctx->status));
-
- m = (upb_msgdef*)&ctx->file->msgs[ctx->file->msg_count++];
- m->full_name = makefullname(ctx, prefix, name);
- CHK_OOM(symtab_add(ctx, m->full_name, pack_def(m, UPB_DEFTYPE_MSG)));
-
- CHK_OOM(upb_inttable_init2(&m->itof, UPB_CTYPE_CONSTPTR, ctx->alloc));
- CHK_OOM(upb_strtable_init2(&m->ntof, UPB_CTYPE_CONSTPTR, ctx->alloc));
-
- m->file = ctx->file;
- m->map_entry = false;
-
- options = google_protobuf_DescriptorProto_options(msg_proto);
-
- if (options) {
- m->map_entry = google_protobuf_MessageOptions_map_entry(options);
- }
-
- if (ctx->layouts) {
- m->layout = *ctx->layouts;
- ctx->layouts++;
- } else {
- /* Allocate now (to allow cross-linking), populate later. */
- m->layout = upb_malloc(ctx->alloc, sizeof(*m->layout));
- }
-
- oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n);
- m->oneof_count = 0;
- m->oneofs = upb_malloc(ctx->alloc, sizeof(*m->oneofs) * n);
- for (i = 0; i < n; i++) {
- CHK(create_oneofdef(ctx, m, oneofs[i]));
- }
-
- fields = google_protobuf_DescriptorProto_field(msg_proto, &n);
- m->field_count = 0;
- m->fields = upb_malloc(ctx->alloc, sizeof(*m->fields) * n);
- for (i = 0; i < n; i++) {
- CHK(create_fielddef(ctx, m->full_name, m, fields[i]));
- }
-
- CHK(assign_msg_indices(m, ctx->status));
- CHK(check_oneofs(m, ctx->status));
- assign_msg_wellknowntype(m);
- upb_inttable_compact2(&m->itof, ctx->alloc);
-
- /* This message is built. Now build nested messages and enums. */
-
- enums = google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
- for (i = 0; i < n; i++) {
- CHK(create_enumdef(ctx, m->full_name, enums[i]));
- }
-
- msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
- for (i = 0; i < n; i++) {
- CHK(create_msgdef(ctx, m->full_name, msgs[i]));
- }
-
- return true;
-}
-
-typedef struct {
- int msg_count;
- int enum_count;
- int ext_count;
-} decl_counts;
-
-static void count_types_in_msg(const google_protobuf_DescriptorProto *msg_proto,
- decl_counts *counts) {
- const google_protobuf_DescriptorProto *const *msgs;
- size_t i, n;
-
- counts->msg_count++;
-
- msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
- for (i = 0; i < n; i++) {
- count_types_in_msg(msgs[i], counts);
- }
-
- google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
- counts->enum_count += n;
-
- google_protobuf_DescriptorProto_extension(msg_proto, &n);
- counts->ext_count += n;
-}
-
-static void count_types_in_file(
- const google_protobuf_FileDescriptorProto *file_proto,
- decl_counts *counts) {
- const google_protobuf_DescriptorProto *const *msgs;
- size_t i, n;
-
- msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
- for (i = 0; i < n; i++) {
- count_types_in_msg(msgs[i], counts);
- }
-
- google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
- counts->enum_count += n;
-
- google_protobuf_FileDescriptorProto_extension(file_proto, &n);
- counts->ext_count += n;
-}
-
-static bool resolve_fielddef(const symtab_addctx *ctx, const char *prefix,
- upb_fielddef *f) {
- upb_strview name;
- const google_protobuf_FieldDescriptorProto *field_proto = f->sub.unresolved;
-
- if (f->is_extension_) {
- if (!google_protobuf_FieldDescriptorProto_has_extendee(field_proto)) {
- upb_status_seterrf(ctx->status,
- "extension for field '%s' had no extendee",
- f->full_name);
- return false;
- }
-
- name = google_protobuf_FieldDescriptorProto_extendee(field_proto);
- f->msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
- CHK(f->msgdef);
- }
-
- if ((upb_fielddef_issubmsg(f) || f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) &&
- !google_protobuf_FieldDescriptorProto_has_type_name(field_proto)) {
- upb_status_seterrf(ctx->status, "field '%s' is missing type name",
- f->full_name);
- return false;
- }
-
- name = google_protobuf_FieldDescriptorProto_type_name(field_proto);
-
- if (upb_fielddef_issubmsg(f)) {
- f->sub.msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
- CHK(f->sub.msgdef);
- } else if (f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) {
- f->sub.enumdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_ENUM);
- CHK(f->sub.enumdef);
- }
-
- /* Have to delay resolving of the default value until now because of the enum
- * case, since enum defaults are specified with a label. */
- if (google_protobuf_FieldDescriptorProto_has_default_value(field_proto)) {
- upb_strview defaultval =
- google_protobuf_FieldDescriptorProto_default_value(field_proto);
-
- if (f->file->syntax == UPB_SYNTAX_PROTO3) {
- upb_status_seterrf(ctx->status,
- "proto3 fields cannot have explicit defaults (%s)",
- f->full_name);
- return false;
- }
-
- if (upb_fielddef_issubmsg(f)) {
- upb_status_seterrf(ctx->status,
- "message fields cannot have explicit defaults (%s)",
- f->full_name);
- return false;
- }
-
- if (!parse_default(ctx, defaultval.data, defaultval.size, f)) {
- upb_status_seterrf(ctx->status,
- "couldn't parse default '" UPB_STRVIEW_FORMAT
- "' for field (%s)",
- UPB_STRVIEW_ARGS(defaultval), f->full_name);
- return false;
- }
- } else {
- set_default_default(ctx, f);
- }
-
- return true;
-}
-
-static bool build_filedef(
- symtab_addctx *ctx, upb_filedef *file,
- const google_protobuf_FileDescriptorProto *file_proto) {
- upb_alloc *alloc = ctx->alloc;
- const google_protobuf_FileOptions *file_options_proto;
- const google_protobuf_DescriptorProto *const *msgs;
- const google_protobuf_EnumDescriptorProto *const *enums;
- const google_protobuf_FieldDescriptorProto *const *exts;
- const upb_strview* strs;
- size_t i, n;
- decl_counts counts = {0};
-
- count_types_in_file(file_proto, &counts);
-
- file->msgs = upb_malloc(alloc, sizeof(*file->msgs) * counts.msg_count);
- file->enums = upb_malloc(alloc, sizeof(*file->enums) * counts.enum_count);
- file->exts = upb_malloc(alloc, sizeof(*file->exts) * counts.ext_count);
-
- CHK_OOM(counts.msg_count == 0 || file->msgs);
- CHK_OOM(counts.enum_count == 0 || file->enums);
- CHK_OOM(counts.ext_count == 0 || file->exts);
-
- /* We increment these as defs are added. */
- file->msg_count = 0;
- file->enum_count = 0;
- file->ext_count = 0;
-
- if (!google_protobuf_FileDescriptorProto_has_name(file_proto)) {
- upb_status_seterrmsg(ctx->status, "File has no name");
- return false;
- }
-
- file->name =
- strviewdup(ctx, google_protobuf_FileDescriptorProto_name(file_proto));
- file->phpprefix = NULL;
- file->phpnamespace = NULL;
-
- if (google_protobuf_FileDescriptorProto_has_package(file_proto)) {
- upb_strview package =
- google_protobuf_FileDescriptorProto_package(file_proto);
- CHK(upb_isident(package, true, ctx->status));
- file->package = strviewdup(ctx, package);
- } else {
- file->package = NULL;
- }
-
- if (google_protobuf_FileDescriptorProto_has_syntax(file_proto)) {
- upb_strview syntax =
- google_protobuf_FileDescriptorProto_syntax(file_proto);
-
- if (streql_view(syntax, "proto2")) {
- file->syntax = UPB_SYNTAX_PROTO2;
- } else if (streql_view(syntax, "proto3")) {
- file->syntax = UPB_SYNTAX_PROTO3;
- } else {
- upb_status_seterrf(ctx->status, "Invalid syntax '" UPB_STRVIEW_FORMAT "'",
- UPB_STRVIEW_ARGS(syntax));
- return false;
- }
- } else {
- file->syntax = UPB_SYNTAX_PROTO2;
- }
-
- /* Read options. */
- file_options_proto = google_protobuf_FileDescriptorProto_options(file_proto);
- if (file_options_proto) {
- if (google_protobuf_FileOptions_has_php_class_prefix(file_options_proto)) {
- file->phpprefix = strviewdup(
- ctx,
- google_protobuf_FileOptions_php_class_prefix(file_options_proto));
- }
- if (google_protobuf_FileOptions_has_php_namespace(file_options_proto)) {
- file->phpnamespace = strviewdup(
- ctx, google_protobuf_FileOptions_php_namespace(file_options_proto));
- }
- }
-
- /* Verify dependencies. */
- strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n);
- file->deps = upb_malloc(alloc, sizeof(*file->deps) * n) ;
- CHK_OOM(n == 0 || file->deps);
-
- for (i = 0; i < n; i++) {
- upb_strview dep_name = strs[i];
- upb_value v;
- if (!upb_strtable_lookup2(&ctx->symtab->files, dep_name.data,
- dep_name.size, &v)) {
- upb_status_seterrf(ctx->status,
- "Depends on file '" UPB_STRVIEW_FORMAT
- "', but it has not been loaded",
- UPB_STRVIEW_ARGS(dep_name));
- return false;
- }
- file->deps[i] = upb_value_getconstptr(v);
- }
-
- /* Create messages. */
- msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
- for (i = 0; i < n; i++) {
- CHK(create_msgdef(ctx, file->package, msgs[i]));
- }
-
- /* Create enums. */
- enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
- for (i = 0; i < n; i++) {
- CHK(create_enumdef(ctx, file->package, enums[i]));
- }
-
- /* Create extensions. */
- exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n);
- file->exts = upb_malloc(alloc, sizeof(*file->exts) * n);
- CHK_OOM(n == 0 || file->exts);
- for (i = 0; i < n; i++) {
- CHK(create_fielddef(ctx, file->package, NULL, exts[i]));
- }
-
- /* Now that all names are in the table, build layouts and resolve refs. */
- for (i = 0; i < file->ext_count; i++) {
- CHK(resolve_fielddef(ctx, file->package, (upb_fielddef*)&file->exts[i]));
- }
-
- for (i = 0; i < file->msg_count; i++) {
- const upb_msgdef *m = &file->msgs[i];
- int j;
- for (j = 0; j < m->field_count; j++) {
- CHK(resolve_fielddef(ctx, m->full_name, (upb_fielddef*)&m->fields[j]));
- }
- }
-
- if (!ctx->layouts) {
- for (i = 0; i < file->msg_count; i++) {
- const upb_msgdef *m = &file->msgs[i];
- make_layout(ctx->symtab, m);
- }
- }
-
- return true;
- }
-
-static bool upb_symtab_addtotabs(upb_symtab *s, symtab_addctx *ctx,
- upb_status *status) {
- const upb_filedef *file = ctx->file;
- upb_alloc *alloc = upb_arena_alloc(s->arena);
- upb_strtable_iter iter;
-
- CHK_OOM(upb_strtable_insert3(&s->files, file->name, strlen(file->name),
- upb_value_constptr(file), alloc));
-
- upb_strtable_begin(&iter, ctx->addtab);
- for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
- upb_strview key = upb_strtable_iter_key(&iter);
- upb_value value = upb_strtable_iter_value(&iter);
- CHK_OOM(upb_strtable_insert3(&s->syms, key.data, key.size, value, alloc));
- }
-
- return true;
-}
-
-/* upb_filedef ****************************************************************/
-
-const char *upb_filedef_name(const upb_filedef *f) {
- return f->name;
-}
-
-const char *upb_filedef_package(const upb_filedef *f) {
- return f->package;
-}
-
-const char *upb_filedef_phpprefix(const upb_filedef *f) {
- return f->phpprefix;
-}
-
-const char *upb_filedef_phpnamespace(const upb_filedef *f) {
- return f->phpnamespace;
-}
-
-upb_syntax_t upb_filedef_syntax(const upb_filedef *f) {
- return f->syntax;
-}
-
-int upb_filedef_msgcount(const upb_filedef *f) {
- return f->msg_count;
-}
-
-int upb_filedef_depcount(const upb_filedef *f) {
- return f->dep_count;
-}
-
-int upb_filedef_enumcount(const upb_filedef *f) {
- return f->enum_count;
-}
-
-const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i) {
- return i < 0 || i >= f->dep_count ? NULL : f->deps[i];
-}
-
-const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i) {
- return i < 0 || i >= f->msg_count ? NULL : &f->msgs[i];
-}
-
-const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i) {
- return i < 0 || i >= f->enum_count ? NULL : &f->enums[i];
-}
-
-void upb_symtab_free(upb_symtab *s) {
- upb_arena_free(s->arena);
- upb_gfree(s);
-}
-
-upb_symtab *upb_symtab_new(void) {
- upb_symtab *s = upb_gmalloc(sizeof(*s));
- upb_alloc *alloc;
-
- if (!s) {
- return NULL;
- }
-
- s->arena = upb_arena_new();
- alloc = upb_arena_alloc(s->arena);
-
- if (!upb_strtable_init2(&s->syms, UPB_CTYPE_CONSTPTR, alloc) ||
- !upb_strtable_init2(&s->files, UPB_CTYPE_CONSTPTR, alloc)) {
- upb_arena_free(s->arena);
- upb_gfree(s);
- s = NULL;
- }
- return s;
-}
-
-const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) {
- upb_value v;
- return upb_strtable_lookup(&s->syms, sym, &v) ?
- unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
-}
-
-const upb_msgdef *upb_symtab_lookupmsg2(const upb_symtab *s, const char *sym,
- size_t len) {
- upb_value v;
- return upb_strtable_lookup2(&s->syms, sym, len, &v) ?
- unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
-}
-
-const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) {
- upb_value v;
- return upb_strtable_lookup(&s->syms, sym, &v) ?
- unpack_def(v, UPB_DEFTYPE_ENUM) : NULL;
-}
-
-const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name) {
- upb_value v;
- return upb_strtable_lookup(&s->files, name, &v) ? upb_value_getconstptr(v)
- : NULL;
-}
-
-const upb_filedef *upb_symtab_lookupfile2(
- const upb_symtab *s, const char *name, size_t len) {
- upb_value v;
- return upb_strtable_lookup2(&s->files, name, len, &v) ?
- upb_value_getconstptr(v) : NULL;
-}
-
-int upb_symtab_filecount(const upb_symtab *s) {
- return (int)upb_strtable_count(&s->files);
-}
-
-static const upb_filedef *_upb_symtab_addfile(
- upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
- const upb_msglayout **layouts, upb_status *status) {
- upb_arena *tmparena = upb_arena_new();
- upb_strtable addtab;
- upb_alloc *alloc = upb_arena_alloc(s->arena);
- upb_filedef *file = upb_malloc(alloc, sizeof(*file));
- bool ok;
- symtab_addctx ctx;
-
- ctx.file = file;
- ctx.symtab = s;
- ctx.alloc = alloc;
- ctx.tmp = upb_arena_alloc(tmparena);
- ctx.addtab = &addtab;
- ctx.layouts = layouts;
- ctx.status = status;
-
- ok = file &&
- upb_strtable_init2(&addtab, UPB_CTYPE_CONSTPTR, ctx.tmp) &&
- build_filedef(&ctx, file, file_proto) &&
- upb_symtab_addtotabs(s, &ctx, status);
-
- upb_arena_free(tmparena);
- return ok ? file : NULL;
-}
-
-const upb_filedef *upb_symtab_addfile(
- upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
- upb_status *status) {
- return _upb_symtab_addfile(s, file_proto, NULL, status);
-}
-
-/* Include here since we want most of this file to be stdio-free. */
-#include
-
-bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) {
- /* Since this function should never fail (it would indicate a bug in upb) we
- * print errors to stderr instead of returning error status to the user. */
- upb_def_init **deps = init->deps;
- google_protobuf_FileDescriptorProto *file;
- upb_arena *arena;
- upb_status status;
-
- upb_status_clear(&status);
-
- if (upb_strtable_lookup(&s->files, init->filename, NULL)) {
- return true;
- }
-
- arena = upb_arena_new();
-
- for (; *deps; deps++) {
- if (!_upb_symtab_loaddefinit(s, *deps)) goto err;
- }
-
- file = google_protobuf_FileDescriptorProto_parse(
- init->descriptor.data, init->descriptor.size, arena);
-
- if (!file) {
- upb_status_seterrf(
- &status,
- "Failed to parse compiled-in descriptor for file '%s'. This should "
- "never happen.",
- init->filename);
- goto err;
- }
-
- if (!_upb_symtab_addfile(s, file, init->layouts, &status)) goto err;
-
- upb_arena_free(arena);
- return true;
-
-err:
- fprintf(stderr, "Error loading compiled-in descriptor: %s\n",
- upb_status_errmsg(&status));
- upb_arena_free(arena);
- return false;
-}
-
-#undef CHK
-#undef CHK_OOM
-
-
-#include
-
-
-static char field_size[] = {
- 0,/* 0 */
- 8, /* UPB_DESCRIPTOR_TYPE_DOUBLE */
- 4, /* UPB_DESCRIPTOR_TYPE_FLOAT */
- 8, /* UPB_DESCRIPTOR_TYPE_INT64 */
- 8, /* UPB_DESCRIPTOR_TYPE_UINT64 */
- 4, /* UPB_DESCRIPTOR_TYPE_INT32 */
- 8, /* UPB_DESCRIPTOR_TYPE_FIXED64 */
- 4, /* UPB_DESCRIPTOR_TYPE_FIXED32 */
- 1, /* UPB_DESCRIPTOR_TYPE_BOOL */
- sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_STRING */
- sizeof(void*), /* UPB_DESCRIPTOR_TYPE_GROUP */
- sizeof(void*), /* UPB_DESCRIPTOR_TYPE_MESSAGE */
- sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_BYTES */
- 4, /* UPB_DESCRIPTOR_TYPE_UINT32 */
- 4, /* UPB_DESCRIPTOR_TYPE_ENUM */
- 4, /* UPB_DESCRIPTOR_TYPE_SFIXED32 */
- 8, /* UPB_DESCRIPTOR_TYPE_SFIXED64 */
- 4, /* UPB_DESCRIPTOR_TYPE_SINT32 */
- 8, /* UPB_DESCRIPTOR_TYPE_SINT64 */
-};
-
-/* Strings/bytes are special-cased in maps. */
-static char _upb_fieldtype_to_mapsize[12] = {
- 0,
- 1, /* UPB_TYPE_BOOL */
- 4, /* UPB_TYPE_FLOAT */
- 4, /* UPB_TYPE_INT32 */
- 4, /* UPB_TYPE_UINT32 */
- 4, /* UPB_TYPE_ENUM */
- sizeof(void*), /* UPB_TYPE_MESSAGE */
- 8, /* UPB_TYPE_DOUBLE */
- 8, /* UPB_TYPE_INT64 */
- 8, /* UPB_TYPE_UINT64 */
- 0, /* UPB_TYPE_STRING */
- 0, /* UPB_TYPE_BYTES */
-};
-
-/** upb_msg *******************************************************************/
-
-upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a) {
- return _upb_msg_new(upb_msgdef_layout(m), a);
-}
-
-static bool in_oneof(const upb_msglayout_field *field) {
- return field->presence < 0;
-}
-
-static uint32_t *oneofcase(const upb_msg *msg,
- const upb_msglayout_field *field) {
- UPB_ASSERT(in_oneof(field));
- return UPB_PTR_AT(msg, -field->presence, uint32_t);
-}
-
-static upb_msgval _upb_msg_getraw(const upb_msg *msg, const upb_fielddef *f) {
- const upb_msglayout_field *field = upb_fielddef_layout(f);
- const char *mem = UPB_PTR_AT(msg, field->offset, char);
- upb_msgval val = {0};
- int size = upb_fielddef_isseq(f) ? sizeof(void *)
- : field_size[field->descriptortype];
- memcpy(&val, mem, size);
- return val;
-}
-
-bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f) {
- const upb_msglayout_field *field = upb_fielddef_layout(f);
- if (in_oneof(field)) {
- return *oneofcase(msg, field) == field->number;
- } else if (field->presence > 0) {
- uint32_t hasbit = field->presence;
- return *UPB_PTR_AT(msg, hasbit / 8, uint8_t) & (1 << (hasbit % 8));
- } else {
- UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
- field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP);
- return _upb_msg_getraw(msg, f).msg_val != NULL;
- }
-}
-
-bool upb_msg_hasoneof(const upb_msg *msg, const upb_oneofdef *o) {
- upb_oneof_iter i;
- const upb_fielddef *f;
- const upb_msglayout_field *field;
-
- upb_oneof_begin(&i, o);
- if (upb_oneof_done(&i)) return false;
- f = upb_oneof_iter_field(&i);
- field = upb_fielddef_layout(f);
- return *oneofcase(msg, field) != 0;
-}
-
-upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f) {
- if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) {
- return _upb_msg_getraw(msg, f);
- } else {
- /* TODO(haberman): change upb_fielddef to not require this switch(). */
- upb_msgval val = {0};
- switch (upb_fielddef_type(f)) {
- case UPB_TYPE_INT32:
- case UPB_TYPE_ENUM:
- val.int32_val = upb_fielddef_defaultint32(f);
- break;
- case UPB_TYPE_INT64:
- val.int64_val = upb_fielddef_defaultint64(f);
- break;
- case UPB_TYPE_UINT32:
- val.uint32_val = upb_fielddef_defaultuint32(f);
- break;
- case UPB_TYPE_UINT64:
- val.uint64_val = upb_fielddef_defaultuint64(f);
- break;
- case UPB_TYPE_FLOAT:
- val.float_val = upb_fielddef_defaultfloat(f);
- break;
- case UPB_TYPE_DOUBLE:
- val.double_val = upb_fielddef_defaultdouble(f);
- break;
- case UPB_TYPE_BOOL:
- val.double_val = upb_fielddef_defaultbool(f);
- break;
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES:
- val.str_val.data = upb_fielddef_defaultstr(f, &val.str_val.size);
- break;
- case UPB_TYPE_MESSAGE:
- val.msg_val = NULL;
- break;
- }
- return val;
- }
-}
-
-upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f,
- upb_arena *a) {
- const upb_msglayout_field *field = upb_fielddef_layout(f);
- upb_mutmsgval ret;
- char *mem = UPB_PTR_AT(msg, field->offset, char);
- bool wrong_oneof = in_oneof(field) && *oneofcase(msg, field) != field->number;
-
- memcpy(&ret, mem, sizeof(void*));
-
- if (a && (!ret.msg || wrong_oneof)) {
- if (upb_fielddef_ismap(f)) {
- const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
- const upb_fielddef *key = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY);
- const upb_fielddef *value = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE);
- ret.map = upb_map_new(a, upb_fielddef_type(key), upb_fielddef_type(value));
- } else if (upb_fielddef_isseq(f)) {
- ret.array = upb_array_new(a, upb_fielddef_type(f));
- } else {
- UPB_ASSERT(upb_fielddef_issubmsg(f));
- ret.msg = upb_msg_new(upb_fielddef_msgsubdef(f), a);
- }
-
- memcpy(mem, &ret, sizeof(void*));
-
- if (wrong_oneof) {
- *oneofcase(msg, field) = field->number;
- }
- }
- return ret;
-}
-
-void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
- upb_arena *a) {
- const upb_msglayout_field *field = upb_fielddef_layout(f);
- char *mem = UPB_PTR_AT(msg, field->offset, char);
- int size = upb_fielddef_isseq(f) ? sizeof(void *)
- : field_size[field->descriptortype];
- memcpy(mem, &val, size);
- if (in_oneof(field)) {
- *oneofcase(msg, field) = field->number;
- }
-}
-
-bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
- const upb_symtab *ext_pool, const upb_fielddef **out_f,
- upb_msgval *out_val, size_t *iter) {
- size_t i = *iter;
- const upb_msgval zero = {0};
- const upb_fielddef *f;
- while ((f = _upb_msgdef_field(m, (int)++i)) != NULL) {
- upb_msgval val = _upb_msg_getraw(msg, f);
-
- /* Skip field if unset or empty. */
- if (upb_fielddef_haspresence(f)) {
- if (!upb_msg_has(msg, f)) continue;
- } else {
- upb_msgval test = val;
- if (upb_fielddef_isstring(f) && !upb_fielddef_isseq(f)) {
- /* Clear string pointer, only size matters (ptr could be non-NULL). */
- test.str_val.data = NULL;
- }
- /* Continue if NULL or 0. */
- if (memcmp(&test, &zero, sizeof(test)) == 0) continue;
-
- /* Continue on empty array or map. */
- if (upb_fielddef_ismap(f)) {
- if (upb_map_size(test.map_val) == 0) continue;
- } else if (upb_fielddef_isseq(f)) {
- if (upb_array_size(test.array_val) == 0) continue;
- }
- }
-
- *out_val = val;
- *out_f = f;
- *iter = i;
- return true;
- }
- *iter = i;
- return false;
-}
-
-/** upb_array *****************************************************************/
-
-upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type) {
- return _upb_array_new(a, type);
-}
-
-size_t upb_array_size(const upb_array *arr) {
- return arr->len;
-}
-
-upb_msgval upb_array_get(const upb_array *arr, size_t i) {
- upb_msgval ret;
- const char* data = _upb_array_constptr(arr);
- int lg2 = arr->data & 7;
- UPB_ASSERT(i < arr->len);
- memcpy(&ret, data + (i << lg2), 1 << lg2);
- return ret;
-}
-
-void upb_array_set(upb_array *arr, size_t i, upb_msgval val) {
- char* data = _upb_array_ptr(arr);
- int lg2 = arr->data & 7;
- UPB_ASSERT(i < arr->len);
- memcpy(data + (i << lg2), &val, 1 << lg2);
-}
-
-bool upb_array_append(upb_array *arr, upb_msgval val, upb_arena *arena) {
- if (!_upb_array_realloc(arr, arr->len + 1, arena)) {
- return false;
- }
- arr->len++;
- upb_array_set(arr, arr->len - 1, val);
- return true;
-}
-
-/* Resizes the array to the given size, reallocating if necessary, and returns a
- * pointer to the new array elements. */
-bool upb_array_resize(upb_array *arr, size_t size, upb_arena *arena) {
- return _upb_array_realloc(arr, size, arena);
-}
-
-/** upb_map *******************************************************************/
-
-upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type,
- upb_fieldtype_t value_type) {
- return _upb_map_new(a, _upb_fieldtype_to_mapsize[key_type],
- _upb_fieldtype_to_mapsize[value_type]);
-}
-
-size_t upb_map_size(const upb_map *map) {
- return _upb_map_size(map);
-}
-
-bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) {
- return _upb_map_get(map, &key, map->key_size, val, map->val_size);
-}
-
-bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
- upb_arena *arena) {
- return _upb_map_set(map, &key, map->key_size, &val, map->val_size, arena);
-}
-
-bool upb_map_delete(upb_map *map, upb_msgval key) {
- return _upb_map_delete(map, &key, map->key_size);
-}
-
-bool upb_mapiter_next(const upb_map *map, size_t *iter) {
- return _upb_map_next(map, iter);
-}
-
-/* Returns the key and value for this entry of the map. */
-upb_msgval upb_mapiter_key(const upb_map *map, size_t iter) {
- upb_strtable_iter i;
- upb_msgval ret;
- i.t = &map->table;
- i.index = iter;
- _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
- return ret;
-}
-
-upb_msgval upb_mapiter_value(const upb_map *map, size_t iter) {
- upb_strtable_iter i;
- upb_msgval ret;
- i.t = &map->table;
- i.index = iter;
- _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size);
- return ret;
-}
-
-/* void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); */
-/*
-** TODO(haberman): it's unclear whether a lot of the consistency checks should
-** UPB_ASSERT() or return false.
-*/
-
-
-#include
-
-
-
-struct upb_handlers {
- upb_handlercache *cache;
- const upb_msgdef *msg;
- const upb_handlers **sub;
- const void *top_closure_type;
- upb_handlers_tabent table[1]; /* Dynamically-sized field handler array. */
-};
-
-static void *upb_calloc(upb_arena *arena, size_t size) {
- void *mem = upb_malloc(upb_arena_alloc(arena), size);
- if (mem) {
- memset(mem, 0, size);
- }
- return mem;
-}
-
-/* Defined for the sole purpose of having a unique pointer value for
- * UPB_NO_CLOSURE. */
-char _upb_noclosure;
-
-/* Given a selector for a STARTSUBMSG handler, resolves to a pointer to the
- * subhandlers for this submessage field. */
-#define SUBH(h, selector) (h->sub[selector])
-
-/* The selector for a submessage field is the field index. */
-#define SUBH_F(h, f) SUBH(h, upb_fielddef_index(f))
-
-static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f,
- upb_handlertype_t type) {
- upb_selector_t sel;
- bool ok;
-
- ok = upb_handlers_getselector(f, type, &sel);
-
- UPB_ASSERT(upb_handlers_msgdef(h) == upb_fielddef_containingtype(f));
- UPB_ASSERT(ok);
-
- return sel;
-}
-
-static upb_selector_t handlers_getsel(upb_handlers *h, const upb_fielddef *f,
- upb_handlertype_t type) {
- int32_t sel = trygetsel(h, f, type);
- UPB_ASSERT(sel >= 0);
- return sel;
-}
-
-static const void **returntype(upb_handlers *h, const upb_fielddef *f,
- upb_handlertype_t type) {
- return &h->table[handlers_getsel(h, f, type)].attr.return_closure_type;
-}
-
-static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f,
- upb_handlertype_t type, upb_func *func,
- const upb_handlerattr *attr) {
- upb_handlerattr set_attr = UPB_HANDLERATTR_INIT;
- const void *closure_type;
- const void **context_closure_type;
-
- UPB_ASSERT(!h->table[sel].func);
-
- if (attr) {
- set_attr = *attr;
- }
-
- /* Check that the given closure type matches the closure type that has been
- * established for this context (if any). */
- closure_type = set_attr.closure_type;
-
- if (type == UPB_HANDLER_STRING) {
- context_closure_type = returntype(h, f, UPB_HANDLER_STARTSTR);
- } else if (f && upb_fielddef_isseq(f) &&
- type != UPB_HANDLER_STARTSEQ &&
- type != UPB_HANDLER_ENDSEQ) {
- context_closure_type = returntype(h, f, UPB_HANDLER_STARTSEQ);
- } else {
- context_closure_type = &h->top_closure_type;
- }
-
- if (closure_type && *context_closure_type &&
- closure_type != *context_closure_type) {
- return false;
- }
-
- if (closure_type)
- *context_closure_type = closure_type;
-
- /* If this is a STARTSEQ or STARTSTR handler, check that the returned pointer
- * matches any pre-existing expectations about what type is expected. */
- if (type == UPB_HANDLER_STARTSEQ || type == UPB_HANDLER_STARTSTR) {
- const void *return_type = set_attr.return_closure_type;
- const void *table_return_type = h->table[sel].attr.return_closure_type;
- if (return_type && table_return_type && return_type != table_return_type) {
- return false;
- }
-
- if (table_return_type && !return_type) {
- set_attr.return_closure_type = table_return_type;
- }
- }
-
- h->table[sel].func = (upb_func*)func;
- h->table[sel].attr = set_attr;
- return true;
-}
-
-/* Returns the effective closure type for this handler (which will propagate
- * from outer frames if this frame has no START* handler). Not implemented for
- * UPB_HANDLER_STRING at the moment since this is not needed. Returns NULL is
- * the effective closure type is unspecified (either no handler was registered
- * to specify it or the handler that was registered did not specify the closure
- * type). */
-const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f,
- upb_handlertype_t type) {
- const void *ret;
- upb_selector_t sel;
-
- UPB_ASSERT(type != UPB_HANDLER_STRING);
- ret = h->top_closure_type;
-
- if (upb_fielddef_isseq(f) &&
- type != UPB_HANDLER_STARTSEQ &&
- type != UPB_HANDLER_ENDSEQ &&
- h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)].func) {
- ret = h->table[sel].attr.return_closure_type;
- }
-
- if (type == UPB_HANDLER_STRING &&
- h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSTR)].func) {
- ret = h->table[sel].attr.return_closure_type;
- }
-
- /* The effective type of the submessage; not used yet.
- * if (type == SUBMESSAGE &&
- * h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) {
- * ret = h->table[sel].attr.return_closure_type;
- * } */
-
- return ret;
-}
-
-/* Checks whether the START* handler specified by f & type is missing even
- * though it is required to convert the established type of an outer frame
- * ("closure_type") into the established type of an inner frame (represented in
- * the return closure type of this handler's attr. */
-bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type,
- upb_status *status) {
- const void *closure_type;
- const upb_handlerattr *attr;
- const void *return_closure_type;
-
- upb_selector_t sel = handlers_getsel(h, f, type);
- if (h->table[sel].func) return true;
- closure_type = effective_closure_type(h, f, type);
- attr = &h->table[sel].attr;
- return_closure_type = attr->return_closure_type;
- if (closure_type && return_closure_type &&
- closure_type != return_closure_type) {
- return false;
- }
- return true;
-}
-
-static upb_handlers *upb_handlers_new(const upb_msgdef *md,
- upb_handlercache *cache,
- upb_arena *arena) {
- int extra;
- upb_handlers *h;
-
- extra =
- (int)(sizeof(upb_handlers_tabent) * (upb_msgdef_selectorcount(md) - 1));
- h = upb_calloc(arena, sizeof(*h) + extra);
- if (!h) return NULL;
-
- h->cache = cache;
- h->msg = md;
-
- if (upb_msgdef_submsgfieldcount(md) > 0) {
- size_t bytes = upb_msgdef_submsgfieldcount(md) * sizeof(*h->sub);
- h->sub = upb_calloc(arena, bytes);
- if (!h->sub) return NULL;
- } else {
- h->sub = 0;
- }
-
- /* calloc() above initialized all handlers to NULL. */
- return h;
-}
-
-/* Public interface ***********************************************************/
-
-#define SETTER(name, handlerctype, handlertype) \
- bool upb_handlers_set##name(upb_handlers *h, const upb_fielddef *f, \
- handlerctype func, \
- const upb_handlerattr *attr) { \
- int32_t sel = trygetsel(h, f, handlertype); \
- return doset(h, sel, f, handlertype, (upb_func *)func, attr); \
- }
-
-SETTER(int32, upb_int32_handlerfunc*, UPB_HANDLER_INT32)
-SETTER(int64, upb_int64_handlerfunc*, UPB_HANDLER_INT64)
-SETTER(uint32, upb_uint32_handlerfunc*, UPB_HANDLER_UINT32)
-SETTER(uint64, upb_uint64_handlerfunc*, UPB_HANDLER_UINT64)
-SETTER(float, upb_float_handlerfunc*, UPB_HANDLER_FLOAT)
-SETTER(double, upb_double_handlerfunc*, UPB_HANDLER_DOUBLE)
-SETTER(bool, upb_bool_handlerfunc*, UPB_HANDLER_BOOL)
-SETTER(startstr, upb_startstr_handlerfunc*, UPB_HANDLER_STARTSTR)
-SETTER(string, upb_string_handlerfunc*, UPB_HANDLER_STRING)
-SETTER(endstr, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSTR)
-SETTER(startseq, upb_startfield_handlerfunc*, UPB_HANDLER_STARTSEQ)
-SETTER(startsubmsg, upb_startfield_handlerfunc*, UPB_HANDLER_STARTSUBMSG)
-SETTER(endsubmsg, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSUBMSG)
-SETTER(endseq, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSEQ)
-
-#undef SETTER
-
-bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func,
- const upb_handlerattr *attr) {
- return doset(h, UPB_UNKNOWN_SELECTOR, NULL, UPB_HANDLER_INT32,
- (upb_func *)func, attr);
-}
-
-bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
- const upb_handlerattr *attr) {
- return doset(h, UPB_STARTMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
- (upb_func *)func, attr);
-}
-
-bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
- const upb_handlerattr *attr) {
- return doset(h, UPB_ENDMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
- (upb_func *)func, attr);
-}
-
-bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
- const upb_handlers *sub) {
- UPB_ASSERT(sub);
- UPB_ASSERT(upb_fielddef_issubmsg(f));
- if (SUBH_F(h, f)) return false; /* Can't reset. */
- if (upb_handlers_msgdef(sub) != upb_fielddef_msgsubdef(f)) {
- return false;
- }
- SUBH_F(h, f) = sub;
- return true;
-}
-
-const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
- const upb_fielddef *f) {
- UPB_ASSERT(upb_fielddef_issubmsg(f));
- return SUBH_F(h, f);
-}
-
-upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s,
- const void **handler_data) {
- upb_func *ret = (upb_func *)h->table[s].func;
- if (ret && handler_data) {
- *handler_data = h->table[s].attr.handler_data;
- }
- return ret;
-}
-
-bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t sel,
- upb_handlerattr *attr) {
- if (!upb_handlers_gethandler(h, sel, NULL))
- return false;
- *attr = h->table[sel].attr;
- return true;
-}
-
-const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
- upb_selector_t sel) {
- /* STARTSUBMSG selector in sel is the field's selector base. */
- return SUBH(h, sel - UPB_STATIC_SELECTOR_COUNT);
-}
-
-const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; }
-
-bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) {
- return upb_handlercache_addcleanup(h->cache, p, func);
-}
-
-upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) {
- switch (upb_fielddef_type(f)) {
- case UPB_TYPE_INT32:
- case UPB_TYPE_ENUM: return UPB_HANDLER_INT32;
- case UPB_TYPE_INT64: return UPB_HANDLER_INT64;
- case UPB_TYPE_UINT32: return UPB_HANDLER_UINT32;
- case UPB_TYPE_UINT64: return UPB_HANDLER_UINT64;
- case UPB_TYPE_FLOAT: return UPB_HANDLER_FLOAT;
- case UPB_TYPE_DOUBLE: return UPB_HANDLER_DOUBLE;
- case UPB_TYPE_BOOL: return UPB_HANDLER_BOOL;
- default: UPB_ASSERT(false); return -1; /* Invalid input. */
- }
-}
-
-bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
- upb_selector_t *s) {
- uint32_t selector_base = upb_fielddef_selectorbase(f);
- switch (type) {
- case UPB_HANDLER_INT32:
- case UPB_HANDLER_INT64:
- case UPB_HANDLER_UINT32:
- case UPB_HANDLER_UINT64:
- case UPB_HANDLER_FLOAT:
- case UPB_HANDLER_DOUBLE:
- case UPB_HANDLER_BOOL:
- if (!upb_fielddef_isprimitive(f) ||
- upb_handlers_getprimitivehandlertype(f) != type)
- return false;
- *s = selector_base;
- break;
- case UPB_HANDLER_STRING:
- if (upb_fielddef_isstring(f)) {
- *s = selector_base;
- } else if (upb_fielddef_lazy(f)) {
- *s = selector_base + 3;
- } else {
- return false;
- }
- break;
- case UPB_HANDLER_STARTSTR:
- if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
- *s = selector_base + 1;
- } else {
- return false;
- }
- break;
- case UPB_HANDLER_ENDSTR:
- if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
- *s = selector_base + 2;
- } else {
- return false;
- }
- break;
- case UPB_HANDLER_STARTSEQ:
- if (!upb_fielddef_isseq(f)) return false;
- *s = selector_base - 2;
- break;
- case UPB_HANDLER_ENDSEQ:
- if (!upb_fielddef_isseq(f)) return false;
- *s = selector_base - 1;
- break;
- case UPB_HANDLER_STARTSUBMSG:
- if (!upb_fielddef_issubmsg(f)) return false;
- /* Selectors for STARTSUBMSG are at the beginning of the table so that the
- * selector can also be used as an index into the "sub" array of
- * subhandlers. The indexes for the two into these two tables are the
- * same, except that in the handler table the static selectors come first. */
- *s = upb_fielddef_index(f) + UPB_STATIC_SELECTOR_COUNT;
- break;
- case UPB_HANDLER_ENDSUBMSG:
- if (!upb_fielddef_issubmsg(f)) return false;
- *s = selector_base;
- break;
- }
- UPB_ASSERT((size_t)*s < upb_msgdef_selectorcount(upb_fielddef_containingtype(f)));
- return true;
-}
-
-/* upb_handlercache ***********************************************************/
-
-struct upb_handlercache {
- upb_arena *arena;
- upb_inttable tab; /* maps upb_msgdef* -> upb_handlers*. */
- upb_handlers_callback *callback;
- const void *closure;
-};
-
-const upb_handlers *upb_handlercache_get(upb_handlercache *c,
- const upb_msgdef *md) {
- upb_msg_field_iter i;
- upb_value v;
- upb_handlers *h;
-
- if (upb_inttable_lookupptr(&c->tab, md, &v)) {
- return upb_value_getptr(v);
- }
-
- h = upb_handlers_new(md, c, c->arena);
- v = upb_value_ptr(h);
-
- if (!h) return NULL;
- if (!upb_inttable_insertptr(&c->tab, md, v)) return NULL;
-
- c->callback(c->closure, h);
-
- /* For each submessage field, get or create a handlers object and set it as
- * the subhandlers. */
- for(upb_msg_field_begin(&i, md);
- !upb_msg_field_done(&i);
- upb_msg_field_next(&i)) {
- upb_fielddef *f = upb_msg_iter_field(&i);
-
- if (upb_fielddef_issubmsg(f)) {
- const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
- const upb_handlers *sub_mh = upb_handlercache_get(c, subdef);
-
- if (!sub_mh) return NULL;
-
- upb_handlers_setsubhandlers(h, f, sub_mh);
- }
- }
-
- return h;
-}
-
-
-upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback,
- const void *closure) {
- upb_handlercache *cache = upb_gmalloc(sizeof(*cache));
-
- if (!cache) return NULL;
-
- cache->arena = upb_arena_new();
-
- cache->callback = callback;
- cache->closure = closure;
-
- if (!upb_inttable_init(&cache->tab, UPB_CTYPE_PTR)) goto oom;
-
- return cache;
-
-oom:
- upb_gfree(cache);
- return NULL;
-}
-
-void upb_handlercache_free(upb_handlercache *cache) {
- upb_inttable_uninit(&cache->tab);
- upb_arena_free(cache->arena);
- upb_gfree(cache);
-}
-
-bool upb_handlercache_addcleanup(upb_handlercache *c, void *p,
- upb_handlerfree *func) {
- return upb_arena_addcleanup(c->arena, p, func);
-}
-
-/* upb_byteshandler ***********************************************************/
-
-bool upb_byteshandler_setstartstr(upb_byteshandler *h,
- upb_startstr_handlerfunc *func, void *d) {
- h->table[UPB_STARTSTR_SELECTOR].func = (upb_func*)func;
- h->table[UPB_STARTSTR_SELECTOR].attr.handler_data = d;
- return true;
-}
-
-bool upb_byteshandler_setstring(upb_byteshandler *h,
- upb_string_handlerfunc *func, void *d) {
- h->table[UPB_STRING_SELECTOR].func = (upb_func*)func;
- h->table[UPB_STRING_SELECTOR].attr.handler_data = d;
- return true;
-}
-
-bool upb_byteshandler_setendstr(upb_byteshandler *h,
- upb_endfield_handlerfunc *func, void *d) {
- h->table[UPB_ENDSTR_SELECTOR].func = (upb_func*)func;
- h->table[UPB_ENDSTR_SELECTOR].attr.handler_data = d;
- return true;
-}
-
-/** Handlers for upb_msg ******************************************************/
-
-typedef struct {
- size_t offset;
- int32_t hasbit;
-} upb_msg_handlerdata;
-
-/* Fallback implementation if the handler is not specialized by the producer. */
-#define MSG_WRITER(type, ctype) \
- bool upb_msg_set ## type (void *c, const void *hd, ctype val) { \
- uint8_t *m = c; \
- const upb_msg_handlerdata *d = hd; \
- if (d->hasbit > 0) \
- *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8); \
- *(ctype*)&m[d->offset] = val; \
- return true; \
- } \
-
-MSG_WRITER(double, double)
-MSG_WRITER(float, float)
-MSG_WRITER(int32, int32_t)
-MSG_WRITER(int64, int64_t)
-MSG_WRITER(uint32, uint32_t)
-MSG_WRITER(uint64, uint64_t)
-MSG_WRITER(bool, bool)
-
-bool upb_msg_setscalarhandler(upb_handlers *h, const upb_fielddef *f,
- size_t offset, int32_t hasbit) {
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
- bool ok;
-
- upb_msg_handlerdata *d = upb_gmalloc(sizeof(*d));
- if (!d) return false;
- d->offset = offset;
- d->hasbit = hasbit;
-
- attr.handler_data = d;
- attr.alwaysok = true;
- upb_handlers_addcleanup(h, d, upb_gfree);
-
-#define TYPE(u, l) \
- case UPB_TYPE_##u: \
- ok = upb_handlers_set##l(h, f, upb_msg_set##l, &attr); break;
-
- ok = false;
-
- switch (upb_fielddef_type(f)) {
- TYPE(INT64, int64);
- TYPE(INT32, int32);
- TYPE(ENUM, int32);
- TYPE(UINT64, uint64);
- TYPE(UINT32, uint32);
- TYPE(DOUBLE, double);
- TYPE(FLOAT, float);
- TYPE(BOOL, bool);
- default: UPB_ASSERT(false); break;
- }
-#undef TYPE
-
- return ok;
-}
-
-bool upb_msg_getscalarhandlerdata(const upb_handlers *h,
- upb_selector_t s,
- upb_fieldtype_t *type,
- size_t *offset,
- int32_t *hasbit) {
- const upb_msg_handlerdata *d;
- const void *p;
- upb_func *f = upb_handlers_gethandler(h, s, &p);
-
- if ((upb_int64_handlerfunc*)f == upb_msg_setint64) {
- *type = UPB_TYPE_INT64;
- } else if ((upb_int32_handlerfunc*)f == upb_msg_setint32) {
- *type = UPB_TYPE_INT32;
- } else if ((upb_uint64_handlerfunc*)f == upb_msg_setuint64) {
- *type = UPB_TYPE_UINT64;
- } else if ((upb_uint32_handlerfunc*)f == upb_msg_setuint32) {
- *type = UPB_TYPE_UINT32;
- } else if ((upb_double_handlerfunc*)f == upb_msg_setdouble) {
- *type = UPB_TYPE_DOUBLE;
- } else if ((upb_float_handlerfunc*)f == upb_msg_setfloat) {
- *type = UPB_TYPE_FLOAT;
- } else if ((upb_bool_handlerfunc*)f == upb_msg_setbool) {
- *type = UPB_TYPE_BOOL;
- } else {
- return false;
- }
-
- d = p;
- *offset = d->offset;
- *hasbit = d->hasbit;
- return true;
-}
-
-
-bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink) {
- void *subc;
- bool ret;
- upb_bufhandle handle = UPB_BUFHANDLE_INIT;
- handle.buf = buf;
- ret = upb_bytessink_start(sink, len, &subc);
- if (ret && len != 0) {
- ret = (upb_bytessink_putbuf(sink, subc, buf, len, &handle) >= len);
- }
- if (ret) {
- ret = upb_bytessink_end(sink);
- }
- return ret;
-}
-
-
-#ifdef UPB_MSVC_VSNPRINTF
-/* Visual C++ earlier than 2015 doesn't have standard C99 snprintf and
- * vsnprintf. To support them, missing functions are manually implemented
- * using the existing secure functions. */
-int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg) {
- if (!s) {
- return _vscprintf(format, arg);
- }
- int ret = _vsnprintf_s(s, n, _TRUNCATE, format, arg);
- if (ret < 0) {
- ret = _vscprintf(format, arg);
- }
- return ret;
-}
-
-int msvc_snprintf(char* s, size_t n, const char* format, ...) {
- va_list arg;
- va_start(arg, format);
- int ret = msvc_vsnprintf(s, n, format, arg);
- va_end(arg);
- return ret;
-}
-#endif
-/*
-** protobuf decoder bytecode compiler
-**
-** Code to compile a upb::Handlers into bytecode for decoding a protobuf
-** according to that specific schema and destination handlers.
-**
-** Bytecode definition is in decoder.int.h.
-*/
-
-#include
-
-#ifdef UPB_DUMP_BYTECODE
-#include
-#endif
-
-
-#define MAXLABEL 5
-#define EMPTYLABEL -1
-
-/* upb_pbdecodermethod ********************************************************/
-
-static void freemethod(upb_pbdecodermethod *method) {
- upb_inttable_uninit(&method->dispatch);
- upb_gfree(method);
-}
-
-static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers,
- mgroup *group) {
- upb_pbdecodermethod *ret = upb_gmalloc(sizeof(*ret));
- upb_byteshandler_init(&ret->input_handler_);
-
- ret->group = group;
- ret->dest_handlers_ = dest_handlers;
- upb_inttable_init(&ret->dispatch, UPB_CTYPE_UINT64);
-
- return ret;
-}
-
-const upb_handlers *upb_pbdecodermethod_desthandlers(
- const upb_pbdecodermethod *m) {
- return m->dest_handlers_;
-}
-
-const upb_byteshandler *upb_pbdecodermethod_inputhandler(
- const upb_pbdecodermethod *m) {
- return &m->input_handler_;
-}
-
-bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m) {
- return m->is_native_;
-}
-
-
-/* mgroup *********************************************************************/
-
-static void freegroup(mgroup *g) {
- upb_inttable_iter i;
-
- upb_inttable_begin(&i, &g->methods);
- for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- freemethod(upb_value_getptr(upb_inttable_iter_value(&i)));
- }
-
- upb_inttable_uninit(&g->methods);
- upb_gfree(g->bytecode);
- upb_gfree(g);
-}
-
-mgroup *newgroup(void) {
- mgroup *g = upb_gmalloc(sizeof(*g));
- upb_inttable_init(&g->methods, UPB_CTYPE_PTR);
- g->bytecode = NULL;
- g->bytecode_end = NULL;
- return g;
-}
-
-
-/* bytecode compiler **********************************************************/
-
-/* Data used only at compilation time. */
-typedef struct {
- mgroup *group;
-
- uint32_t *pc;
- int fwd_labels[MAXLABEL];
- int back_labels[MAXLABEL];
-
- /* For fields marked "lazy", parse them lazily or eagerly? */
- bool lazy;
-} compiler;
-
-static compiler *newcompiler(mgroup *group, bool lazy) {
- compiler *ret = upb_gmalloc(sizeof(*ret));
- int i;
-
- ret->group = group;
- ret->lazy = lazy;
- for (i = 0; i < MAXLABEL; i++) {
- ret->fwd_labels[i] = EMPTYLABEL;
- ret->back_labels[i] = EMPTYLABEL;
- }
- return ret;
-}
-
-static void freecompiler(compiler *c) {
- upb_gfree(c);
-}
-
-const size_t ptr_words = sizeof(void*) / sizeof(uint32_t);
-
-/* How many words an instruction is. */
-static int instruction_len(uint32_t instr) {
- switch (getop(instr)) {
- case OP_SETDISPATCH: return 1 + ptr_words;
- case OP_TAGN: return 3;
- case OP_SETBIGGROUPNUM: return 2;
- default: return 1;
- }
-}
-
-bool op_has_longofs(int32_t instruction) {
- switch (getop(instruction)) {
- case OP_CALL:
- case OP_BRANCH:
- case OP_CHECKDELIM:
- return true;
- /* The "tag" instructions only have 8 bytes available for the jump target,
- * but that is ok because these opcodes only require short jumps. */
- case OP_TAG1:
- case OP_TAG2:
- case OP_TAGN:
- return false;
- default:
- UPB_ASSERT(false);
- return false;
- }
-}
-
-static int32_t getofs(uint32_t instruction) {
- if (op_has_longofs(instruction)) {
- return (int32_t)instruction >> 8;
- } else {
- return (int8_t)(instruction >> 8);
- }
-}
-
-static void setofs(uint32_t *instruction, int32_t ofs) {
- if (op_has_longofs(*instruction)) {
- *instruction = getop(*instruction) | (uint32_t)ofs << 8;
- } else {
- *instruction = (*instruction & ~0xff00) | ((ofs & 0xff) << 8);
- }
- UPB_ASSERT(getofs(*instruction) == ofs); /* Would fail in cases of overflow. */
-}
-
-static uint32_t pcofs(compiler *c) {
- return (uint32_t)(c->pc - c->group->bytecode);
-}
-
-/* Defines a local label at the current PC location. All previous forward
- * references are updated to point to this location. The location is noted
- * for any future backward references. */
-static void label(compiler *c, unsigned int label) {
- int val;
- uint32_t *codep;
-
- UPB_ASSERT(label < MAXLABEL);
- val = c->fwd_labels[label];
- codep = (val == EMPTYLABEL) ? NULL : c->group->bytecode + val;
- while (codep) {
- int ofs = getofs(*codep);
- setofs(codep, (int32_t)(c->pc - codep - instruction_len(*codep)));
- codep = ofs ? codep + ofs : NULL;
- }
- c->fwd_labels[label] = EMPTYLABEL;
- c->back_labels[label] = pcofs(c);
-}
-
-/* Creates a reference to a numbered label; either a forward reference
- * (positive arg) or backward reference (negative arg). For forward references
- * the value returned now is actually a "next" pointer into a linked list of all
- * instructions that use this label and will be patched later when the label is
- * defined with label().
- *
- * The returned value is the offset that should be written into the instruction.
- */
-static int32_t labelref(compiler *c, int label) {
- UPB_ASSERT(label < MAXLABEL);
- if (label == LABEL_DISPATCH) {
- /* No resolving required. */
- return 0;
- } else if (label < 0) {
- /* Backward local label. Relative to the next instruction. */
- uint32_t from = (uint32_t)((c->pc + 1) - c->group->bytecode);
- return c->back_labels[-label] - from;
- } else {
- /* Forward local label: prepend to (possibly-empty) linked list. */
- int *lptr = &c->fwd_labels[label];
- int32_t ret = (*lptr == EMPTYLABEL) ? 0 : *lptr - pcofs(c);
- *lptr = pcofs(c);
- return ret;
- }
-}
-
-static void put32(compiler *c, uint32_t v) {
- mgroup *g = c->group;
- if (c->pc == g->bytecode_end) {
- int ofs = pcofs(c);
- size_t oldsize = g->bytecode_end - g->bytecode;
- size_t newsize = UPB_MAX(oldsize * 2, 64);
- /* TODO(haberman): handle OOM. */
- g->bytecode = upb_grealloc(g->bytecode, oldsize * sizeof(uint32_t),
- newsize * sizeof(uint32_t));
- g->bytecode_end = g->bytecode + newsize;
- c->pc = g->bytecode + ofs;
- }
- *c->pc++ = v;
-}
-
-static void putop(compiler *c, int op, ...) {
- va_list ap;
- va_start(ap, op);
-
- switch (op) {
- case OP_SETDISPATCH: {
- uintptr_t ptr = (uintptr_t)va_arg(ap, void*);
- put32(c, OP_SETDISPATCH);
- put32(c, (uint32_t)ptr);
- if (sizeof(uintptr_t) > sizeof(uint32_t))
- put32(c, (uint64_t)ptr >> 32);
- break;
- }
- case OP_STARTMSG:
- case OP_ENDMSG:
- case OP_PUSHLENDELIM:
- case OP_POP:
- case OP_SETDELIM:
- case OP_HALT:
- case OP_RET:
- case OP_DISPATCH:
- put32(c, op);
- break;
- case OP_PARSE_DOUBLE:
- case OP_PARSE_FLOAT:
- case OP_PARSE_INT64:
- case OP_PARSE_UINT64:
- case OP_PARSE_INT32:
- case OP_PARSE_FIXED64:
- case OP_PARSE_FIXED32:
- case OP_PARSE_BOOL:
- case OP_PARSE_UINT32:
- case OP_PARSE_SFIXED32:
- case OP_PARSE_SFIXED64:
- case OP_PARSE_SINT32:
- case OP_PARSE_SINT64:
- case OP_STARTSEQ:
- case OP_ENDSEQ:
- case OP_STARTSUBMSG:
- case OP_ENDSUBMSG:
- case OP_STARTSTR:
- case OP_STRING:
- case OP_ENDSTR:
- case OP_PUSHTAGDELIM:
- put32(c, op | va_arg(ap, upb_selector_t) << 8);
- break;
- case OP_SETBIGGROUPNUM:
- put32(c, op);
- put32(c, va_arg(ap, int));
- break;
- case OP_CALL: {
- const upb_pbdecodermethod *method = va_arg(ap, upb_pbdecodermethod *);
- put32(c, op | (method->code_base.ofs - (pcofs(c) + 1)) << 8);
- break;
- }
- case OP_CHECKDELIM:
- case OP_BRANCH: {
- uint32_t instruction = op;
- int label = va_arg(ap, int);
- setofs(&instruction, labelref(c, label));
- put32(c, instruction);
- break;
- }
- case OP_TAG1:
- case OP_TAG2: {
- int label = va_arg(ap, int);
- uint64_t tag = va_arg(ap, uint64_t);
- uint32_t instruction = (uint32_t)(op | (tag << 16));
- UPB_ASSERT(tag <= 0xffff);
- setofs(&instruction, labelref(c, label));
- put32(c, instruction);
- break;
- }
- case OP_TAGN: {
- int label = va_arg(ap, int);
- uint64_t tag = va_arg(ap, uint64_t);
- uint32_t instruction = op | (upb_value_size(tag) << 16);
- setofs(&instruction, labelref(c, label));
- put32(c, instruction);
- put32(c, (uint32_t)tag);
- put32(c, tag >> 32);
- break;
- }
- }
-
- va_end(ap);
-}
-
-#if defined(UPB_DUMP_BYTECODE)
-
-const char *upb_pbdecoder_getopname(unsigned int op) {
-#define QUOTE(x) #x
-#define EXPAND_AND_QUOTE(x) QUOTE(x)
-#define OPNAME(x) OP_##x
-#define OP(x) case OPNAME(x): return EXPAND_AND_QUOTE(OPNAME(x));
-#define T(x) OP(PARSE_##x)
- /* Keep in sync with list in decoder.int.h. */
- switch ((opcode)op) {
- T(DOUBLE) T(FLOAT) T(INT64) T(UINT64) T(INT32) T(FIXED64) T(FIXED32)
- T(BOOL) T(UINT32) T(SFIXED32) T(SFIXED64) T(SINT32) T(SINT64)
- OP(STARTMSG) OP(ENDMSG) OP(STARTSEQ) OP(ENDSEQ) OP(STARTSUBMSG)
- OP(ENDSUBMSG) OP(STARTSTR) OP(STRING) OP(ENDSTR) OP(CALL) OP(RET)
- OP(PUSHLENDELIM) OP(PUSHTAGDELIM) OP(SETDELIM) OP(CHECKDELIM)
- OP(BRANCH) OP(TAG1) OP(TAG2) OP(TAGN) OP(SETDISPATCH) OP(POP)
- OP(SETBIGGROUPNUM) OP(DISPATCH) OP(HALT)
- }
- return "";
-#undef OP
-#undef T
-}
-
-#endif
-
-#ifdef UPB_DUMP_BYTECODE
-
-static void dumpbc(uint32_t *p, uint32_t *end, FILE *f) {
-
- uint32_t *begin = p;
-
- while (p < end) {
- fprintf(f, "%p %8tx", p, p - begin);
- uint32_t instr = *p++;
- uint8_t op = getop(instr);
- fprintf(f, " %s", upb_pbdecoder_getopname(op));
- switch ((opcode)op) {
- case OP_SETDISPATCH: {
- const upb_inttable *dispatch;
- memcpy(&dispatch, p, sizeof(void*));
- p += ptr_words;
- const upb_pbdecodermethod *method =
- (void *)((char *)dispatch -
- offsetof(upb_pbdecodermethod, dispatch));
- fprintf(f, " %s", upb_msgdef_fullname(
- upb_handlers_msgdef(method->dest_handlers_)));
- break;
- }
- case OP_DISPATCH:
- case OP_STARTMSG:
- case OP_ENDMSG:
- case OP_PUSHLENDELIM:
- case OP_POP:
- case OP_SETDELIM:
- case OP_HALT:
- case OP_RET:
- break;
- case OP_PARSE_DOUBLE:
- case OP_PARSE_FLOAT:
- case OP_PARSE_INT64:
- case OP_PARSE_UINT64:
- case OP_PARSE_INT32:
- case OP_PARSE_FIXED64:
- case OP_PARSE_FIXED32:
- case OP_PARSE_BOOL:
- case OP_PARSE_UINT32:
- case OP_PARSE_SFIXED32:
- case OP_PARSE_SFIXED64:
- case OP_PARSE_SINT32:
- case OP_PARSE_SINT64:
- case OP_STARTSEQ:
- case OP_ENDSEQ:
- case OP_STARTSUBMSG:
- case OP_ENDSUBMSG:
- case OP_STARTSTR:
- case OP_STRING:
- case OP_ENDSTR:
- case OP_PUSHTAGDELIM:
- fprintf(f, " %d", instr >> 8);
- break;
- case OP_SETBIGGROUPNUM:
- fprintf(f, " %d", *p++);
- break;
- case OP_CHECKDELIM:
- case OP_CALL:
- case OP_BRANCH:
- fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
- break;
- case OP_TAG1:
- case OP_TAG2: {
- fprintf(f, " tag:0x%x", instr >> 16);
- if (getofs(instr)) {
- fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
- }
- break;
- }
- case OP_TAGN: {
- uint64_t tag = *p++;
- tag |= (uint64_t)*p++ << 32;
- fprintf(f, " tag:0x%llx", (long long)tag);
- fprintf(f, " n:%d", instr >> 16);
- if (getofs(instr)) {
- fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
- }
- break;
- }
- }
- fputs("\n", f);
- }
-}
-
-#endif
-
-static uint64_t get_encoded_tag(const upb_fielddef *f, int wire_type) {
- uint32_t tag = (upb_fielddef_number(f) << 3) | wire_type;
- uint64_t encoded_tag = upb_vencode32(tag);
- /* No tag should be greater than 5 bytes. */
- UPB_ASSERT(encoded_tag <= 0xffffffffff);
- return encoded_tag;
-}
-
-static void putchecktag(compiler *c, const upb_fielddef *f,
- int wire_type, int dest) {
- uint64_t tag = get_encoded_tag(f, wire_type);
- switch (upb_value_size(tag)) {
- case 1:
- putop(c, OP_TAG1, dest, tag);
- break;
- case 2:
- putop(c, OP_TAG2, dest, tag);
- break;
- default:
- putop(c, OP_TAGN, dest, tag);
- break;
- }
-}
-
-static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
- upb_selector_t selector;
- bool ok = upb_handlers_getselector(f, type, &selector);
- UPB_ASSERT(ok);
- return selector;
-}
-
-/* Takes an existing, primary dispatch table entry and repacks it with a
- * different alternate wire type. Called when we are inserting a secondary
- * dispatch table entry for an alternate wire type. */
-static uint64_t repack(uint64_t dispatch, int new_wt2) {
- uint64_t ofs;
- uint8_t wt1;
- uint8_t old_wt2;
- upb_pbdecoder_unpackdispatch(dispatch, &ofs, &wt1, &old_wt2);
- UPB_ASSERT(old_wt2 == NO_WIRE_TYPE); /* wt2 should not be set yet. */
- return upb_pbdecoder_packdispatch(ofs, wt1, new_wt2);
-}
-
-/* Marks the current bytecode position as the dispatch target for this message,
- * field, and wire type. */
-static void dispatchtarget(compiler *c, upb_pbdecodermethod *method,
- const upb_fielddef *f, int wire_type) {
- /* Offset is relative to msg base. */
- uint64_t ofs = pcofs(c) - method->code_base.ofs;
- uint32_t fn = upb_fielddef_number(f);
- upb_inttable *d = &method->dispatch;
- upb_value v;
- if (upb_inttable_remove(d, fn, &v)) {
- /* TODO: prioritize based on packed setting in .proto file. */
- uint64_t repacked = repack(upb_value_getuint64(v), wire_type);
- upb_inttable_insert(d, fn, upb_value_uint64(repacked));
- upb_inttable_insert(d, fn + UPB_MAX_FIELDNUMBER, upb_value_uint64(ofs));
- } else {
- uint64_t val = upb_pbdecoder_packdispatch(ofs, wire_type, NO_WIRE_TYPE);
- upb_inttable_insert(d, fn, upb_value_uint64(val));
- }
-}
-
-static void putpush(compiler *c, const upb_fielddef *f) {
- if (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) {
- putop(c, OP_PUSHLENDELIM);
- } else {
- uint32_t fn = upb_fielddef_number(f);
- if (fn >= 1 << 24) {
- putop(c, OP_PUSHTAGDELIM, 0);
- putop(c, OP_SETBIGGROUPNUM, fn);
- } else {
- putop(c, OP_PUSHTAGDELIM, fn);
- }
- }
-}
-
-static upb_pbdecodermethod *find_submethod(const compiler *c,
- const upb_pbdecodermethod *method,
- const upb_fielddef *f) {
- const upb_handlers *sub =
- upb_handlers_getsubhandlers(method->dest_handlers_, f);
- upb_value v;
- return upb_inttable_lookupptr(&c->group->methods, sub, &v)
- ? upb_value_getptr(v)
- : NULL;
-}
-
-static void putsel(compiler *c, opcode op, upb_selector_t sel,
- const upb_handlers *h) {
- if (upb_handlers_gethandler(h, sel, NULL)) {
- putop(c, op, sel);
- }
-}
-
-/* Puts an opcode to call a callback, but only if a callback actually exists for
- * this field and handler type. */
-static void maybeput(compiler *c, opcode op, const upb_handlers *h,
- const upb_fielddef *f, upb_handlertype_t type) {
- putsel(c, op, getsel(f, type), h);
-}
-
-static bool haslazyhandlers(const upb_handlers *h, const upb_fielddef *f) {
- if (!upb_fielddef_lazy(f))
- return false;
-
- return upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STARTSTR), NULL) ||
- upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STRING), NULL) ||
- upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_ENDSTR), NULL);
-}
-
-
-/* bytecode compiler code generation ******************************************/
-
-/* Symbolic names for our local labels. */
-#define LABEL_LOOPSTART 1 /* Top of a repeated field loop. */
-#define LABEL_LOOPBREAK 2 /* To jump out of a repeated loop */
-#define LABEL_FIELD 3 /* Jump backward to find the most recent field. */
-#define LABEL_ENDMSG 4 /* To reach the OP_ENDMSG instr for this msg. */
-
-/* Generates bytecode to parse a single non-lazy message field. */
-static void generate_msgfield(compiler *c, const upb_fielddef *f,
- upb_pbdecodermethod *method) {
- const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
- const upb_pbdecodermethod *sub_m = find_submethod(c, method, f);
- int wire_type;
-
- if (!sub_m) {
- /* Don't emit any code for this field at all; it will be parsed as an
- * unknown field.
- *
- * TODO(haberman): we should change this to parse it as a string field
- * instead. It will probably be faster, but more importantly, once we
- * start vending unknown fields, a field shouldn't be treated as unknown
- * just because it doesn't have subhandlers registered. */
- return;
- }
-
- label(c, LABEL_FIELD);
-
- wire_type =
- (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE)
- ? UPB_WIRE_TYPE_DELIMITED
- : UPB_WIRE_TYPE_START_GROUP;
-
- if (upb_fielddef_isseq(f)) {
- putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
- putchecktag(c, f, wire_type, LABEL_DISPATCH);
- dispatchtarget(c, method, f, wire_type);
- putop(c, OP_PUSHTAGDELIM, 0);
- putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
- label(c, LABEL_LOOPSTART);
- putpush(c, f);
- putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
- putop(c, OP_CALL, sub_m);
- putop(c, OP_POP);
- maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
- if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
- putop(c, OP_SETDELIM);
- }
- putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
- putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
- putop(c, OP_BRANCH, -LABEL_LOOPSTART);
- label(c, LABEL_LOOPBREAK);
- putop(c, OP_POP);
- maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
- } else {
- putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
- putchecktag(c, f, wire_type, LABEL_DISPATCH);
- dispatchtarget(c, method, f, wire_type);
- putpush(c, f);
- putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
- putop(c, OP_CALL, sub_m);
- putop(c, OP_POP);
- maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
- if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
- putop(c, OP_SETDELIM);
- }
- }
-}
-
-/* Generates bytecode to parse a single string or lazy submessage field. */
-static void generate_delimfield(compiler *c, const upb_fielddef *f,
- upb_pbdecodermethod *method) {
- const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
-
- label(c, LABEL_FIELD);
- if (upb_fielddef_isseq(f)) {
- putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
- putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
- dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
- putop(c, OP_PUSHTAGDELIM, 0);
- putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
- label(c, LABEL_LOOPSTART);
- putop(c, OP_PUSHLENDELIM);
- putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
- /* Need to emit even if no handler to skip past the string. */
- putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
- maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
- putop(c, OP_POP);
- putop(c, OP_SETDELIM);
- putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
- putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_LOOPBREAK);
- putop(c, OP_BRANCH, -LABEL_LOOPSTART);
- label(c, LABEL_LOOPBREAK);
- putop(c, OP_POP);
- maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
- } else {
- putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
- putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
- dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
- putop(c, OP_PUSHLENDELIM);
- putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
- putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
- maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
- putop(c, OP_POP);
- putop(c, OP_SETDELIM);
- }
-}
-
-/* Generates bytecode to parse a single primitive field. */
-static void generate_primitivefield(compiler *c, const upb_fielddef *f,
- upb_pbdecodermethod *method) {
- const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
- upb_descriptortype_t descriptor_type = upb_fielddef_descriptortype(f);
- opcode parse_type;
- upb_selector_t sel;
- int wire_type;
-
- label(c, LABEL_FIELD);
-
- /* From a decoding perspective, ENUM is the same as INT32. */
- if (descriptor_type == UPB_DESCRIPTOR_TYPE_ENUM)
- descriptor_type = UPB_DESCRIPTOR_TYPE_INT32;
-
- parse_type = (opcode)descriptor_type;
-
- /* TODO(haberman): generate packed or non-packed first depending on "packed"
- * setting in the fielddef. This will favor (in speed) whichever was
- * specified. */
-
- UPB_ASSERT((int)parse_type >= 0 && parse_type <= OP_MAX);
- sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
- wire_type = upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
- if (upb_fielddef_isseq(f)) {
- putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
- putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
- dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
- putop(c, OP_PUSHLENDELIM);
- putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); /* Packed */
- label(c, LABEL_LOOPSTART);
- putop(c, parse_type, sel);
- putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
- putop(c, OP_BRANCH, -LABEL_LOOPSTART);
- dispatchtarget(c, method, f, wire_type);
- putop(c, OP_PUSHTAGDELIM, 0);
- putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); /* Non-packed */
- label(c, LABEL_LOOPSTART);
- putop(c, parse_type, sel);
- putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
- putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
- putop(c, OP_BRANCH, -LABEL_LOOPSTART);
- label(c, LABEL_LOOPBREAK);
- putop(c, OP_POP); /* Packed and non-packed join. */
- maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
- putop(c, OP_SETDELIM); /* Could remove for non-packed by dup ENDSEQ. */
- } else {
- putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
- putchecktag(c, f, wire_type, LABEL_DISPATCH);
- dispatchtarget(c, method, f, wire_type);
- putop(c, parse_type, sel);
- }
-}
-
-/* Adds bytecode for parsing the given message to the given decoderplan,
- * while adding all dispatch targets to this message's dispatch table. */
-static void compile_method(compiler *c, upb_pbdecodermethod *method) {
- const upb_handlers *h;
- const upb_msgdef *md;
- uint32_t* start_pc;
- upb_msg_field_iter i;
- upb_value val;
-
- UPB_ASSERT(method);
-
- /* Clear all entries in the dispatch table. */
- upb_inttable_uninit(&method->dispatch);
- upb_inttable_init(&method->dispatch, UPB_CTYPE_UINT64);
-
- h = upb_pbdecodermethod_desthandlers(method);
- md = upb_handlers_msgdef(h);
-
- method->code_base.ofs = pcofs(c);
- putop(c, OP_SETDISPATCH, &method->dispatch);
- putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h);
- label(c, LABEL_FIELD);
- start_pc = c->pc;
- for(upb_msg_field_begin(&i, md);
- !upb_msg_field_done(&i);
- upb_msg_field_next(&i)) {
- const upb_fielddef *f = upb_msg_iter_field(&i);
- upb_fieldtype_t type = upb_fielddef_type(f);
-
- if (type == UPB_TYPE_MESSAGE && !(haslazyhandlers(h, f) && c->lazy)) {
- generate_msgfield(c, f, method);
- } else if (type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES ||
- type == UPB_TYPE_MESSAGE) {
- generate_delimfield(c, f, method);
- } else {
- generate_primitivefield(c, f, method);
- }
- }
-
- /* If there were no fields, or if no handlers were defined, we need to
- * generate a non-empty loop body so that we can at least dispatch for unknown
- * fields and check for the end of the message. */
- if (c->pc == start_pc) {
- /* Check for end-of-message. */
- putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
- /* Unconditionally dispatch. */
- putop(c, OP_DISPATCH, 0);
- }
-
- /* For now we just loop back to the last field of the message (or if none,
- * the DISPATCH opcode for the message). */
- putop(c, OP_BRANCH, -LABEL_FIELD);
-
- /* Insert both a label and a dispatch table entry for this end-of-msg. */
- label(c, LABEL_ENDMSG);
- val = upb_value_uint64(pcofs(c) - method->code_base.ofs);
- upb_inttable_insert(&method->dispatch, DISPATCH_ENDMSG, val);
-
- putsel(c, OP_ENDMSG, UPB_ENDMSG_SELECTOR, h);
- putop(c, OP_RET);
-
- upb_inttable_compact(&method->dispatch);
-}
-
-/* Populate "methods" with new upb_pbdecodermethod objects reachable from "h".
- * Returns the method for these handlers.
- *
- * Generates a new method for every destination handlers reachable from "h". */
-static void find_methods(compiler *c, const upb_handlers *h) {
- upb_value v;
- upb_msg_field_iter i;
- const upb_msgdef *md;
- upb_pbdecodermethod *method;
-
- if (upb_inttable_lookupptr(&c->group->methods, h, &v))
- return;
-
- method = newmethod(h, c->group);
- upb_inttable_insertptr(&c->group->methods, h, upb_value_ptr(method));
-
- /* Find submethods. */
- md = upb_handlers_msgdef(h);
- for(upb_msg_field_begin(&i, md);
- !upb_msg_field_done(&i);
- upb_msg_field_next(&i)) {
- const upb_fielddef *f = upb_msg_iter_field(&i);
- const upb_handlers *sub_h;
- if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
- (sub_h = upb_handlers_getsubhandlers(h, f)) != NULL) {
- /* We only generate a decoder method for submessages with handlers.
- * Others will be parsed as unknown fields. */
- find_methods(c, sub_h);
- }
- }
-}
-
-/* (Re-)compile bytecode for all messages in "msgs."
- * Overwrites any existing bytecode in "c". */
-static void compile_methods(compiler *c) {
- upb_inttable_iter i;
-
- /* Start over at the beginning of the bytecode. */
- c->pc = c->group->bytecode;
-
- upb_inttable_begin(&i, &c->group->methods);
- for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
- compile_method(c, method);
- }
-}
-
-static void set_bytecode_handlers(mgroup *g) {
- upb_inttable_iter i;
- upb_inttable_begin(&i, &g->methods);
- for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- upb_pbdecodermethod *m = upb_value_getptr(upb_inttable_iter_value(&i));
- upb_byteshandler *h = &m->input_handler_;
-
- m->code_base.ptr = g->bytecode + m->code_base.ofs;
-
- upb_byteshandler_setstartstr(h, upb_pbdecoder_startbc, m->code_base.ptr);
- upb_byteshandler_setstring(h, upb_pbdecoder_decode, g);
- upb_byteshandler_setendstr(h, upb_pbdecoder_end, m);
- }
-}
-
-
-/* TODO(haberman): allow this to be constructed for an arbitrary set of dest
- * handlers and other mgroups (but verify we have a transitive closure). */
-const mgroup *mgroup_new(const upb_handlers *dest, bool lazy) {
- mgroup *g;
- compiler *c;
-
- g = newgroup();
- c = newcompiler(g, lazy);
- find_methods(c, dest);
-
- /* We compile in two passes:
- * 1. all messages are assigned relative offsets from the beginning of the
- * bytecode (saved in method->code_base).
- * 2. forwards OP_CALL instructions can be correctly linked since message
- * offsets have been previously assigned.
- *
- * Could avoid the second pass by linking OP_CALL instructions somehow. */
- compile_methods(c);
- compile_methods(c);
- g->bytecode_end = c->pc;
- freecompiler(c);
-
-#ifdef UPB_DUMP_BYTECODE
- {
- FILE *f = fopen("/tmp/upb-bytecode", "w");
- UPB_ASSERT(f);
- dumpbc(g->bytecode, g->bytecode_end, stderr);
- dumpbc(g->bytecode, g->bytecode_end, f);
- fclose(f);
-
- f = fopen("/tmp/upb-bytecode.bin", "wb");
- UPB_ASSERT(f);
- fwrite(g->bytecode, 1, g->bytecode_end - g->bytecode, f);
- fclose(f);
- }
-#endif
-
- set_bytecode_handlers(g);
- return g;
-}
-
-
-/* upb_pbcodecache ************************************************************/
-
-upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest) {
- upb_pbcodecache *c = upb_gmalloc(sizeof(*c));
-
- if (!c) return NULL;
-
- c->dest = dest;
- c->lazy = false;
-
- c->arena = upb_arena_new();
- if (!upb_inttable_init(&c->groups, UPB_CTYPE_CONSTPTR)) return NULL;
-
- return c;
-}
-
-void upb_pbcodecache_free(upb_pbcodecache *c) {
- upb_inttable_iter i;
-
- upb_inttable_begin(&i, &c->groups);
- for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- upb_value val = upb_inttable_iter_value(&i);
- freegroup((void*)upb_value_getconstptr(val));
- }
-
- upb_inttable_uninit(&c->groups);
- upb_arena_free(c->arena);
- upb_gfree(c);
-}
-
-void upb_pbdecodermethodopts_setlazy(upb_pbcodecache *c, bool lazy) {
- UPB_ASSERT(upb_inttable_count(&c->groups) == 0);
- c->lazy = lazy;
-}
-
-const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c,
- const upb_msgdef *md) {
- upb_value v;
- bool ok;
- const upb_handlers *h;
- const mgroup *g;
-
- h = upb_handlercache_get(c->dest, md);
- if (upb_inttable_lookupptr(&c->groups, md, &v)) {
- g = upb_value_getconstptr(v);
- } else {
- g = mgroup_new(h, c->lazy);
- ok = upb_inttable_insertptr(&c->groups, md, upb_value_constptr(g));
- UPB_ASSUME(ok);
- }
-
- ok = upb_inttable_lookupptr(&g->methods, h, &v);
- UPB_ASSUME(ok);
- return upb_value_getptr(v);
-}
-/*
-** upb::Decoder (Bytecode Decoder VM)
-**
-** Bytecode must previously have been generated using the bytecode compiler in
-** compile_decoder.c. This decoder then walks through the bytecode op-by-op to
-** parse the input.
-**
-** Decoding is fully resumable; we just keep a pointer to the current bytecode
-** instruction and resume from there. A fair amount of the logic here is to
-** handle the fact that values can span buffer seams and we have to be able to
-** be capable of suspending/resuming from any byte in the stream. This
-** sometimes requires keeping a few trailing bytes from the last buffer around
-** in the "residual" buffer.
-*/
-
-#include
-#include
-
-#ifdef UPB_DUMP_BYTECODE
-#include
-#endif
-
-
-#define CHECK_SUSPEND(x) if (!(x)) return upb_pbdecoder_suspend(d);
-
-/* Error messages that are shared between the bytecode and JIT decoders. */
-const char *kPbDecoderStackOverflow = "Nesting too deep.";
-const char *kPbDecoderSubmessageTooLong =
- "Submessage end extends past enclosing submessage.";
-
-/* Error messages shared within this file. */
-static const char *kUnterminatedVarint = "Unterminated varint.";
-
-/* upb_pbdecoder **************************************************************/
-
-static opcode halt = OP_HALT;
-
-/* A dummy character we can point to when the user passes us a NULL buffer.
- * We need this because in C (NULL + 0) and (NULL - NULL) are undefined
- * behavior, which would invalidate functions like curbufleft(). */
-static const char dummy_char;
-
-/* Whether an op consumes any of the input buffer. */
-static bool consumes_input(opcode op) {
- switch (op) {
- case OP_SETDISPATCH:
- case OP_STARTMSG:
- case OP_ENDMSG:
- case OP_STARTSEQ:
- case OP_ENDSEQ:
- case OP_STARTSUBMSG:
- case OP_ENDSUBMSG:
- case OP_STARTSTR:
- case OP_ENDSTR:
- case OP_PUSHTAGDELIM:
- case OP_POP:
- case OP_SETDELIM:
- case OP_SETBIGGROUPNUM:
- case OP_CHECKDELIM:
- case OP_CALL:
- case OP_RET:
- case OP_BRANCH:
- return false;
- default:
- return true;
- }
-}
-
-static size_t stacksize(upb_pbdecoder *d, size_t entries) {
- UPB_UNUSED(d);
- return entries * sizeof(upb_pbdecoder_frame);
-}
-
-static size_t callstacksize(upb_pbdecoder *d, size_t entries) {
- UPB_UNUSED(d);
-
- return entries * sizeof(uint32_t*);
-}
-
-
-static bool in_residual_buf(const upb_pbdecoder *d, const char *p);
-
-/* It's unfortunate that we have to micro-manage the compiler with
- * UPB_FORCEINLINE and UPB_NOINLINE, especially since this tuning is necessarily
- * specific to one hardware configuration. But empirically on a Core i7,
- * performance increases 30-50% with these annotations. Every instance where
- * these appear, gcc 4.2.1 made the wrong decision and degraded performance in
- * benchmarks. */
-
-static void seterr(upb_pbdecoder *d, const char *msg) {
- upb_status_seterrmsg(d->status, msg);
-}
-
-void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) {
- seterr(d, msg);
-}
-
-
-/* Buffering ******************************************************************/
-
-/* We operate on one buffer at a time, which is either the user's buffer passed
- * to our "decode" callback or some residual bytes from the previous buffer. */
-
-/* How many bytes can be safely read from d->ptr without reading past end-of-buf
- * or past the current delimited end. */
-static size_t curbufleft(const upb_pbdecoder *d) {
- UPB_ASSERT(d->data_end >= d->ptr);
- return d->data_end - d->ptr;
-}
-
-/* How many bytes are available before end-of-buffer. */
-static size_t bufleft(const upb_pbdecoder *d) {
- return d->end - d->ptr;
-}
-
-/* Overall stream offset of d->ptr. */
-uint64_t offset(const upb_pbdecoder *d) {
- return d->bufstart_ofs + (d->ptr - d->buf);
-}
-
-/* How many bytes are available before the end of this delimited region. */
-size_t delim_remaining(const upb_pbdecoder *d) {
- return d->top->end_ofs - offset(d);
-}
-
-/* Advances d->ptr. */
-static void advance(upb_pbdecoder *d, size_t len) {
- UPB_ASSERT(curbufleft(d) >= len);
- d->ptr += len;
-}
-
-static bool in_buf(const char *p, const char *buf, const char *end) {
- return p >= buf && p <= end;
-}
-
-static bool in_residual_buf(const upb_pbdecoder *d, const char *p) {
- return in_buf(p, d->residual, d->residual_end);
-}
-
-/* Calculates the delim_end value, which is affected by both the current buffer
- * and the parsing stack, so must be called whenever either is updated. */
-static void set_delim_end(upb_pbdecoder *d) {
- size_t delim_ofs = d->top->end_ofs - d->bufstart_ofs;
- if (delim_ofs <= (size_t)(d->end - d->buf)) {
- d->delim_end = d->buf + delim_ofs;
- d->data_end = d->delim_end;
- } else {
- d->data_end = d->end;
- d->delim_end = NULL;
- }
-}
-
-static void switchtobuf(upb_pbdecoder *d, const char *buf, const char *end) {
- d->ptr = buf;
- d->buf = buf;
- d->end = end;
- set_delim_end(d);
-}
-
-static void advancetobuf(upb_pbdecoder *d, const char *buf, size_t len) {
- UPB_ASSERT(curbufleft(d) == 0);
- d->bufstart_ofs += (d->end - d->buf);
- switchtobuf(d, buf, buf + len);
-}
-
-static void checkpoint(upb_pbdecoder *d) {
- /* The assertion here is in the interests of efficiency, not correctness.
- * We are trying to ensure that we don't checkpoint() more often than
- * necessary. */
- UPB_ASSERT(d->checkpoint != d->ptr);
- d->checkpoint = d->ptr;
-}
-
-/* Skips "bytes" bytes in the stream, which may be more than available. If we
- * skip more bytes than are available, we return a long read count to the caller
- * indicating how many bytes can be skipped over before passing actual data
- * again. Skipped bytes can pass a NULL buffer and the decoder guarantees they
- * won't actually be read.
- */
-static int32_t skip(upb_pbdecoder *d, size_t bytes) {
- UPB_ASSERT(!in_residual_buf(d, d->ptr) || d->size_param == 0);
- UPB_ASSERT(d->skip == 0);
- if (bytes > delim_remaining(d)) {
- seterr(d, "Skipped value extended beyond enclosing submessage.");
- return (int32_t)upb_pbdecoder_suspend(d);
- } else if (bufleft(d) >= bytes) {
- /* Skipped data is all in current buffer, and more is still available. */
- advance(d, bytes);
- d->skip = 0;
- return DECODE_OK;
- } else {
- /* Skipped data extends beyond currently available buffers. */
- d->pc = d->last;
- d->skip = bytes - curbufleft(d);
- d->bufstart_ofs += (d->end - d->buf);
- d->residual_end = d->residual;
- switchtobuf(d, d->residual, d->residual_end);
- return (int32_t)(d->size_param + d->skip);
- }
-}
-
-
-/* Resumes the decoder from an initial state or from a previous suspend. */
-int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
- size_t size, const upb_bufhandle *handle) {
- UPB_UNUSED(p); /* Useless; just for the benefit of the JIT. */
-
- /* d->skip and d->residual_end could probably elegantly be represented
- * as a single variable, to more easily represent this invariant. */
- UPB_ASSERT(!(d->skip && d->residual_end > d->residual));
-
- /* We need to remember the original size_param, so that the value we return
- * is relative to it, even if we do some skipping first. */
- d->size_param = size;
- d->handle = handle;
-
- /* Have to handle this case specially (ie. not with skip()) because the user
- * is allowed to pass a NULL buffer here, which won't allow us to safely
- * calculate a d->end or use our normal functions like curbufleft(). */
- if (d->skip && d->skip >= size) {
- d->skip -= size;
- d->bufstart_ofs += size;
- buf = &dummy_char;
- size = 0;
-
- /* We can't just return now, because we might need to execute some ops
- * like CHECKDELIM, which could call some callbacks and pop the stack. */
- }
-
- /* We need to pretend that this was the actual buffer param, since some of the
- * calculations assume that d->ptr/d->buf is relative to this. */
- d->buf_param = buf;
-
- if (!buf) {
- /* NULL buf is ok if its entire span is covered by the "skip" above, but
- * by this point we know that "skip" doesn't cover the buffer. */
- seterr(d, "Passed NULL buffer over non-skippable region.");
- return (int32_t)upb_pbdecoder_suspend(d);
- }
-
- if (d->residual_end > d->residual) {
- /* We have residual bytes from the last buffer. */
- UPB_ASSERT(d->ptr == d->residual);
- } else {
- switchtobuf(d, buf, buf + size);
- }
-
- d->checkpoint = d->ptr;
-
- /* Handle skips that don't cover the whole buffer (as above). */
- if (d->skip) {
- size_t skip_bytes = d->skip;
- d->skip = 0;
- CHECK_RETURN(skip(d, skip_bytes));
- checkpoint(d);
- }
-
- /* If we're inside an unknown group, continue to parse unknown values. */
- if (d->top->groupnum < 0) {
- CHECK_RETURN(upb_pbdecoder_skipunknown(d, -1, 0));
- checkpoint(d);
- }
-
- return DECODE_OK;
-}
-
-/* Suspends the decoder at the last checkpoint, without saving any residual
- * bytes. If there are any unconsumed bytes, returns a short byte count. */
-size_t upb_pbdecoder_suspend(upb_pbdecoder *d) {
- d->pc = d->last;
- if (d->checkpoint == d->residual) {
- /* Checkpoint was in residual buf; no user bytes were consumed. */
- d->ptr = d->residual;
- return 0;
- } else {
- size_t ret = d->size_param - (d->end - d->checkpoint);
- UPB_ASSERT(!in_residual_buf(d, d->checkpoint));
- UPB_ASSERT(d->buf == d->buf_param || d->buf == &dummy_char);
-
- d->bufstart_ofs += (d->checkpoint - d->buf);
- d->residual_end = d->residual;
- switchtobuf(d, d->residual, d->residual_end);
- return ret;
- }
-}
-
-/* Suspends the decoder at the last checkpoint, and saves any unconsumed
- * bytes in our residual buffer. This is necessary if we need more user
- * bytes to form a complete value, which might not be contiguous in the
- * user's buffers. Always consumes all user bytes. */
-static size_t suspend_save(upb_pbdecoder *d) {
- /* We hit end-of-buffer before we could parse a full value.
- * Save any unconsumed bytes (if any) to the residual buffer. */
- d->pc = d->last;
-
- if (d->checkpoint == d->residual) {
- /* Checkpoint was in residual buf; append user byte(s) to residual buf. */
- UPB_ASSERT((d->residual_end - d->residual) + d->size_param <=
- sizeof(d->residual));
- if (!in_residual_buf(d, d->ptr)) {
- d->bufstart_ofs -= (d->residual_end - d->residual);
- }
- memcpy(d->residual_end, d->buf_param, d->size_param);
- d->residual_end += d->size_param;
- } else {
- /* Checkpoint was in user buf; old residual bytes not needed. */
- size_t save;
- UPB_ASSERT(!in_residual_buf(d, d->checkpoint));
-
- d->ptr = d->checkpoint;
- save = curbufleft(d);
- UPB_ASSERT(save <= sizeof(d->residual));
- memcpy(d->residual, d->ptr, save);
- d->residual_end = d->residual + save;
- d->bufstart_ofs = offset(d);
- }
-
- switchtobuf(d, d->residual, d->residual_end);
- return d->size_param;
-}
-
-/* Copies the next "bytes" bytes into "buf" and advances the stream.
- * Requires that this many bytes are available in the current buffer. */
-UPB_FORCEINLINE static void consumebytes(upb_pbdecoder *d, void *buf,
- size_t bytes) {
- UPB_ASSERT(bytes <= curbufleft(d));
- memcpy(buf, d->ptr, bytes);
- advance(d, bytes);
-}
-
-/* Slow path for getting the next "bytes" bytes, regardless of whether they are
- * available in the current buffer or not. Returns a status code as described
- * in decoder.int.h. */
-UPB_NOINLINE static int32_t getbytes_slow(upb_pbdecoder *d, void *buf,
- size_t bytes) {
- const size_t avail = curbufleft(d);
- consumebytes(d, buf, avail);
- bytes -= avail;
- UPB_ASSERT(bytes > 0);
- if (in_residual_buf(d, d->ptr)) {
- advancetobuf(d, d->buf_param, d->size_param);
- }
- if (curbufleft(d) >= bytes) {
- consumebytes(d, (char *)buf + avail, bytes);
- return DECODE_OK;
- } else if (d->data_end == d->delim_end) {
- seterr(d, "Submessage ended in the middle of a value or group");
- return (int32_t)upb_pbdecoder_suspend(d);
- } else {
- return (int32_t)suspend_save(d);
- }
-}
-
-/* Gets the next "bytes" bytes, regardless of whether they are available in the
- * current buffer or not. Returns a status code as described in decoder.int.h.
- */
-UPB_FORCEINLINE static int32_t getbytes(upb_pbdecoder *d, void *buf,
- size_t bytes) {
- if (curbufleft(d) >= bytes) {
- /* Buffer has enough data to satisfy. */
- consumebytes(d, buf, bytes);
- return DECODE_OK;
- } else {
- return getbytes_slow(d, buf, bytes);
- }
-}
-
-UPB_NOINLINE static size_t peekbytes_slow(upb_pbdecoder *d, void *buf,
- size_t bytes) {
- size_t ret = curbufleft(d);
- memcpy(buf, d->ptr, ret);
- if (in_residual_buf(d, d->ptr)) {
- size_t copy = UPB_MIN(bytes - ret, d->size_param);
- memcpy((char *)buf + ret, d->buf_param, copy);
- ret += copy;
- }
- return ret;
-}
-
-UPB_FORCEINLINE static size_t peekbytes(upb_pbdecoder *d, void *buf,
- size_t bytes) {
- if (curbufleft(d) >= bytes) {
- memcpy(buf, d->ptr, bytes);
- return bytes;
- } else {
- return peekbytes_slow(d, buf, bytes);
- }
-}
-
-
-/* Decoding of wire types *****************************************************/
-
-/* Slow path for decoding a varint from the current buffer position.
- * Returns a status code as described in decoder.int.h. */
-UPB_NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d,
- uint64_t *u64) {
- uint8_t byte = 0x80;
- int bitpos;
- *u64 = 0;
- for(bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) {
- CHECK_RETURN(getbytes(d, &byte, 1));
- *u64 |= (uint64_t)(byte & 0x7F) << bitpos;
- }
- if(bitpos == 70 && (byte & 0x80)) {
- seterr(d, kUnterminatedVarint);
- return (int32_t)upb_pbdecoder_suspend(d);
- }
- return DECODE_OK;
-}
-
-/* Decodes a varint from the current buffer position.
- * Returns a status code as described in decoder.int.h. */
-UPB_FORCEINLINE static int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) {
- if (curbufleft(d) > 0 && !(*d->ptr & 0x80)) {
- *u64 = *d->ptr;
- advance(d, 1);
- return DECODE_OK;
- } else if (curbufleft(d) >= 10) {
- /* Fast case. */
- upb_decoderet r = upb_vdecode_fast(d->ptr);
- if (r.p == NULL) {
- seterr(d, kUnterminatedVarint);
- return (int32_t)upb_pbdecoder_suspend(d);
- }
- advance(d, r.p - d->ptr);
- *u64 = r.val;
- return DECODE_OK;
- } else {
- /* Slow case -- varint spans buffer seam. */
- return upb_pbdecoder_decode_varint_slow(d, u64);
- }
-}
-
-/* Decodes a 32-bit varint from the current buffer position.
- * Returns a status code as described in decoder.int.h. */
-UPB_FORCEINLINE static int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) {
- uint64_t u64;
- int32_t ret = decode_varint(d, &u64);
- if (ret >= 0) return ret;
- if (u64 > UINT32_MAX) {
- seterr(d, "Unterminated 32-bit varint");
- /* TODO(haberman) guarantee that this function return is >= 0 somehow,
- * so we know this path will always be treated as error by our caller.
- * Right now the size_t -> int32_t can overflow and produce negative values.
- */
- *u32 = 0;
- return (int32_t)upb_pbdecoder_suspend(d);
- }
- *u32 = (uint32_t)u64;
- return DECODE_OK;
-}
-
-/* Decodes a fixed32 from the current buffer position.
- * Returns a status code as described in decoder.int.h.
- * TODO: proper byte swapping for big-endian machines. */
-UPB_FORCEINLINE static int32_t decode_fixed32(upb_pbdecoder *d, uint32_t *u32) {
- return getbytes(d, u32, 4);
-}
-
-/* Decodes a fixed64 from the current buffer position.
- * Returns a status code as described in decoder.int.h.
- * TODO: proper byte swapping for big-endian machines. */
-UPB_FORCEINLINE static int32_t decode_fixed64(upb_pbdecoder *d, uint64_t *u64) {
- return getbytes(d, u64, 8);
-}
-
-/* Non-static versions of the above functions.
- * These are called by the JIT for fallback paths. */
-int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32) {
- return decode_fixed32(d, u32);
-}
-
-int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64) {
- return decode_fixed64(d, u64);
-}
-
-static double as_double(uint64_t n) { double d; memcpy(&d, &n, 8); return d; }
-static float as_float(uint32_t n) { float f; memcpy(&f, &n, 4); return f; }
-
-/* Pushes a frame onto the decoder stack. */
-static bool decoder_push(upb_pbdecoder *d, uint64_t end) {
- upb_pbdecoder_frame *fr = d->top;
-
- if (end > fr->end_ofs) {
- seterr(d, kPbDecoderSubmessageTooLong);
- return false;
- } else if (fr == d->limit) {
- seterr(d, kPbDecoderStackOverflow);
- return false;
- }
-
- fr++;
- fr->end_ofs = end;
- fr->dispatch = NULL;
- fr->groupnum = 0;
- d->top = fr;
- return true;
-}
-
-static bool pushtagdelim(upb_pbdecoder *d, uint32_t arg) {
- /* While we expect to see an "end" tag (either ENDGROUP or a non-sequence
- * field number) prior to hitting any enclosing submessage end, pushing our
- * existing delim end prevents us from continuing to parse values from a
- * corrupt proto that doesn't give us an END tag in time. */
- if (!decoder_push(d, d->top->end_ofs))
- return false;
- d->top->groupnum = arg;
- return true;
-}
-
-/* Pops a frame from the decoder stack. */
-static void decoder_pop(upb_pbdecoder *d) { d->top--; }
-
-UPB_NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d,
- uint64_t expected) {
- uint64_t data = 0;
- size_t bytes = upb_value_size(expected);
- size_t read = peekbytes(d, &data, bytes);
- if (read == bytes && data == expected) {
- /* Advance past matched bytes. */
- int32_t ok = getbytes(d, &data, read);
- UPB_ASSERT(ok < 0);
- return DECODE_OK;
- } else if (read < bytes && memcmp(&data, &expected, read) == 0) {
- return (int32_t)suspend_save(d);
- } else {
- return DECODE_MISMATCH;
- }
-}
-
-int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum,
- uint8_t wire_type) {
- if (fieldnum >= 0)
- goto have_tag;
-
- while (true) {
- uint32_t tag;
- CHECK_RETURN(decode_v32(d, &tag));
- wire_type = tag & 0x7;
- fieldnum = tag >> 3;
-
-have_tag:
- if (fieldnum == 0) {
- seterr(d, "Saw invalid field number (0)");
- return (int32_t)upb_pbdecoder_suspend(d);
- }
-
- switch (wire_type) {
- case UPB_WIRE_TYPE_32BIT:
- CHECK_RETURN(skip(d, 4));
- break;
- case UPB_WIRE_TYPE_64BIT:
- CHECK_RETURN(skip(d, 8));
- break;
- case UPB_WIRE_TYPE_VARINT: {
- uint64_t u64;
- CHECK_RETURN(decode_varint(d, &u64));
- break;
- }
- case UPB_WIRE_TYPE_DELIMITED: {
- uint32_t len;
- CHECK_RETURN(decode_v32(d, &len));
- CHECK_RETURN(skip(d, len));
- break;
- }
- case UPB_WIRE_TYPE_START_GROUP:
- if (!pushtagdelim(d, -fieldnum)) {
- return (int32_t)upb_pbdecoder_suspend(d);
- }
- break;
- case UPB_WIRE_TYPE_END_GROUP:
- if (fieldnum == -d->top->groupnum) {
- decoder_pop(d);
- } else if (fieldnum == d->top->groupnum) {
- return DECODE_ENDGROUP;
- } else {
- seterr(d, "Unmatched ENDGROUP tag.");
- return (int32_t)upb_pbdecoder_suspend(d);
- }
- break;
- default:
- seterr(d, "Invalid wire type");
- return (int32_t)upb_pbdecoder_suspend(d);
- }
-
- if (d->top->groupnum >= 0) {
- /* TODO: More code needed for handling unknown groups. */
- upb_sink_putunknown(d->top->sink, d->checkpoint, d->ptr - d->checkpoint);
- return DECODE_OK;
- }
-
- /* Unknown group -- continue looping over unknown fields. */
- checkpoint(d);
- }
-}
-
-static void goto_endmsg(upb_pbdecoder *d) {
- upb_value v;
- bool found = upb_inttable_lookup32(d->top->dispatch, DISPATCH_ENDMSG, &v);
- UPB_ASSERT(found);
- d->pc = d->top->base + upb_value_getuint64(v);
-}
-
-/* Parses a tag and jumps to the corresponding bytecode instruction for this
- * field.
- *
- * If the tag is unknown (or the wire type doesn't match), parses the field as
- * unknown. If the tag is a valid ENDGROUP tag, jumps to the bytecode
- * instruction for the end of message. */
-static int32_t dispatch(upb_pbdecoder *d) {
- upb_inttable *dispatch = d->top->dispatch;
- uint32_t tag;
- uint8_t wire_type;
- uint32_t fieldnum;
- upb_value val;
- int32_t retval;
-
- /* Decode tag. */
- CHECK_RETURN(decode_v32(d, &tag));
- wire_type = tag & 0x7;
- fieldnum = tag >> 3;
-
- /* Lookup tag. Because of packed/non-packed compatibility, we have to
- * check the wire type against two possibilities. */
- if (fieldnum != DISPATCH_ENDMSG &&
- upb_inttable_lookup32(dispatch, fieldnum, &val)) {
- uint64_t v = upb_value_getuint64(val);
- if (wire_type == (v & 0xff)) {
- d->pc = d->top->base + (v >> 16);
- return DECODE_OK;
- } else if (wire_type == ((v >> 8) & 0xff)) {
- bool found =
- upb_inttable_lookup(dispatch, fieldnum + UPB_MAX_FIELDNUMBER, &val);
- UPB_ASSERT(found);
- d->pc = d->top->base + upb_value_getuint64(val);
- return DECODE_OK;
- }
- }
-
- /* We have some unknown fields (or ENDGROUP) to parse. The DISPATCH or TAG
- * bytecode that triggered this is preceded by a CHECKDELIM bytecode which
- * we need to back up to, so that when we're done skipping unknown data we
- * can re-check the delimited end. */
- d->last--; /* Necessary if we get suspended */
- d->pc = d->last;
- UPB_ASSERT(getop(*d->last) == OP_CHECKDELIM);
-
- /* Unknown field or ENDGROUP. */
- retval = upb_pbdecoder_skipunknown(d, fieldnum, wire_type);
-
- CHECK_RETURN(retval);
-
- if (retval == DECODE_ENDGROUP) {
- goto_endmsg(d);
- return DECODE_OK;
- }
-
- return DECODE_OK;
-}
-
-/* Callers know that the stack is more than one deep because the opcodes that
- * call this only occur after PUSH operations. */
-upb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) {
- UPB_ASSERT(d->top != d->stack);
- return d->top - 1;
-}
-
-
-/* The main decoding loop *****************************************************/
-
-/* The main decoder VM function. Uses traditional bytecode dispatch loop with a
- * switch() statement. */
-size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group,
- const upb_bufhandle* handle) {
-
-#define VMCASE(op, code) \
- case op: { code; if (consumes_input(op)) checkpoint(d); break; }
-#define PRIMITIVE_OP(type, wt, name, convfunc, ctype) \
- VMCASE(OP_PARSE_ ## type, { \
- ctype val; \
- CHECK_RETURN(decode_ ## wt(d, &val)); \
- upb_sink_put ## name(d->top->sink, arg, (convfunc)(val)); \
- })
-
- while(1) {
- int32_t instruction;
- opcode op;
- uint32_t arg;
- int32_t longofs;
-
- d->last = d->pc;
- instruction = *d->pc++;
- op = getop(instruction);
- arg = instruction >> 8;
- longofs = arg;
- UPB_ASSERT(d->ptr != d->residual_end);
- UPB_UNUSED(group);
-#ifdef UPB_DUMP_BYTECODE
- fprintf(stderr, "s_ofs=%d buf_ofs=%d data_rem=%d buf_rem=%d delim_rem=%d "
- "%x %s (%d)\n",
- (int)offset(d),
- (int)(d->ptr - d->buf),
- (int)(d->data_end - d->ptr),
- (int)(d->end - d->ptr),
- (int)((d->top->end_ofs - d->bufstart_ofs) - (d->ptr - d->buf)),
- (int)(d->pc - 1 - group->bytecode),
- upb_pbdecoder_getopname(op),
- arg);
-#endif
- switch (op) {
- /* Technically, we are losing data if we see a 32-bit varint that is not
- * properly sign-extended. We could detect this and error about the data
- * loss, but proto2 does not do this, so we pass. */
- PRIMITIVE_OP(INT32, varint, int32, int32_t, uint64_t)
- PRIMITIVE_OP(INT64, varint, int64, int64_t, uint64_t)
- PRIMITIVE_OP(UINT32, varint, uint32, uint32_t, uint64_t)
- PRIMITIVE_OP(UINT64, varint, uint64, uint64_t, uint64_t)
- PRIMITIVE_OP(FIXED32, fixed32, uint32, uint32_t, uint32_t)
- PRIMITIVE_OP(FIXED64, fixed64, uint64, uint64_t, uint64_t)
- PRIMITIVE_OP(SFIXED32, fixed32, int32, int32_t, uint32_t)
- PRIMITIVE_OP(SFIXED64, fixed64, int64, int64_t, uint64_t)
- PRIMITIVE_OP(BOOL, varint, bool, bool, uint64_t)
- PRIMITIVE_OP(DOUBLE, fixed64, double, as_double, uint64_t)
- PRIMITIVE_OP(FLOAT, fixed32, float, as_float, uint32_t)
- PRIMITIVE_OP(SINT32, varint, int32, upb_zzdec_32, uint64_t)
- PRIMITIVE_OP(SINT64, varint, int64, upb_zzdec_64, uint64_t)
-
- VMCASE(OP_SETDISPATCH,
- d->top->base = d->pc - 1;
- memcpy(&d->top->dispatch, d->pc, sizeof(void*));
- d->pc += sizeof(void*) / sizeof(uint32_t);
- )
- VMCASE(OP_STARTMSG,
- CHECK_SUSPEND(upb_sink_startmsg(d->top->sink));
- )
- VMCASE(OP_ENDMSG,
- CHECK_SUSPEND(upb_sink_endmsg(d->top->sink, d->status));
- )
- VMCASE(OP_STARTSEQ,
- upb_pbdecoder_frame *outer = outer_frame(d);
- CHECK_SUSPEND(upb_sink_startseq(outer->sink, arg, &d->top->sink));
- )
- VMCASE(OP_ENDSEQ,
- CHECK_SUSPEND(upb_sink_endseq(d->top->sink, arg));
- )
- VMCASE(OP_STARTSUBMSG,
- upb_pbdecoder_frame *outer = outer_frame(d);
- CHECK_SUSPEND(upb_sink_startsubmsg(outer->sink, arg, &d->top->sink));
- )
- VMCASE(OP_ENDSUBMSG,
- upb_sink subsink = (d->top + 1)->sink;
- CHECK_SUSPEND(upb_sink_endsubmsg(d->top->sink, subsink, arg));
- )
- VMCASE(OP_STARTSTR,
- uint32_t len = (uint32_t)delim_remaining(d);
- upb_pbdecoder_frame *outer = outer_frame(d);
- CHECK_SUSPEND(upb_sink_startstr(outer->sink, arg, len, &d->top->sink));
- if (len == 0) {
- d->pc++; /* Skip OP_STRING. */
- }
- )
- VMCASE(OP_STRING,
- uint32_t len = (uint32_t)curbufleft(d);
- size_t n = upb_sink_putstring(d->top->sink, arg, d->ptr, len, handle);
- if (n > len) {
- if (n > delim_remaining(d)) {
- seterr(d, "Tried to skip past end of string.");
- return upb_pbdecoder_suspend(d);
- } else {
- int32_t ret = skip(d, n);
- /* This shouldn't return DECODE_OK, because n > len. */
- UPB_ASSERT(ret >= 0);
- return ret;
- }
- }
- advance(d, n);
- if (n < len || d->delim_end == NULL) {
- /* We aren't finished with this string yet. */
- d->pc--; /* Repeat OP_STRING. */
- if (n > 0) checkpoint(d);
- return upb_pbdecoder_suspend(d);
- }
- )
- VMCASE(OP_ENDSTR,
- CHECK_SUSPEND(upb_sink_endstr(d->top->sink, arg));
- )
- VMCASE(OP_PUSHTAGDELIM,
- CHECK_SUSPEND(pushtagdelim(d, arg));
- )
- VMCASE(OP_SETBIGGROUPNUM,
- d->top->groupnum = *d->pc++;
- )
- VMCASE(OP_POP,
- UPB_ASSERT(d->top > d->stack);
- decoder_pop(d);
- )
- VMCASE(OP_PUSHLENDELIM,
- uint32_t len;
- CHECK_RETURN(decode_v32(d, &len));
- CHECK_SUSPEND(decoder_push(d, offset(d) + len));
- set_delim_end(d);
- )
- VMCASE(OP_SETDELIM,
- set_delim_end(d);
- )
- VMCASE(OP_CHECKDELIM,
- /* We are guaranteed of this assert because we never allow ourselves to
- * consume bytes beyond data_end, which covers delim_end when non-NULL.
- */
- UPB_ASSERT(!(d->delim_end && d->ptr > d->delim_end));
- if (d->ptr == d->delim_end)
- d->pc += longofs;
- )
- VMCASE(OP_CALL,
- d->callstack[d->call_len++] = d->pc;
- d->pc += longofs;
- )
- VMCASE(OP_RET,
- UPB_ASSERT(d->call_len > 0);
- d->pc = d->callstack[--d->call_len];
- )
- VMCASE(OP_BRANCH,
- d->pc += longofs;
- )
- VMCASE(OP_TAG1,
- uint8_t expected;
- CHECK_SUSPEND(curbufleft(d) > 0);
- expected = (arg >> 8) & 0xff;
- if (*d->ptr == expected) {
- advance(d, 1);
- } else {
- int8_t shortofs;
- badtag:
- shortofs = arg;
- if (shortofs == LABEL_DISPATCH) {
- CHECK_RETURN(dispatch(d));
- } else {
- d->pc += shortofs;
- break; /* Avoid checkpoint(). */
- }
- }
- )
- VMCASE(OP_TAG2,
- uint16_t expected;
- CHECK_SUSPEND(curbufleft(d) > 0);
- expected = (arg >> 8) & 0xffff;
- if (curbufleft(d) >= 2) {
- uint16_t actual;
- memcpy(&actual, d->ptr, 2);
- if (expected == actual) {
- advance(d, 2);
- } else {
- goto badtag;
- }
- } else {
- int32_t result = upb_pbdecoder_checktag_slow(d, expected);
- if (result == DECODE_MISMATCH) goto badtag;
- if (result >= 0) return result;
- }
- )
- VMCASE(OP_TAGN, {
- uint64_t expected;
- int32_t result;
- memcpy(&expected, d->pc, 8);
- d->pc += 2;
- result = upb_pbdecoder_checktag_slow(d, expected);
- if (result == DECODE_MISMATCH) goto badtag;
- if (result >= 0) return result;
- })
- VMCASE(OP_DISPATCH, {
- CHECK_RETURN(dispatch(d));
- })
- VMCASE(OP_HALT, {
- return d->size_param;
- })
- }
- }
-}
-
-
-/* BytesHandler handlers ******************************************************/
-
-void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint) {
- upb_pbdecoder *d = closure;
- UPB_UNUSED(size_hint);
- d->top->end_ofs = UINT64_MAX;
- d->bufstart_ofs = 0;
- d->call_len = 1;
- d->callstack[0] = &halt;
- d->pc = pc;
- d->skip = 0;
- return d;
-}
-
-bool upb_pbdecoder_end(void *closure, const void *handler_data) {
- upb_pbdecoder *d = closure;
- const upb_pbdecodermethod *method = handler_data;
- uint64_t end;
- char dummy;
-
- if (d->residual_end > d->residual) {
- seterr(d, "Unexpected EOF: decoder still has buffered unparsed data");
- return false;
- }
-
- if (d->skip) {
- seterr(d, "Unexpected EOF inside skipped data");
- return false;
- }
-
- if (d->top->end_ofs != UINT64_MAX) {
- seterr(d, "Unexpected EOF inside delimited string");
- return false;
- }
-
- /* The user's end() call indicates that the message ends here. */
- end = offset(d);
- d->top->end_ofs = end;
-
- {
- const uint32_t *p = d->pc;
- d->stack->end_ofs = end;
- /* Check the previous bytecode, but guard against beginning. */
- if (p != method->code_base.ptr) p--;
- if (getop(*p) == OP_CHECKDELIM) {
- /* Rewind from OP_TAG* to OP_CHECKDELIM. */
- UPB_ASSERT(getop(*d->pc) == OP_TAG1 ||
- getop(*d->pc) == OP_TAG2 ||
- getop(*d->pc) == OP_TAGN ||
- getop(*d->pc) == OP_DISPATCH);
- d->pc = p;
- }
- upb_pbdecoder_decode(closure, handler_data, &dummy, 0, NULL);
- }
-
- if (d->call_len != 0) {
- seterr(d, "Unexpected EOF inside submessage or group");
- return false;
- }
-
- return true;
-}
-
-size_t upb_pbdecoder_decode(void *decoder, const void *group, const char *buf,
- size_t size, const upb_bufhandle *handle) {
- int32_t result = upb_pbdecoder_resume(decoder, NULL, buf, size, handle);
-
- if (result == DECODE_ENDGROUP) goto_endmsg(decoder);
- CHECK_RETURN(result);
-
- return run_decoder_vm(decoder, group, handle);
-}
-
-
-/* Public API *****************************************************************/
-
-void upb_pbdecoder_reset(upb_pbdecoder *d) {
- d->top = d->stack;
- d->top->groupnum = 0;
- d->ptr = d->residual;
- d->buf = d->residual;
- d->end = d->residual;
- d->residual_end = d->residual;
-}
-
-upb_pbdecoder *upb_pbdecoder_create(upb_arena *a, const upb_pbdecodermethod *m,
- upb_sink sink, upb_status *status) {
- const size_t default_max_nesting = 64;
-
- upb_pbdecoder *d = upb_arena_malloc(a, sizeof(upb_pbdecoder));
- if (!d) return NULL;
-
- d->method_ = m;
- d->callstack = upb_arena_malloc(a, callstacksize(d, default_max_nesting));
- d->stack = upb_arena_malloc(a, stacksize(d, default_max_nesting));
- if (!d->stack || !d->callstack) {
- return NULL;
- }
-
- d->arena = a;
- d->limit = d->stack + default_max_nesting - 1;
- d->stack_size = default_max_nesting;
- d->status = status;
-
- upb_pbdecoder_reset(d);
- upb_bytessink_reset(&d->input_, &m->input_handler_, d);
-
- if (d->method_->dest_handlers_) {
- if (sink.handlers != d->method_->dest_handlers_)
- return NULL;
- }
- d->top->sink = sink;
-
- return d;
-}
-
-uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d) {
- return offset(d);
-}
-
-const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d) {
- return d->method_;
-}
-
-upb_bytessink upb_pbdecoder_input(upb_pbdecoder *d) {
- return d->input_;
-}
-
-size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d) {
- return d->stack_size;
-}
-
-bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) {
- UPB_ASSERT(d->top >= d->stack);
-
- if (max < (size_t)(d->top - d->stack)) {
- /* Can't set a limit smaller than what we are currently at. */
- return false;
- }
-
- if (max > d->stack_size) {
- /* Need to reallocate stack and callstack to accommodate. */
- size_t old_size = stacksize(d, d->stack_size);
- size_t new_size = stacksize(d, max);
- void *p = upb_arena_realloc(d->arena, d->stack, old_size, new_size);
- if (!p) {
- return false;
- }
- d->stack = p;
-
- old_size = callstacksize(d, d->stack_size);
- new_size = callstacksize(d, max);
- p = upb_arena_realloc(d->arena, d->callstack, old_size, new_size);
- if (!p) {
- return false;
- }
- d->callstack = p;
-
- d->stack_size = max;
- }
-
- d->limit = d->stack + max - 1;
- return true;
-}
-/*
-** upb::Encoder
-**
-** Since we are implementing pure handlers (ie. without any out-of-band access
-** to pre-computed lengths), we have to buffer all submessages before we can
-** emit even their first byte.
-**
-** Not knowing the size of submessages also means we can't write a perfect
-** zero-copy implementation, even with buffering. Lengths are stored as
-** varints, which means that we don't know how many bytes to reserve for the
-** length until we know what the length is.
-**
-** This leaves us with three main choices:
-**
-** 1. buffer all submessage data in a temporary buffer, then copy it exactly
-** once into the output buffer.
-**
-** 2. attempt to buffer data directly into the output buffer, estimating how
-** many bytes each length will take. When our guesses are wrong, use
-** memmove() to grow or shrink the allotted space.
-**
-** 3. buffer directly into the output buffer, allocating a max length
-** ahead-of-time for each submessage length. If we overallocated, we waste
-** space, but no memcpy() or memmove() is required. This approach requires
-** defining a maximum size for submessages and rejecting submessages that
-** exceed that size.
-**
-** (2) and (3) have the potential to have better performance, but they are more
-** complicated and subtle to implement:
-**
-** (3) requires making an arbitrary choice of the maximum message size; it
-** wastes space when submessages are shorter than this and fails
-** completely when they are longer. This makes it more finicky and
-** requires configuration based on the input. It also makes it impossible
-** to perfectly match the output of reference encoders that always use the
-** optimal amount of space for each length.
-**
-** (2) requires guessing the the size upfront, and if multiple lengths are
-** guessed wrong the minimum required number of memmove() operations may
-** be complicated to compute correctly. Implemented properly, it may have
-** a useful amortized or average cost, but more investigation is required
-** to determine this and what the optimal algorithm is to achieve it.
-**
-** (1) makes you always pay for exactly one copy, but its implementation is
-** the simplest and its performance is predictable.
-**
-** So for now, we implement (1) only. If we wish to optimize later, we should
-** be able to do it without affecting users.
-**
-** The strategy is to buffer the segments of data that do *not* depend on
-** unknown lengths in one buffer, and keep a separate buffer of segment pointers
-** and lengths. When the top-level submessage ends, we can go beginning to end,
-** alternating the writing of lengths with memcpy() of the rest of the data.
-** At the top level though, no buffering is required.
-*/
-
-
-
-/* The output buffer is divided into segments; a segment is a string of data
- * that is "ready to go" -- it does not need any varint lengths inserted into
- * the middle. The seams between segments are where varints will be inserted
- * once they are known.
- *
- * We also use the concept of a "run", which is a range of encoded bytes that
- * occur at a single submessage level. Every segment contains one or more runs.
- *
- * A segment can span messages. Consider:
- *
- * .--Submessage lengths---------.
- * | | |
- * | V V
- * V | |--------------- | |-----------------
- * Submessages: | |-----------------------------------------------
- * Top-level msg: ------------------------------------------------------------
- *
- * Segments: ----- ------------------- -----------------
- * Runs: *---- *--------------*--- *----------------
- * (* marks the start)
- *
- * Note that the top-level menssage is not in any segment because it does not
- * have any length preceding it.
- *
- * A segment is only interrupted when another length needs to be inserted. So
- * observe how the second segment spans both the inner submessage and part of
- * the next enclosing message. */
-typedef struct {
- uint32_t msglen; /* The length to varint-encode before this segment. */
- uint32_t seglen; /* Length of the segment. */
-} upb_pb_encoder_segment;
-
-struct upb_pb_encoder {
- upb_arena *arena;
-
- /* Our input and output. */
- upb_sink input_;
- upb_bytessink output_;
-
- /* The "subclosure" -- used as the inner closure as part of the bytessink
- * protocol. */
- void *subc;
-
- /* The output buffer and limit, and our current write position. "buf"
- * initially points to "initbuf", but is dynamically allocated if we need to
- * grow beyond the initial size. */
- char *buf, *ptr, *limit;
-
- /* The beginning of the current run, or undefined if we are at the top
- * level. */
- char *runbegin;
-
- /* The list of segments we are accumulating. */
- upb_pb_encoder_segment *segbuf, *segptr, *seglimit;
-
- /* The stack of enclosing submessages. Each entry in the stack points to the
- * segment where this submessage's length is being accumulated. */
- int *stack, *top, *stacklimit;
-
- /* Depth of startmsg/endmsg calls. */
- int depth;
-};
-
-/* low-level buffering ********************************************************/
-
-/* Low-level functions for interacting with the output buffer. */
-
-/* TODO(haberman): handle pushback */
-static void putbuf(upb_pb_encoder *e, const char *buf, size_t len) {
- size_t n = upb_bytessink_putbuf(e->output_, e->subc, buf, len, NULL);
- UPB_ASSERT(n == len);
-}
-
-static upb_pb_encoder_segment *top(upb_pb_encoder *e) {
- return &e->segbuf[*e->top];
-}
-
-/* Call to ensure that at least "bytes" bytes are available for writing at
- * e->ptr. Returns false if the bytes could not be allocated. */
-static bool reserve(upb_pb_encoder *e, size_t bytes) {
- if ((size_t)(e->limit - e->ptr) < bytes) {
- /* Grow buffer. */
- char *new_buf;
- size_t needed = bytes + (e->ptr - e->buf);
- size_t old_size = e->limit - e->buf;
-
- size_t new_size = old_size;
-
- while (new_size < needed) {
- new_size *= 2;
- }
-
- new_buf = upb_arena_realloc(e->arena, e->buf, old_size, new_size);
-
- if (new_buf == NULL) {
- return false;
- }
-
- e->ptr = new_buf + (e->ptr - e->buf);
- e->runbegin = new_buf + (e->runbegin - e->buf);
- e->limit = new_buf + new_size;
- e->buf = new_buf;
- }
-
- return true;
-}
-
-/* Call when "bytes" bytes have been writte at e->ptr. The caller *must* have
- * previously called reserve() with at least this many bytes. */
-static void encoder_advance(upb_pb_encoder *e, size_t bytes) {
- UPB_ASSERT((size_t)(e->limit - e->ptr) >= bytes);
- e->ptr += bytes;
-}
-
-/* Call when all of the bytes for a handler have been written. Flushes the
- * bytes if possible and necessary, returning false if this failed. */
-static bool commit(upb_pb_encoder *e) {
- if (!e->top) {
- /* We aren't inside a delimited region. Flush our accumulated bytes to
- * the output.
- *
- * TODO(haberman): in the future we may want to delay flushing for
- * efficiency reasons. */
- putbuf(e, e->buf, e->ptr - e->buf);
- e->ptr = e->buf;
- }
-
- return true;
-}
-
-/* Writes the given bytes to the buffer, handling reserve/advance. */
-static bool encode_bytes(upb_pb_encoder *e, const void *data, size_t len) {
- if (!reserve(e, len)) {
- return false;
- }
-
- memcpy(e->ptr, data, len);
- encoder_advance(e, len);
- return true;
-}
-
-/* Finish the current run by adding the run totals to the segment and message
- * length. */
-static void accumulate(upb_pb_encoder *e) {
- size_t run_len;
- UPB_ASSERT(e->ptr >= e->runbegin);
- run_len = e->ptr - e->runbegin;
- e->segptr->seglen += run_len;
- top(e)->msglen += run_len;
- e->runbegin = e->ptr;
-}
-
-/* Call to indicate the start of delimited region for which the full length is
- * not yet known. All data will be buffered until the length is known.
- * Delimited regions may be nested; their lengths will all be tracked properly. */
-static bool start_delim(upb_pb_encoder *e) {
- if (e->top) {
- /* We are already buffering, advance to the next segment and push it on the
- * stack. */
- accumulate(e);
-
- if (++e->top == e->stacklimit) {
- /* TODO(haberman): grow stack? */
- return false;
- }
-
- if (++e->segptr == e->seglimit) {
- /* Grow segment buffer. */
- size_t old_size =
- (e->seglimit - e->segbuf) * sizeof(upb_pb_encoder_segment);
- size_t new_size = old_size * 2;
- upb_pb_encoder_segment *new_buf =
- upb_arena_realloc(e->arena, e->segbuf, old_size, new_size);
-
- if (new_buf == NULL) {
- return false;
- }
-
- e->segptr = new_buf + (e->segptr - e->segbuf);
- e->seglimit = new_buf + (new_size / sizeof(upb_pb_encoder_segment));
- e->segbuf = new_buf;
- }
- } else {
- /* We were previously at the top level, start buffering. */
- e->segptr = e->segbuf;
- e->top = e->stack;
- e->runbegin = e->ptr;
- }
-
- *e->top = (int)(e->segptr - e->segbuf);
- e->segptr->seglen = 0;
- e->segptr->msglen = 0;
-
- return true;
-}
-
-/* Call to indicate the end of a delimited region. We now know the length of
- * the delimited region. If we are not nested inside any other delimited
- * regions, we can now emit all of the buffered data we accumulated. */
-static bool end_delim(upb_pb_encoder *e) {
- size_t msglen;
- accumulate(e);
- msglen = top(e)->msglen;
-
- if (e->top == e->stack) {
- /* All lengths are now available, emit all buffered data. */
- char buf[UPB_PB_VARINT_MAX_LEN];
- upb_pb_encoder_segment *s;
- const char *ptr = e->buf;
- for (s = e->segbuf; s <= e->segptr; s++) {
- size_t lenbytes = upb_vencode64(s->msglen, buf);
- putbuf(e, buf, lenbytes);
- putbuf(e, ptr, s->seglen);
- ptr += s->seglen;
- }
-
- e->ptr = e->buf;
- e->top = NULL;
- } else {
- /* Need to keep buffering; propagate length info into enclosing
- * submessages. */
- --e->top;
- top(e)->msglen += msglen + upb_varint_size(msglen);
- }
-
- return true;
-}
-
-
-/* tag_t **********************************************************************/
-
-/* A precomputed (pre-encoded) tag and length. */
-
-typedef struct {
- uint8_t bytes;
- char tag[7];
-} tag_t;
-
-/* Allocates a new tag for this field, and sets it in these handlerattr. */
-static void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt,
- upb_handlerattr *attr) {
- uint32_t n = upb_fielddef_number(f);
-
- tag_t *tag = upb_gmalloc(sizeof(tag_t));
- tag->bytes = upb_vencode64((n << 3) | wt, tag->tag);
-
- attr->handler_data = tag;
- upb_handlers_addcleanup(h, tag, upb_gfree);
-}
-
-static bool encode_tag(upb_pb_encoder *e, const tag_t *tag) {
- return encode_bytes(e, tag->tag, tag->bytes);
-}
-
-
-/* encoding of wire types *****************************************************/
-
-static bool encode_fixed64(upb_pb_encoder *e, uint64_t val) {
- /* TODO(haberman): byte-swap for big endian. */
- return encode_bytes(e, &val, sizeof(uint64_t));
-}
-
-static bool encode_fixed32(upb_pb_encoder *e, uint32_t val) {
- /* TODO(haberman): byte-swap for big endian. */
- return encode_bytes(e, &val, sizeof(uint32_t));
-}
-
-static bool encode_varint(upb_pb_encoder *e, uint64_t val) {
- if (!reserve(e, UPB_PB_VARINT_MAX_LEN)) {
- return false;
- }
-
- encoder_advance(e, upb_vencode64(val, e->ptr));
- return true;
-}
-
-static uint64_t dbl2uint64(double d) {
- uint64_t ret;
- memcpy(&ret, &d, sizeof(uint64_t));
- return ret;
-}
-
-static uint32_t flt2uint32(float d) {
- uint32_t ret;
- memcpy(&ret, &d, sizeof(uint32_t));
- return ret;
-}
-
-
-/* encoding of proto types ****************************************************/
-
-static bool startmsg(void *c, const void *hd) {
- upb_pb_encoder *e = c;
- UPB_UNUSED(hd);
- if (e->depth++ == 0) {
- upb_bytessink_start(e->output_, 0, &e->subc);
- }
- return true;
-}
-
-static bool endmsg(void *c, const void *hd, upb_status *status) {
- upb_pb_encoder *e = c;
- UPB_UNUSED(hd);
- UPB_UNUSED(status);
- if (--e->depth == 0) {
- upb_bytessink_end(e->output_);
- }
- return true;
-}
-
-static void *encode_startdelimfield(void *c, const void *hd) {
- bool ok = encode_tag(c, hd) && commit(c) && start_delim(c);
- return ok ? c : UPB_BREAK;
-}
-
-static bool encode_unknown(void *c, const void *hd, const char *buf,
- size_t len) {
- UPB_UNUSED(hd);
- return encode_bytes(c, buf, len) && commit(c);
-}
-
-static bool encode_enddelimfield(void *c, const void *hd) {
- UPB_UNUSED(hd);
- return end_delim(c);
-}
-
-static void *encode_startgroup(void *c, const void *hd) {
- return (encode_tag(c, hd) && commit(c)) ? c : UPB_BREAK;
-}
-
-static bool encode_endgroup(void *c, const void *hd) {
- return encode_tag(c, hd) && commit(c);
-}
-
-static void *encode_startstr(void *c, const void *hd, size_t size_hint) {
- UPB_UNUSED(size_hint);
- return encode_startdelimfield(c, hd);
-}
-
-static size_t encode_strbuf(void *c, const void *hd, const char *buf,
- size_t len, const upb_bufhandle *h) {
- UPB_UNUSED(hd);
- UPB_UNUSED(h);
- return encode_bytes(c, buf, len) ? len : 0;
-}
-
-#define T(type, ctype, convert, encode) \
- static bool encode_scalar_##type(void *e, const void *hd, ctype val) { \
- return encode_tag(e, hd) && encode(e, (convert)(val)) && commit(e); \
- } \
- static bool encode_packed_##type(void *e, const void *hd, ctype val) { \
- UPB_UNUSED(hd); \
- return encode(e, (convert)(val)); \
- }
-
-T(double, double, dbl2uint64, encode_fixed64)
-T(float, float, flt2uint32, encode_fixed32)
-T(int64, int64_t, uint64_t, encode_varint)
-T(int32, int32_t, int64_t, encode_varint)
-T(fixed64, uint64_t, uint64_t, encode_fixed64)
-T(fixed32, uint32_t, uint32_t, encode_fixed32)
-T(bool, bool, bool, encode_varint)
-T(uint32, uint32_t, uint32_t, encode_varint)
-T(uint64, uint64_t, uint64_t, encode_varint)
-T(enum, int32_t, uint32_t, encode_varint)
-T(sfixed32, int32_t, uint32_t, encode_fixed32)
-T(sfixed64, int64_t, uint64_t, encode_fixed64)
-T(sint32, int32_t, upb_zzenc_32, encode_varint)
-T(sint64, int64_t, upb_zzenc_64, encode_varint)
-
-#undef T
-
-
-/* code to build the handlers *************************************************/
-
-#include
-static void newhandlers_callback(const void *closure, upb_handlers *h) {
- const upb_msgdef *m;
- upb_msg_field_iter i;
-
- UPB_UNUSED(closure);
-
- upb_handlers_setstartmsg(h, startmsg, NULL);
- upb_handlers_setendmsg(h, endmsg, NULL);
- upb_handlers_setunknown(h, encode_unknown, NULL);
-
- m = upb_handlers_msgdef(h);
- for(upb_msg_field_begin(&i, m);
- !upb_msg_field_done(&i);
- upb_msg_field_next(&i)) {
- const upb_fielddef *f = upb_msg_iter_field(&i);
- bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) &&
- upb_fielddef_packed(f);
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
- upb_wiretype_t wt =
- packed ? UPB_WIRE_TYPE_DELIMITED
- : upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
-
- /* Pre-encode the tag for this field. */
- new_tag(h, f, wt, &attr);
-
- if (packed) {
- upb_handlers_setstartseq(h, f, encode_startdelimfield, &attr);
- upb_handlers_setendseq(h, f, encode_enddelimfield, &attr);
- }
-
-#define T(upper, lower, upbtype) \
- case UPB_DESCRIPTOR_TYPE_##upper: \
- if (packed) { \
- upb_handlers_set##upbtype(h, f, encode_packed_##lower, &attr); \
- } else { \
- upb_handlers_set##upbtype(h, f, encode_scalar_##lower, &attr); \
- } \
- break;
-
- switch (upb_fielddef_descriptortype(f)) {
- T(DOUBLE, double, double);
- T(FLOAT, float, float);
- T(INT64, int64, int64);
- T(INT32, int32, int32);
- T(FIXED64, fixed64, uint64);
- T(FIXED32, fixed32, uint32);
- T(BOOL, bool, bool);
- T(UINT32, uint32, uint32);
- T(UINT64, uint64, uint64);
- T(ENUM, enum, int32);
- T(SFIXED32, sfixed32, int32);
- T(SFIXED64, sfixed64, int64);
- T(SINT32, sint32, int32);
- T(SINT64, sint64, int64);
- case UPB_DESCRIPTOR_TYPE_STRING:
- case UPB_DESCRIPTOR_TYPE_BYTES:
- upb_handlers_setstartstr(h, f, encode_startstr, &attr);
- upb_handlers_setendstr(h, f, encode_enddelimfield, &attr);
- upb_handlers_setstring(h, f, encode_strbuf, &attr);
- break;
- case UPB_DESCRIPTOR_TYPE_MESSAGE:
- upb_handlers_setstartsubmsg(h, f, encode_startdelimfield, &attr);
- upb_handlers_setendsubmsg(h, f, encode_enddelimfield, &attr);
- break;
- case UPB_DESCRIPTOR_TYPE_GROUP: {
- /* Endgroup takes a different tag (wire_type = END_GROUP). */
- upb_handlerattr attr2 = UPB_HANDLERATTR_INIT;
- new_tag(h, f, UPB_WIRE_TYPE_END_GROUP, &attr2);
-
- upb_handlers_setstartsubmsg(h, f, encode_startgroup, &attr);
- upb_handlers_setendsubmsg(h, f, encode_endgroup, &attr2);
-
- break;
- }
- }
-
-#undef T
- }
-}
-
-void upb_pb_encoder_reset(upb_pb_encoder *e) {
- e->segptr = NULL;
- e->top = NULL;
- e->depth = 0;
-}
-
-
-/* public API *****************************************************************/
-
-upb_handlercache *upb_pb_encoder_newcache(void) {
- return upb_handlercache_new(newhandlers_callback, NULL);
-}
-
-upb_pb_encoder *upb_pb_encoder_create(upb_arena *arena, const upb_handlers *h,
- upb_bytessink output) {
- const size_t initial_bufsize = 256;
- const size_t initial_segbufsize = 16;
- /* TODO(haberman): make this configurable. */
- const size_t stack_size = 64;
-
- upb_pb_encoder *e = upb_arena_malloc(arena, sizeof(upb_pb_encoder));
- if (!e) return NULL;
-
- e->buf = upb_arena_malloc(arena, initial_bufsize);
- e->segbuf = upb_arena_malloc(arena, initial_segbufsize * sizeof(*e->segbuf));
- e->stack = upb_arena_malloc(arena, stack_size * sizeof(*e->stack));
-
- if (!e->buf || !e->segbuf || !e->stack) {
- return NULL;
- }
-
- e->limit = e->buf + initial_bufsize;
- e->seglimit = e->segbuf + initial_segbufsize;
- e->stacklimit = e->stack + stack_size;
-
- upb_pb_encoder_reset(e);
- upb_sink_reset(&e->input_, h, e);
-
- e->arena = arena;
- e->output_ = output;
- e->subc = output.closure;
- e->ptr = e->buf;
-
- return e;
-}
-
-upb_sink upb_pb_encoder_input(upb_pb_encoder *e) { return e->input_; }
-/*
- * upb::pb::TextPrinter
- *
- * OPT: This is not optimized at all. It uses printf() which parses the format
- * string every time, and it allocates memory for every put.
- */
-
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-
-struct upb_textprinter {
- upb_sink input_;
- upb_bytessink output_;
- int indent_depth_;
- bool single_line_;
- void *subc;
-};
-
-#define CHECK(x) if ((x) < 0) goto err;
-
-static const char *shortname(const char *longname) {
- const char *last = strrchr(longname, '.');
- return last ? last + 1 : longname;
-}
-
-static int indent(upb_textprinter *p) {
- int i;
- if (!p->single_line_)
- for (i = 0; i < p->indent_depth_; i++)
- upb_bytessink_putbuf(p->output_, p->subc, " ", 2, NULL);
- return 0;
-}
-
-static int endfield(upb_textprinter *p) {
- const char ch = (p->single_line_ ? ' ' : '\n');
- upb_bytessink_putbuf(p->output_, p->subc, &ch, 1, NULL);
- return 0;
-}
-
-static int putescaped(upb_textprinter *p, const char *buf, size_t len,
- bool preserve_utf8) {
- /* Based on CEscapeInternal() from Google's protobuf release. */
- char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf);
- const char *end = buf + len;
-
- /* I think hex is prettier and more useful, but proto2 uses octal; should
- * investigate whether it can parse hex also. */
- const bool use_hex = false;
- bool last_hex_escape = false; /* true if last output char was \xNN */
-
- for (; buf < end; buf++) {
- bool is_hex_escape;
-
- if (dstend - dst < 4) {
- upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
- dst = dstbuf;
- }
-
- is_hex_escape = false;
- switch (*buf) {
- case '\n': *(dst++) = '\\'; *(dst++) = 'n'; break;
- case '\r': *(dst++) = '\\'; *(dst++) = 'r'; break;
- case '\t': *(dst++) = '\\'; *(dst++) = 't'; break;
- case '\"': *(dst++) = '\\'; *(dst++) = '\"'; break;
- case '\'': *(dst++) = '\\'; *(dst++) = '\''; break;
- case '\\': *(dst++) = '\\'; *(dst++) = '\\'; break;
- default:
- /* Note that if we emit \xNN and the buf character after that is a hex
- * digit then that digit must be escaped too to prevent it being
- * interpreted as part of the character code by C. */
- if ((!preserve_utf8 || (uint8_t)*buf < 0x80) &&
- (!isprint(*buf) || (last_hex_escape && isxdigit(*buf)))) {
- sprintf(dst, (use_hex ? "\\x%02x" : "\\%03o"), (uint8_t)*buf);
- is_hex_escape = use_hex;
- dst += 4;
- } else {
- *(dst++) = *buf; break;
- }
- }
- last_hex_escape = is_hex_escape;
- }
- /* Flush remaining data. */
- upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
- return 0;
-}
-
-bool putf(upb_textprinter *p, const char *fmt, ...) {
- va_list args;
- va_list args_copy;
- char *str;
- int written;
- int len;
- bool ok;
-
- va_start(args, fmt);
-
- /* Run once to get the length of the string. */
- _upb_va_copy(args_copy, args);
- len = _upb_vsnprintf(NULL, 0, fmt, args_copy);
- va_end(args_copy);
-
- /* + 1 for NULL terminator (vsprintf() requires it even if we don't). */
- str = upb_gmalloc(len + 1);
- if (!str) return false;
- written = vsprintf(str, fmt, args);
- va_end(args);
- UPB_ASSERT(written == len);
-
- ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL);
- upb_gfree(str);
- return ok;
-}
-
-
-/* handlers *******************************************************************/
-
-static bool textprinter_startmsg(void *c, const void *hd) {
- upb_textprinter *p = c;
- UPB_UNUSED(hd);
- if (p->indent_depth_ == 0) {
- upb_bytessink_start(p->output_, 0, &p->subc);
- }
- return true;
-}
-
-static bool textprinter_endmsg(void *c, const void *hd, upb_status *s) {
- upb_textprinter *p = c;
- UPB_UNUSED(hd);
- UPB_UNUSED(s);
- if (p->indent_depth_ == 0) {
- upb_bytessink_end(p->output_);
- }
- return true;
-}
-
-#define TYPE(name, ctype, fmt) \
- static bool textprinter_put ## name(void *closure, const void *handler_data, \
- ctype val) { \
- upb_textprinter *p = closure; \
- const upb_fielddef *f = handler_data; \
- CHECK(indent(p)); \
- putf(p, "%s: " fmt, upb_fielddef_name(f), val); \
- CHECK(endfield(p)); \
- return true; \
- err: \
- return false; \
-}
-
-static bool textprinter_putbool(void *closure, const void *handler_data,
- bool val) {
- upb_textprinter *p = closure;
- const upb_fielddef *f = handler_data;
- CHECK(indent(p));
- putf(p, "%s: %s", upb_fielddef_name(f), val ? "true" : "false");
- CHECK(endfield(p));
- return true;
-err:
- return false;
-}
-
-#define STRINGIFY_HELPER(x) #x
-#define STRINGIFY_MACROVAL(x) STRINGIFY_HELPER(x)
-
-TYPE(int32, int32_t, "%" PRId32)
-TYPE(int64, int64_t, "%" PRId64)
-TYPE(uint32, uint32_t, "%" PRIu32)
-TYPE(uint64, uint64_t, "%" PRIu64)
-TYPE(float, float, "%." STRINGIFY_MACROVAL(FLT_DIG) "g")
-TYPE(double, double, "%." STRINGIFY_MACROVAL(DBL_DIG) "g")
-
-#undef TYPE
-
-/* Output a symbolic value from the enum if found, else just print as int32. */
-static bool textprinter_putenum(void *closure, const void *handler_data,
- int32_t val) {
- upb_textprinter *p = closure;
- const upb_fielddef *f = handler_data;
- const upb_enumdef *enum_def = upb_fielddef_enumsubdef(f);
- const char *label = upb_enumdef_iton(enum_def, val);
- if (label) {
- indent(p);
- putf(p, "%s: %s", upb_fielddef_name(f), label);
- endfield(p);
- } else {
- if (!textprinter_putint32(closure, handler_data, val))
- return false;
- }
- return true;
-}
-
-static void *textprinter_startstr(void *closure, const void *handler_data,
- size_t size_hint) {
- upb_textprinter *p = closure;
- const upb_fielddef *f = handler_data;
- UPB_UNUSED(size_hint);
- indent(p);
- putf(p, "%s: \"", upb_fielddef_name(f));
- return p;
-}
-
-static bool textprinter_endstr(void *closure, const void *handler_data) {
- upb_textprinter *p = closure;
- UPB_UNUSED(handler_data);
- putf(p, "\"");
- endfield(p);
- return true;
-}
-
-static size_t textprinter_putstr(void *closure, const void *hd, const char *buf,
- size_t len, const upb_bufhandle *handle) {
- upb_textprinter *p = closure;
- const upb_fielddef *f = hd;
- UPB_UNUSED(handle);
- CHECK(putescaped(p, buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING));
- return len;
-err:
- return 0;
-}
-
-static void *textprinter_startsubmsg(void *closure, const void *handler_data) {
- upb_textprinter *p = closure;
- const char *name = handler_data;
- CHECK(indent(p));
- putf(p, "%s {%c", name, p->single_line_ ? ' ' : '\n');
- p->indent_depth_++;
- return p;
-err:
- return UPB_BREAK;
-}
-
-static bool textprinter_endsubmsg(void *closure, const void *handler_data) {
- upb_textprinter *p = closure;
- UPB_UNUSED(handler_data);
- p->indent_depth_--;
- CHECK(indent(p));
- upb_bytessink_putbuf(p->output_, p->subc, "}", 1, NULL);
- CHECK(endfield(p));
- return true;
-err:
- return false;
-}
-
-static void onmreg(const void *c, upb_handlers *h) {
- const upb_msgdef *m = upb_handlers_msgdef(h);
- upb_msg_field_iter i;
- UPB_UNUSED(c);
-
- upb_handlers_setstartmsg(h, textprinter_startmsg, NULL);
- upb_handlers_setendmsg(h, textprinter_endmsg, NULL);
-
- for(upb_msg_field_begin(&i, m);
- !upb_msg_field_done(&i);
- upb_msg_field_next(&i)) {
- upb_fielddef *f = upb_msg_iter_field(&i);
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
- attr.handler_data = f;
- switch (upb_fielddef_type(f)) {
- case UPB_TYPE_INT32:
- upb_handlers_setint32(h, f, textprinter_putint32, &attr);
- break;
- case UPB_TYPE_INT64:
- upb_handlers_setint64(h, f, textprinter_putint64, &attr);
- break;
- case UPB_TYPE_UINT32:
- upb_handlers_setuint32(h, f, textprinter_putuint32, &attr);
- break;
- case UPB_TYPE_UINT64:
- upb_handlers_setuint64(h, f, textprinter_putuint64, &attr);
- break;
- case UPB_TYPE_FLOAT:
- upb_handlers_setfloat(h, f, textprinter_putfloat, &attr);
- break;
- case UPB_TYPE_DOUBLE:
- upb_handlers_setdouble(h, f, textprinter_putdouble, &attr);
- break;
- case UPB_TYPE_BOOL:
- upb_handlers_setbool(h, f, textprinter_putbool, &attr);
- break;
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES:
- upb_handlers_setstartstr(h, f, textprinter_startstr, &attr);
- upb_handlers_setstring(h, f, textprinter_putstr, &attr);
- upb_handlers_setendstr(h, f, textprinter_endstr, &attr);
- break;
- case UPB_TYPE_MESSAGE: {
- const char *name =
- upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_GROUP
- ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f)))
- : upb_fielddef_name(f);
- attr.handler_data = name;
- upb_handlers_setstartsubmsg(h, f, textprinter_startsubmsg, &attr);
- upb_handlers_setendsubmsg(h, f, textprinter_endsubmsg, &attr);
- break;
- }
- case UPB_TYPE_ENUM:
- upb_handlers_setint32(h, f, textprinter_putenum, &attr);
- break;
- }
- }
-}
-
-static void textprinter_reset(upb_textprinter *p, bool single_line) {
- p->single_line_ = single_line;
- p->indent_depth_ = 0;
-}
-
-
-/* Public API *****************************************************************/
-
-upb_textprinter *upb_textprinter_create(upb_arena *arena, const upb_handlers *h,
- upb_bytessink output) {
- upb_textprinter *p = upb_arena_malloc(arena, sizeof(upb_textprinter));
- if (!p) return NULL;
-
- p->output_ = output;
- upb_sink_reset(&p->input_, h, p);
- textprinter_reset(p, false);
-
- return p;
-}
-
-upb_handlercache *upb_textprinter_newcache(void) {
- return upb_handlercache_new(&onmreg, NULL);
-}
-
-upb_sink upb_textprinter_input(upb_textprinter *p) { return p->input_; }
-
-void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) {
- p->single_line_ = single_line;
-}
-
-
-/* Index is descriptor type. */
-const uint8_t upb_pb_native_wire_types[] = {
- UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */
- UPB_WIRE_TYPE_64BIT, /* DOUBLE */
- UPB_WIRE_TYPE_32BIT, /* FLOAT */
- UPB_WIRE_TYPE_VARINT, /* INT64 */
- UPB_WIRE_TYPE_VARINT, /* UINT64 */
- UPB_WIRE_TYPE_VARINT, /* INT32 */
- UPB_WIRE_TYPE_64BIT, /* FIXED64 */
- UPB_WIRE_TYPE_32BIT, /* FIXED32 */
- UPB_WIRE_TYPE_VARINT, /* BOOL */
- UPB_WIRE_TYPE_DELIMITED, /* STRING */
- UPB_WIRE_TYPE_START_GROUP, /* GROUP */
- UPB_WIRE_TYPE_DELIMITED, /* MESSAGE */
- UPB_WIRE_TYPE_DELIMITED, /* BYTES */
- UPB_WIRE_TYPE_VARINT, /* UINT32 */
- UPB_WIRE_TYPE_VARINT, /* ENUM */
- UPB_WIRE_TYPE_32BIT, /* SFIXED32 */
- UPB_WIRE_TYPE_64BIT, /* SFIXED64 */
- UPB_WIRE_TYPE_VARINT, /* SINT32 */
- UPB_WIRE_TYPE_VARINT, /* SINT64 */
-};
-
-/* A basic branch-based decoder, uses 32-bit values to get good performance
- * on 32-bit architectures (but performs well on 64-bits also).
- * This scheme comes from the original Google Protobuf implementation
- * (proto2). */
-upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r) {
- upb_decoderet err = {NULL, 0};
- const char *p = r.p;
- uint32_t low = (uint32_t)r.val;
- uint32_t high = 0;
- uint32_t b;
- b = *(p++); low |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
- b = *(p++); low |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
- b = *(p++); low |= (b & 0x7fU) << 28;
- high = (b & 0x7fU) >> 4; if (!(b & 0x80)) goto done;
- b = *(p++); high |= (b & 0x7fU) << 3; if (!(b & 0x80)) goto done;
- b = *(p++); high |= (b & 0x7fU) << 10; if (!(b & 0x80)) goto done;
- b = *(p++); high |= (b & 0x7fU) << 17; if (!(b & 0x80)) goto done;
- b = *(p++); high |= (b & 0x7fU) << 24; if (!(b & 0x80)) goto done;
- b = *(p++); high |= (b & 0x7fU) << 31; if (!(b & 0x80)) goto done;
- return err;
-
-done:
- r.val = ((uint64_t)high << 32) | low;
- r.p = p;
- return r;
-}
-
-/* Like the previous, but uses 64-bit values. */
-upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r) {
- const char *p = r.p;
- uint64_t val = r.val;
- uint64_t b;
- upb_decoderet err = {NULL, 0};
- b = *(p++); val |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
- b = *(p++); val |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
- b = *(p++); val |= (b & 0x7fU) << 28; if (!(b & 0x80)) goto done;
- b = *(p++); val |= (b & 0x7fU) << 35; if (!(b & 0x80)) goto done;
- b = *(p++); val |= (b & 0x7fU) << 42; if (!(b & 0x80)) goto done;
- b = *(p++); val |= (b & 0x7fU) << 49; if (!(b & 0x80)) goto done;
- b = *(p++); val |= (b & 0x7fU) << 56; if (!(b & 0x80)) goto done;
- b = *(p++); val |= (b & 0x7fU) << 63; if (!(b & 0x80)) goto done;
- return err;
-
-done:
- r.val = val;
- r.p = p;
- return r;
-}
-
-#line 1 "upb/json/parser.rl"
-/*
-** upb::json::Parser (upb_json_parser)
-**
-** A parser that uses the Ragel State Machine Compiler to generate
-** the finite automata.
-**
-** Ragel only natively handles regular languages, but we can manually
-** program it a bit to handle context-free languages like JSON, by using
-** the "fcall" and "fret" constructs.
-**
-** This parser can handle the basics, but needs several things to be fleshed
-** out:
-**
-** - handling of unicode escape sequences (including high surrogate pairs).
-** - properly check and report errors for unknown fields, stack overflow,
-** improper array nesting (or lack of nesting).
-** - handling of base64 sequences with padding characters.
-** - handling of push-back (non-success returns from sink functions).
-** - handling of keys/escape-sequences/etc that span input buffers.
-*/
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-
-
-#define UPB_JSON_MAX_DEPTH 64
-
-/* Type of value message */
-enum {
- VALUE_NULLVALUE = 0,
- VALUE_NUMBERVALUE = 1,
- VALUE_STRINGVALUE = 2,
- VALUE_BOOLVALUE = 3,
- VALUE_STRUCTVALUE = 4,
- VALUE_LISTVALUE = 5
-};
-
-/* Forward declare */
-static bool is_top_level(upb_json_parser *p);
-static bool is_wellknown_msg(upb_json_parser *p, upb_wellknowntype_t type);
-static bool is_wellknown_field(upb_json_parser *p, upb_wellknowntype_t type);
-
-static bool is_number_wrapper_object(upb_json_parser *p);
-static bool does_number_wrapper_start(upb_json_parser *p);
-static bool does_number_wrapper_end(upb_json_parser *p);
-
-static bool is_string_wrapper_object(upb_json_parser *p);
-static bool does_string_wrapper_start(upb_json_parser *p);
-static bool does_string_wrapper_end(upb_json_parser *p);
-
-static bool does_fieldmask_start(upb_json_parser *p);
-static bool does_fieldmask_end(upb_json_parser *p);
-static void start_fieldmask_object(upb_json_parser *p);
-static void end_fieldmask_object(upb_json_parser *p);
-
-static void start_wrapper_object(upb_json_parser *p);
-static void end_wrapper_object(upb_json_parser *p);
-
-static void start_value_object(upb_json_parser *p, int value_type);
-static void end_value_object(upb_json_parser *p);
-
-static void start_listvalue_object(upb_json_parser *p);
-static void end_listvalue_object(upb_json_parser *p);
-
-static void start_structvalue_object(upb_json_parser *p);
-static void end_structvalue_object(upb_json_parser *p);
-
-static void start_object(upb_json_parser *p);
-static void end_object(upb_json_parser *p);
-
-static void start_any_object(upb_json_parser *p, const char *ptr);
-static bool end_any_object(upb_json_parser *p, const char *ptr);
-
-static bool start_subobject(upb_json_parser *p);
-static void end_subobject(upb_json_parser *p);
-
-static void start_member(upb_json_parser *p);
-static void end_member(upb_json_parser *p);
-static bool end_membername(upb_json_parser *p);
-
-static void start_any_member(upb_json_parser *p, const char *ptr);
-static void end_any_member(upb_json_parser *p, const char *ptr);
-static bool end_any_membername(upb_json_parser *p);
-
-size_t parse(void *closure, const void *hd, const char *buf, size_t size,
- const upb_bufhandle *handle);
-static bool end(void *closure, const void *hd);
-
-static const char eof_ch = 'e';
-
-/* stringsink */
-typedef struct {
- upb_byteshandler handler;
- upb_bytessink sink;
- char *ptr;
- size_t len, size;
-} upb_stringsink;
-
-
-static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
- upb_stringsink *sink = _sink;
- sink->len = 0;
- UPB_UNUSED(hd);
- UPB_UNUSED(size_hint);
- return sink;
-}
-
-static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
- size_t len, const upb_bufhandle *handle) {
- upb_stringsink *sink = _sink;
- size_t new_size = sink->size;
-
- UPB_UNUSED(hd);
- UPB_UNUSED(handle);
-
- while (sink->len + len > new_size) {
- new_size *= 2;
- }
-
- if (new_size != sink->size) {
- sink->ptr = realloc(sink->ptr, new_size);
- sink->size = new_size;
- }
-
- memcpy(sink->ptr + sink->len, ptr, len);
- sink->len += len;
-
- return len;
-}
-
-void upb_stringsink_init(upb_stringsink *sink) {
- upb_byteshandler_init(&sink->handler);
- upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
- upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
-
- upb_bytessink_reset(&sink->sink, &sink->handler, sink);
-
- sink->size = 32;
- sink->ptr = malloc(sink->size);
- sink->len = 0;
-}
-
-void upb_stringsink_uninit(upb_stringsink *sink) { free(sink->ptr); }
-
-typedef struct {
- /* For encoding Any value field in binary format. */
- upb_handlercache *encoder_handlercache;
- upb_stringsink stringsink;
-
- /* For decoding Any value field in json format. */
- upb_json_codecache *parser_codecache;
- upb_sink sink;
- upb_json_parser *parser;
-
- /* Mark the range of uninterpreted values in json input before type url. */
- const char *before_type_url_start;
- const char *before_type_url_end;
-
- /* Mark the range of uninterpreted values in json input after type url. */
- const char *after_type_url_start;
-} upb_jsonparser_any_frame;
-
-typedef struct {
- upb_sink sink;
-
- /* The current message in which we're parsing, and the field whose value we're
- * expecting next. */
- const upb_msgdef *m;
- const upb_fielddef *f;
-
- /* The table mapping json name to fielddef for this message. */
- const upb_strtable *name_table;
-
- /* We are in a repeated-field context. We need this flag to decide whether to
- * handle the array as a normal repeated field or a
- * google.protobuf.ListValue/google.protobuf.Value. */
- bool is_repeated;
-
- /* We are in a repeated-field context, ready to emit mapentries as
- * submessages. This flag alters the start-of-object (open-brace) behavior to
- * begin a sequence of mapentry messages rather than a single submessage. */
- bool is_map;
-
- /* We are in a map-entry message context. This flag is set when parsing the
- * value field of a single map entry and indicates to all value-field parsers
- * (subobjects, strings, numbers, and bools) that the map-entry submessage
- * should end as soon as the value is parsed. */
- bool is_mapentry;
-
- /* If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent
- * message's map field that we're currently parsing. This differs from |f|
- * because |f| is the field in the *current* message (i.e., the map-entry
- * message itself), not the parent's field that leads to this map. */
- const upb_fielddef *mapfield;
-
- /* We are in an Any message context. This flag is set when parsing the Any
- * message and indicates to all field parsers (subobjects, strings, numbers,
- * and bools) that the parsed field should be serialized as binary data or
- * cached (type url not found yet). */
- bool is_any;
-
- /* The type of packed message in Any. */
- upb_jsonparser_any_frame *any_frame;
-
- /* True if the field to be parsed is unknown. */
- bool is_unknown_field;
-} upb_jsonparser_frame;
-
-static void init_frame(upb_jsonparser_frame* frame) {
- frame->m = NULL;
- frame->f = NULL;
- frame->name_table = NULL;
- frame->is_repeated = false;
- frame->is_map = false;
- frame->is_mapentry = false;
- frame->mapfield = NULL;
- frame->is_any = false;
- frame->any_frame = NULL;
- frame->is_unknown_field = false;
-}
-
-struct upb_json_parser {
- upb_arena *arena;
- const upb_json_parsermethod *method;
- upb_bytessink input_;
-
- /* Stack to track the JSON scopes we are in. */
- upb_jsonparser_frame stack[UPB_JSON_MAX_DEPTH];
- upb_jsonparser_frame *top;
- upb_jsonparser_frame *limit;
-
- upb_status *status;
-
- /* Ragel's internal parsing stack for the parsing state machine. */
- int current_state;
- int parser_stack[UPB_JSON_MAX_DEPTH];
- int parser_top;
-
- /* The handle for the current buffer. */
- const upb_bufhandle *handle;
-
- /* Accumulate buffer. See details in parser.rl. */
- const char *accumulated;
- size_t accumulated_len;
- char *accumulate_buf;
- size_t accumulate_buf_size;
-
- /* Multi-part text data. See details in parser.rl. */
- int multipart_state;
- upb_selector_t string_selector;
-
- /* Input capture. See details in parser.rl. */
- const char *capture;
-
- /* Intermediate result of parsing a unicode escape sequence. */
- uint32_t digit;
-
- /* For resolve type url in Any. */
- const upb_symtab *symtab;
-
- /* Whether to proceed if unknown field is met. */
- bool ignore_json_unknown;
-
- /* Cache for parsing timestamp due to base and zone are handled in different
- * handlers. */
- struct tm tm;
-};
-
-static upb_jsonparser_frame* start_jsonparser_frame(upb_json_parser *p) {
- upb_jsonparser_frame *inner;
- inner = p->top + 1;
- init_frame(inner);
- return inner;
-}
-
-struct upb_json_codecache {
- upb_arena *arena;
- upb_inttable methods; /* upb_msgdef* -> upb_json_parsermethod* */
-};
-
-struct upb_json_parsermethod {
- const upb_json_codecache *cache;
- upb_byteshandler input_handler_;
-
- /* Maps json_name -> fielddef */
- upb_strtable name_table;
-};
-
-#define PARSER_CHECK_RETURN(x) if (!(x)) return false
-
-static upb_jsonparser_any_frame *json_parser_any_frame_new(
- upb_json_parser *p) {
- upb_jsonparser_any_frame *frame;
-
- frame = upb_arena_malloc(p->arena, sizeof(upb_jsonparser_any_frame));
-
- frame->encoder_handlercache = upb_pb_encoder_newcache();
- frame->parser_codecache = upb_json_codecache_new();
- frame->parser = NULL;
- frame->before_type_url_start = NULL;
- frame->before_type_url_end = NULL;
- frame->after_type_url_start = NULL;
-
- upb_stringsink_init(&frame->stringsink);
-
- return frame;
-}
-
-static void json_parser_any_frame_set_payload_type(
- upb_json_parser *p,
- upb_jsonparser_any_frame *frame,
- const upb_msgdef *payload_type) {
- const upb_handlers *h;
- const upb_json_parsermethod *parser_method;
- upb_pb_encoder *encoder;
-
- /* Initialize encoder. */
- h = upb_handlercache_get(frame->encoder_handlercache, payload_type);
- encoder = upb_pb_encoder_create(p->arena, h, frame->stringsink.sink);
-
- /* Initialize parser. */
- parser_method = upb_json_codecache_get(frame->parser_codecache, payload_type);
- upb_sink_reset(&frame->sink, h, encoder);
- frame->parser =
- upb_json_parser_create(p->arena, parser_method, p->symtab, frame->sink,
- p->status, p->ignore_json_unknown);
-}
-
-static void json_parser_any_frame_free(upb_jsonparser_any_frame *frame) {
- upb_handlercache_free(frame->encoder_handlercache);
- upb_json_codecache_free(frame->parser_codecache);
- upb_stringsink_uninit(&frame->stringsink);
-}
-
-static bool json_parser_any_frame_has_type_url(
- upb_jsonparser_any_frame *frame) {
- return frame->parser != NULL;
-}
-
-static bool json_parser_any_frame_has_value_before_type_url(
- upb_jsonparser_any_frame *frame) {
- return frame->before_type_url_start != frame->before_type_url_end;
-}
-
-static bool json_parser_any_frame_has_value_after_type_url(
- upb_jsonparser_any_frame *frame) {
- return frame->after_type_url_start != NULL;
-}
-
-static bool json_parser_any_frame_has_value(
- upb_jsonparser_any_frame *frame) {
- return json_parser_any_frame_has_value_before_type_url(frame) ||
- json_parser_any_frame_has_value_after_type_url(frame);
-}
-
-static void json_parser_any_frame_set_before_type_url_end(
- upb_jsonparser_any_frame *frame,
- const char *ptr) {
- if (frame->parser == NULL) {
- frame->before_type_url_end = ptr;
- }
-}
-
-static void json_parser_any_frame_set_after_type_url_start_once(
- upb_jsonparser_any_frame *frame,
- const char *ptr) {
- if (json_parser_any_frame_has_type_url(frame) &&
- frame->after_type_url_start == NULL) {
- frame->after_type_url_start = ptr;
- }
-}
-
-/* Used to signal that a capture has been suspended. */
-static char suspend_capture;
-
-static upb_selector_t getsel_for_handlertype(upb_json_parser *p,
- upb_handlertype_t type) {
- upb_selector_t sel;
- bool ok = upb_handlers_getselector(p->top->f, type, &sel);
- UPB_ASSUME(ok);
- return sel;
-}
-
-static upb_selector_t parser_getsel(upb_json_parser *p) {
- return getsel_for_handlertype(
- p, upb_handlers_getprimitivehandlertype(p->top->f));
-}
-
-static bool check_stack(upb_json_parser *p) {
- if ((p->top + 1) == p->limit) {
- upb_status_seterrmsg(p->status, "Nesting too deep");
- return false;
- }
-
- return true;
-}
-
-static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) {
- upb_value v;
- const upb_json_codecache *cache = p->method->cache;
- bool ok;
- const upb_json_parsermethod *method;
-
- ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v);
- UPB_ASSUME(ok);
- method = upb_value_getconstptr(v);
-
- frame->name_table = &method->name_table;
-}
-
-/* There are GCC/Clang built-ins for overflow checking which we could start
- * using if there was any performance benefit to it. */
-
-static bool checked_add(size_t a, size_t b, size_t *c) {
- if (SIZE_MAX - a < b) return false;
- *c = a + b;
- return true;
-}
-
-static size_t saturating_multiply(size_t a, size_t b) {
- /* size_t is unsigned, so this is defined behavior even on overflow. */
- size_t ret = a * b;
- if (b != 0 && ret / b != a) {
- ret = SIZE_MAX;
- }
- return ret;
-}
-
-
-/* Base64 decoding ************************************************************/
-
-/* TODO(haberman): make this streaming. */
-
-static const signed char b64table[] = {
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */,
- 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
- 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
- -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
- 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
- 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
- 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1,
- -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
- 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
- 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
- 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1
-};
-
-/* Returns the table value sign-extended to 32 bits. Knowing that the upper
- * bits will be 1 for unrecognized characters makes it easier to check for
- * this error condition later (see below). */
-int32_t b64lookup(unsigned char ch) { return b64table[ch]; }
-
-/* Returns true if the given character is not a valid base64 character or
- * padding. */
-bool nonbase64(unsigned char ch) { return b64lookup(ch) == -1 && ch != '='; }
-
-static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
- size_t len) {
- const char *limit = ptr + len;
- for (; ptr < limit; ptr += 4) {
- uint32_t val;
- char output[3];
-
- if (limit - ptr < 4) {
- upb_status_seterrf(p->status,
- "Base64 input for bytes field not a multiple of 4: %s",
- upb_fielddef_name(p->top->f));
- return false;
- }
-
- val = b64lookup(ptr[0]) << 18 |
- b64lookup(ptr[1]) << 12 |
- b64lookup(ptr[2]) << 6 |
- b64lookup(ptr[3]);
-
- /* Test the upper bit; returns true if any of the characters returned -1. */
- if (val & 0x80000000) {
- goto otherchar;
- }
-
- output[0] = val >> 16;
- output[1] = (val >> 8) & 0xff;
- output[2] = val & 0xff;
- upb_sink_putstring(p->top->sink, sel, output, 3, NULL);
- }
- return true;
-
-otherchar:
- if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) ||
- nonbase64(ptr[3]) ) {
- upb_status_seterrf(p->status,
- "Non-base64 characters in bytes field: %s",
- upb_fielddef_name(p->top->f));
- return false;
- } if (ptr[2] == '=') {
- uint32_t val;
- char output;
-
- /* Last group contains only two input bytes, one output byte. */
- if (ptr[0] == '=' || ptr[1] == '=' || ptr[3] != '=') {
- goto badpadding;
- }
-
- val = b64lookup(ptr[0]) << 18 |
- b64lookup(ptr[1]) << 12;
-
- UPB_ASSERT(!(val & 0x80000000));
- output = val >> 16;
- upb_sink_putstring(p->top->sink, sel, &output, 1, NULL);
- return true;
- } else {
- uint32_t val;
- char output[2];
-
- /* Last group contains only three input bytes, two output bytes. */
- if (ptr[0] == '=' || ptr[1] == '=' || ptr[2] == '=') {
- goto badpadding;
- }
-
- val = b64lookup(ptr[0]) << 18 |
- b64lookup(ptr[1]) << 12 |
- b64lookup(ptr[2]) << 6;
-
- output[0] = val >> 16;
- output[1] = (val >> 8) & 0xff;
- upb_sink_putstring(p->top->sink, sel, output, 2, NULL);
- return true;
- }
-
-badpadding:
- upb_status_seterrf(p->status,
- "Incorrect base64 padding for field: %s (%.*s)",
- upb_fielddef_name(p->top->f),
- 4, ptr);
- return false;
-}
-
-
-/* Accumulate buffer **********************************************************/
-
-/* Functionality for accumulating a buffer.
- *
- * Some parts of the parser need an entire value as a contiguous string. For
- * example, to look up a member name in a hash table, or to turn a string into
- * a number, the relevant library routines need the input string to be in
- * contiguous memory, even if the value spanned two or more buffers in the
- * input. These routines handle that.
- *
- * In the common case we can just point to the input buffer to get this
- * contiguous string and avoid any actual copy. So we optimistically begin
- * this way. But there are a few cases where we must instead copy into a
- * separate buffer:
- *
- * 1. The string was not contiguous in the input (it spanned buffers).
- *
- * 2. The string included escape sequences that need to be interpreted to get
- * the true value in a contiguous buffer. */
-
-static void assert_accumulate_empty(upb_json_parser *p) {
- UPB_ASSERT(p->accumulated == NULL);
- UPB_ASSERT(p->accumulated_len == 0);
-}
-
-static void accumulate_clear(upb_json_parser *p) {
- p->accumulated = NULL;
- p->accumulated_len = 0;
-}
-
-/* Used internally by accumulate_append(). */
-static bool accumulate_realloc(upb_json_parser *p, size_t need) {
- void *mem;
- size_t old_size = p->accumulate_buf_size;
- size_t new_size = UPB_MAX(old_size, 128);
- while (new_size < need) {
- new_size = saturating_multiply(new_size, 2);
- }
-
- mem = upb_arena_realloc(p->arena, p->accumulate_buf, old_size, new_size);
- if (!mem) {
- upb_status_seterrmsg(p->status, "Out of memory allocating buffer.");
- return false;
- }
-
- p->accumulate_buf = mem;
- p->accumulate_buf_size = new_size;
- return true;
-}
-
-/* Logically appends the given data to the append buffer.
- * If "can_alias" is true, we will try to avoid actually copying, but the buffer
- * must be valid until the next accumulate_append() call (if any). */
-static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
- bool can_alias) {
- size_t need;
-
- if (!p->accumulated && can_alias) {
- p->accumulated = buf;
- p->accumulated_len = len;
- return true;
- }
-
- if (!checked_add(p->accumulated_len, len, &need)) {
- upb_status_seterrmsg(p->status, "Integer overflow.");
- return false;
- }
-
- if (need > p->accumulate_buf_size && !accumulate_realloc(p, need)) {
- return false;
- }
-
- if (p->accumulated != p->accumulate_buf) {
- memcpy(p->accumulate_buf, p->accumulated, p->accumulated_len);
- p->accumulated = p->accumulate_buf;
- }
-
- memcpy(p->accumulate_buf + p->accumulated_len, buf, len);
- p->accumulated_len += len;
- return true;
-}
-
-/* Returns a pointer to the data accumulated since the last accumulate_clear()
- * call, and writes the length to *len. This with point either to the input
- * buffer or a temporary accumulate buffer. */
-static const char *accumulate_getptr(upb_json_parser *p, size_t *len) {
- UPB_ASSERT(p->accumulated);
- *len = p->accumulated_len;
- return p->accumulated;
-}
-
-
-/* Mult-part text data ********************************************************/
-
-/* When we have text data in the input, it can often come in multiple segments.
- * For example, there may be some raw string data followed by an escape
- * sequence. The two segments are processed with different logic. Also buffer
- * seams in the input can cause multiple segments.
- *
- * As we see segments, there are two main cases for how we want to process them:
- *
- * 1. we want to push the captured input directly to string handlers.
- *
- * 2. we need to accumulate all the parts into a contiguous buffer for further
- * processing (field name lookup, string->number conversion, etc). */
-
-/* This is the set of states for p->multipart_state. */
-enum {
- /* We are not currently processing multipart data. */
- MULTIPART_INACTIVE = 0,
-
- /* We are processing multipart data by accumulating it into a contiguous
- * buffer. */
- MULTIPART_ACCUMULATE = 1,
-
- /* We are processing multipart data by pushing each part directly to the
- * current string handlers. */
- MULTIPART_PUSHEAGERLY = 2
-};
-
-/* Start a multi-part text value where we accumulate the data for processing at
- * the end. */
-static void multipart_startaccum(upb_json_parser *p) {
- assert_accumulate_empty(p);
- UPB_ASSERT(p->multipart_state == MULTIPART_INACTIVE);
- p->multipart_state = MULTIPART_ACCUMULATE;
-}
-
-/* Start a multi-part text value where we immediately push text data to a string
- * value with the given selector. */
-static void multipart_start(upb_json_parser *p, upb_selector_t sel) {
- assert_accumulate_empty(p);
- UPB_ASSERT(p->multipart_state == MULTIPART_INACTIVE);
- p->multipart_state = MULTIPART_PUSHEAGERLY;
- p->string_selector = sel;
-}
-
-static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
- bool can_alias) {
- switch (p->multipart_state) {
- case MULTIPART_INACTIVE:
- upb_status_seterrmsg(
- p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
- return false;
-
- case MULTIPART_ACCUMULATE:
- if (!accumulate_append(p, buf, len, can_alias)) {
- return false;
- }
- break;
-
- case MULTIPART_PUSHEAGERLY: {
- const upb_bufhandle *handle = can_alias ? p->handle : NULL;
- upb_sink_putstring(p->top->sink, p->string_selector, buf, len, handle);
- break;
- }
- }
-
- return true;
-}
-
-/* Note: this invalidates the accumulate buffer! Call only after reading its
- * contents. */
-static void multipart_end(upb_json_parser *p) {
- /* This is false sometimes. Probably a bug of some sort, but this code is
- * intended for deletion soon. */
- /* UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE); */
- p->multipart_state = MULTIPART_INACTIVE;
- accumulate_clear(p);
-}
-
-
-/* Input capture **************************************************************/
-
-/* Functionality for capturing a region of the input as text. Gracefully
- * handles the case where a buffer seam occurs in the middle of the captured
- * region. */
-
-static void capture_begin(upb_json_parser *p, const char *ptr) {
- UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE);
- UPB_ASSERT(p->capture == NULL);
- p->capture = ptr;
-}
-
-static bool capture_end(upb_json_parser *p, const char *ptr) {
- UPB_ASSERT(p->capture);
- if (multipart_text(p, p->capture, ptr - p->capture, true)) {
- p->capture = NULL;
- return true;
- } else {
- return false;
- }
-}
-
-/* This is called at the end of each input buffer (ie. when we have hit a
- * buffer seam). If we are in the middle of capturing the input, this
- * processes the unprocessed capture region. */
-static void capture_suspend(upb_json_parser *p, const char **ptr) {
- if (!p->capture) return;
-
- if (multipart_text(p, p->capture, *ptr - p->capture, false)) {
- /* We use this as a signal that we were in the middle of capturing, and
- * that capturing should resume at the beginning of the next buffer.
- *
- * We can't use *ptr here, because we have no guarantee that this pointer
- * will be valid when we resume (if the underlying memory is freed, then
- * using the pointer at all, even to compare to NULL, is likely undefined
- * behavior). */
- p->capture = &suspend_capture;
- } else {
- /* Need to back up the pointer to the beginning of the capture, since
- * we were not able to actually preserve it. */
- *ptr = p->capture;
- }
-}
-
-static void capture_resume(upb_json_parser *p, const char *ptr) {
- if (p->capture) {
- UPB_ASSERT(p->capture == &suspend_capture);
- p->capture = ptr;
- }
-}
-
-
-/* Callbacks from the parser **************************************************/
-
-/* These are the functions called directly from the parser itself.
- * We define these in the same order as their declarations in the parser. */
-
-static char escape_char(char in) {
- switch (in) {
- case 'r': return '\r';
- case 't': return '\t';
- case 'n': return '\n';
- case 'f': return '\f';
- case 'b': return '\b';
- case '/': return '/';
- case '"': return '"';
- case '\\': return '\\';
- default:
- UPB_ASSERT(0);
- return 'x';
- }
-}
-
-static bool escape(upb_json_parser *p, const char *ptr) {
- char ch = escape_char(*ptr);
- return multipart_text(p, &ch, 1, false);
-}
-
-static void start_hex(upb_json_parser *p) {
- p->digit = 0;
-}
-
-static void hexdigit(upb_json_parser *p, const char *ptr) {
- char ch = *ptr;
-
- p->digit <<= 4;
-
- if (ch >= '0' && ch <= '9') {
- p->digit += (ch - '0');
- } else if (ch >= 'a' && ch <= 'f') {
- p->digit += ((ch - 'a') + 10);
- } else {
- UPB_ASSERT(ch >= 'A' && ch <= 'F');
- p->digit += ((ch - 'A') + 10);
- }
-}
-
-static bool end_hex(upb_json_parser *p) {
- uint32_t codepoint = p->digit;
-
- /* emit the codepoint as UTF-8. */
- char utf8[3]; /* support \u0000 -- \uFFFF -- need only three bytes. */
- int length = 0;
- if (codepoint <= 0x7F) {
- utf8[0] = codepoint;
- length = 1;
- } else if (codepoint <= 0x07FF) {
- utf8[1] = (codepoint & 0x3F) | 0x80;
- codepoint >>= 6;
- utf8[0] = (codepoint & 0x1F) | 0xC0;
- length = 2;
- } else /* codepoint <= 0xFFFF */ {
- utf8[2] = (codepoint & 0x3F) | 0x80;
- codepoint >>= 6;
- utf8[1] = (codepoint & 0x3F) | 0x80;
- codepoint >>= 6;
- utf8[0] = (codepoint & 0x0F) | 0xE0;
- length = 3;
- }
- /* TODO(haberman): Handle high surrogates: if codepoint is a high surrogate
- * we have to wait for the next escape to get the full code point). */
-
- return multipart_text(p, utf8, length, false);
-}
-
-static void start_text(upb_json_parser *p, const char *ptr) {
- capture_begin(p, ptr);
-}
-
-static bool end_text(upb_json_parser *p, const char *ptr) {
- return capture_end(p, ptr);
-}
-
-static bool start_number(upb_json_parser *p, const char *ptr) {
- if (is_top_level(p)) {
- if (is_number_wrapper_object(p)) {
- start_wrapper_object(p);
- } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
- start_value_object(p, VALUE_NUMBERVALUE);
- } else {
- return false;
- }
- } else if (does_number_wrapper_start(p)) {
- if (!start_subobject(p)) {
- return false;
- }
- start_wrapper_object(p);
- } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
- if (!start_subobject(p)) {
- return false;
- }
- start_value_object(p, VALUE_NUMBERVALUE);
- }
-
- multipart_startaccum(p);
- capture_begin(p, ptr);
- return true;
-}
-
-static bool parse_number(upb_json_parser *p, bool is_quoted);
-
-static bool end_number_nontop(upb_json_parser *p, const char *ptr) {
- if (!capture_end(p, ptr)) {
- return false;
- }
-
- if (p->top->f == NULL) {
- multipart_end(p);
- return true;
- }
-
- return parse_number(p, false);
-}
-
-static bool end_number(upb_json_parser *p, const char *ptr) {
- if (!end_number_nontop(p, ptr)) {
- return false;
- }
-
- if (does_number_wrapper_end(p)) {
- end_wrapper_object(p);
- if (!is_top_level(p)) {
- end_subobject(p);
- }
- return true;
- }
-
- if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
- end_value_object(p);
- if (!is_top_level(p)) {
- end_subobject(p);
- }
- return true;
- }
-
- return true;
-}
-
-/* |buf| is NULL-terminated. |buf| itself will never include quotes;
- * |is_quoted| tells us whether this text originally appeared inside quotes. */
-static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
- bool is_quoted) {
- size_t len = strlen(buf);
- const char *bufend = buf + len;
- char *end;
- upb_fieldtype_t type = upb_fielddef_type(p->top->f);
- double val;
- double dummy;
- double inf = UPB_INFINITY;
-
- errno = 0;
-
- if (len == 0 || buf[0] == ' ') {
- return false;
- }
-
- /* For integer types, first try parsing with integer-specific routines.
- * If these succeed, they will be more accurate for int64/uint64 than
- * strtod().
- */
- switch (type) {
- case UPB_TYPE_ENUM:
- case UPB_TYPE_INT32: {
- long val = strtol(buf, &end, 0);
- if (errno == ERANGE || end != bufend) {
- break;
- } else if (val > INT32_MAX || val < INT32_MIN) {
- return false;
- } else {
- upb_sink_putint32(p->top->sink, parser_getsel(p), (int32_t)val);
- return true;
- }
- }
- case UPB_TYPE_UINT32: {
- unsigned long val = strtoul(buf, &end, 0);
- if (end != bufend) {
- break;
- } else if (val > UINT32_MAX || errno == ERANGE) {
- return false;
- } else {
- upb_sink_putuint32(p->top->sink, parser_getsel(p), (uint32_t)val);
- return true;
- }
- }
- /* XXX: We can't handle [u]int64 properly on 32-bit machines because
- * strto[u]ll isn't in C89. */
- case UPB_TYPE_INT64: {
- long val = strtol(buf, &end, 0);
- if (errno == ERANGE || end != bufend) {
- break;
- } else {
- upb_sink_putint64(p->top->sink, parser_getsel(p), val);
- return true;
- }
- }
- case UPB_TYPE_UINT64: {
- unsigned long val = strtoul(p->accumulated, &end, 0);
- if (end != bufend) {
- break;
- } else if (errno == ERANGE) {
- return false;
- } else {
- upb_sink_putuint64(p->top->sink, parser_getsel(p), val);
- return true;
- }
- }
- default:
- break;
- }
-
- if (type != UPB_TYPE_DOUBLE && type != UPB_TYPE_FLOAT && is_quoted) {
- /* Quoted numbers for integer types are not allowed to be in double form. */
- return false;
- }
-
- if (len == strlen("Infinity") && strcmp(buf, "Infinity") == 0) {
- /* C89 does not have an INFINITY macro. */
- val = inf;
- } else if (len == strlen("-Infinity") && strcmp(buf, "-Infinity") == 0) {
- val = -inf;
- } else {
- val = strtod(buf, &end);
- if (errno == ERANGE || end != bufend) {
- return false;
- }
- }
-
- switch (type) {
-#define CASE(capitaltype, smalltype, ctype, min, max) \
- case UPB_TYPE_ ## capitaltype: { \
- if (modf(val, &dummy) != 0 || val > max || val < min) { \
- return false; \
- } else { \
- upb_sink_put ## smalltype(p->top->sink, parser_getsel(p), \
- (ctype)val); \
- return true; \
- } \
- break; \
- }
- case UPB_TYPE_ENUM:
- CASE(INT32, int32, int32_t, INT32_MIN, INT32_MAX);
- CASE(INT64, int64, int64_t, INT64_MIN, INT64_MAX);
- CASE(UINT32, uint32, uint32_t, 0, UINT32_MAX);
- CASE(UINT64, uint64, uint64_t, 0, UINT64_MAX);
-#undef CASE
-
- case UPB_TYPE_DOUBLE:
- upb_sink_putdouble(p->top->sink, parser_getsel(p), val);
- return true;
- case UPB_TYPE_FLOAT:
- if ((val > FLT_MAX || val < -FLT_MAX) && val != inf && val != -inf) {
- return false;
- } else {
- upb_sink_putfloat(p->top->sink, parser_getsel(p), val);
- return true;
- }
- default:
- return false;
- }
-}
-
-static bool parse_number(upb_json_parser *p, bool is_quoted) {
- size_t len;
- const char *buf;
-
- /* strtol() and friends unfortunately do not support specifying the length of
- * the input string, so we need to force a copy into a NULL-terminated buffer. */
- if (!multipart_text(p, "\0", 1, false)) {
- return false;
- }
-
- buf = accumulate_getptr(p, &len);
-
- if (parse_number_from_buffer(p, buf, is_quoted)) {
- multipart_end(p);
- return true;
- } else {
- upb_status_seterrf(p->status, "error parsing number: %s", buf);
- multipart_end(p);
- return false;
- }
-}
-
-static bool parser_putbool(upb_json_parser *p, bool val) {
- bool ok;
-
- if (p->top->f == NULL) {
- return true;
- }
-
- if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
- upb_status_seterrf(p->status,
- "Boolean value specified for non-bool field: %s",
- upb_fielddef_name(p->top->f));
- return false;
- }
-
- ok = upb_sink_putbool(p->top->sink, parser_getsel(p), val);
- UPB_ASSERT(ok);
-
- return true;
-}
-
-static bool end_bool(upb_json_parser *p, bool val) {
- if (is_top_level(p)) {
- if (is_wellknown_msg(p, UPB_WELLKNOWN_BOOLVALUE)) {
- start_wrapper_object(p);
- } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
- start_value_object(p, VALUE_BOOLVALUE);
- } else {
- return false;
- }
- } else if (is_wellknown_field(p, UPB_WELLKNOWN_BOOLVALUE)) {
- if (!start_subobject(p)) {
- return false;
- }
- start_wrapper_object(p);
- } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
- if (!start_subobject(p)) {
- return false;
- }
- start_value_object(p, VALUE_BOOLVALUE);
- }
-
- if (p->top->is_unknown_field) {
- return true;
- }
-
- if (!parser_putbool(p, val)) {
- return false;
- }
-
- if (is_wellknown_msg(p, UPB_WELLKNOWN_BOOLVALUE)) {
- end_wrapper_object(p);
- if (!is_top_level(p)) {
- end_subobject(p);
- }
- return true;
- }
-
- if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
- end_value_object(p);
- if (!is_top_level(p)) {
- end_subobject(p);
- }
- return true;
- }
-
- return true;
-}
-
-static bool end_null(upb_json_parser *p) {
- const char *zero_ptr = "0";
-
- if (is_top_level(p)) {
- if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
- start_value_object(p, VALUE_NULLVALUE);
- } else {
- return true;
- }
- } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
- if (!start_subobject(p)) {
- return false;
- }
- start_value_object(p, VALUE_NULLVALUE);
- } else {
- return true;
- }
-
- /* Fill null_value field. */
- multipart_startaccum(p);
- capture_begin(p, zero_ptr);
- capture_end(p, zero_ptr + 1);
- parse_number(p, false);
-
- end_value_object(p);
- if (!is_top_level(p)) {
- end_subobject(p);
- }
-
- return true;
-}
-
-static bool start_any_stringval(upb_json_parser *p) {
- multipart_startaccum(p);
- return true;
-}
-
-static bool start_stringval(upb_json_parser *p) {
- if (is_top_level(p)) {
- if (is_string_wrapper_object(p) ||
- is_number_wrapper_object(p)) {
- start_wrapper_object(p);
- } else if (is_wellknown_msg(p, UPB_WELLKNOWN_FIELDMASK)) {
- start_fieldmask_object(p);
- return true;
- } else if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
- is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) {
- start_object(p);
- } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
- start_value_object(p, VALUE_STRINGVALUE);
- } else {
- return false;
- }
- } else if (does_string_wrapper_start(p) ||
- does_number_wrapper_start(p)) {
- if (!start_subobject(p)) {
- return false;
- }
- start_wrapper_object(p);
- } else if (does_fieldmask_start(p)) {
- if (!start_subobject(p)) {
- return false;
- }
- start_fieldmask_object(p);
- return true;
- } else if (is_wellknown_field(p, UPB_WELLKNOWN_TIMESTAMP) ||
- is_wellknown_field(p, UPB_WELLKNOWN_DURATION)) {
- if (!start_subobject(p)) {
- return false;
- }
- start_object(p);
- } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
- if (!start_subobject(p)) {
- return false;
- }
- start_value_object(p, VALUE_STRINGVALUE);
- }
-
- if (p->top->f == NULL) {
- multipart_startaccum(p);
- return true;
- }
-
- if (p->top->is_any) {
- return start_any_stringval(p);
- }
-
- if (upb_fielddef_isstring(p->top->f)) {
- upb_jsonparser_frame *inner;
- upb_selector_t sel;
-
- if (!check_stack(p)) return false;
-
- /* Start a new parser frame: parser frames correspond one-to-one with
- * handler frames, and string events occur in a sub-frame. */
- inner = start_jsonparser_frame(p);
- sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
- inner->m = p->top->m;
- inner->f = p->top->f;
- p->top = inner;
-
- if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) {
- /* For STRING fields we push data directly to the handlers as it is
- * parsed. We don't do this yet for BYTES fields, because our base64
- * decoder is not streaming.
- *
- * TODO(haberman): make base64 decoding streaming also. */
- multipart_start(p, getsel_for_handlertype(p, UPB_HANDLER_STRING));
- return true;
- } else {
- multipart_startaccum(p);
- return true;
- }
- } else if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL &&
- upb_fielddef_type(p->top->f) != UPB_TYPE_MESSAGE) {
- /* No need to push a frame -- numeric values in quotes remain in the
- * current parser frame. These values must accmulate so we can convert
- * them all at once at the end. */
- multipart_startaccum(p);
- return true;
- } else {
- upb_status_seterrf(p->status,
- "String specified for bool or submessage field: %s",
- upb_fielddef_name(p->top->f));
- return false;
- }
-}
-
-static bool end_any_stringval(upb_json_parser *p) {
- size_t len;
- const char *buf = accumulate_getptr(p, &len);
-
- /* Set type_url */
- upb_selector_t sel;
- upb_jsonparser_frame *inner;
- if (!check_stack(p)) return false;
- inner = p->top + 1;
-
- sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
- sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
- upb_sink_putstring(inner->sink, sel, buf, len, NULL);
- sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(inner->sink, sel);
-
- multipart_end(p);
-
- /* Resolve type url */
- if (strncmp(buf, "type.googleapis.com/", 20) == 0 && len > 20) {
- const upb_msgdef *payload_type = NULL;
- buf += 20;
- len -= 20;
-
- payload_type = upb_symtab_lookupmsg2(p->symtab, buf, len);
- if (payload_type == NULL) {
- upb_status_seterrf(
- p->status, "Cannot find packed type: %.*s\n", (int)len, buf);
- return false;
- }
-
- json_parser_any_frame_set_payload_type(p, p->top->any_frame, payload_type);
-
- return true;
- } else {
- upb_status_seterrf(
- p->status, "Invalid type url: %.*s\n", (int)len, buf);
- return false;
- }
-}
-
-static bool end_stringval_nontop(upb_json_parser *p) {
- bool ok = true;
-
- if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
- is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) {
- multipart_end(p);
- return true;
- }
-
- if (p->top->f == NULL) {
- multipart_end(p);
- return true;
- }
-
- if (p->top->is_any) {
- return end_any_stringval(p);
- }
-
- switch (upb_fielddef_type(p->top->f)) {
- case UPB_TYPE_BYTES:
- if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
- p->accumulated, p->accumulated_len)) {
- return false;
- }
- /* Fall through. */
-
- case UPB_TYPE_STRING: {
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(p->top->sink, sel);
- p->top--;
- break;
- }
-
- case UPB_TYPE_ENUM: {
- /* Resolve enum symbolic name to integer value. */
- const upb_enumdef *enumdef = upb_fielddef_enumsubdef(p->top->f);
-
- size_t len;
- const char *buf = accumulate_getptr(p, &len);
-
- int32_t int_val = 0;
- ok = upb_enumdef_ntoi(enumdef, buf, len, &int_val);
-
- if (ok) {
- upb_selector_t sel = parser_getsel(p);
- upb_sink_putint32(p->top->sink, sel, int_val);
- } else {
- if (p->ignore_json_unknown) {
- ok = true;
- /* TODO(teboring): Should also clean this field. */
- } else {
- upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf);
- }
- }
-
- break;
- }
-
- case UPB_TYPE_INT32:
- case UPB_TYPE_INT64:
- case UPB_TYPE_UINT32:
- case UPB_TYPE_UINT64:
- case UPB_TYPE_DOUBLE:
- case UPB_TYPE_FLOAT:
- ok = parse_number(p, true);
- break;
-
- default:
- UPB_ASSERT(false);
- upb_status_seterrmsg(p->status, "Internal error in JSON decoder");
- ok = false;
- break;
- }
-
- multipart_end(p);
-
- return ok;
-}
-
-static bool end_stringval(upb_json_parser *p) {
- /* FieldMask's stringvals have been ended when handling them. Only need to
- * close FieldMask here.*/
- if (does_fieldmask_end(p)) {
- end_fieldmask_object(p);
- if (!is_top_level(p)) {
- end_subobject(p);
- }
- return true;
- }
-
- if (!end_stringval_nontop(p)) {
- return false;
- }
-
- if (does_string_wrapper_end(p) ||
- does_number_wrapper_end(p)) {
- end_wrapper_object(p);
- if (!is_top_level(p)) {
- end_subobject(p);
- }
- return true;
- }
-
- if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
- end_value_object(p);
- if (!is_top_level(p)) {
- end_subobject(p);
- }
- return true;
- }
-
- if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
- is_wellknown_msg(p, UPB_WELLKNOWN_DURATION) ||
- is_wellknown_msg(p, UPB_WELLKNOWN_FIELDMASK)) {
- end_object(p);
- if (!is_top_level(p)) {
- end_subobject(p);
- }
- return true;
- }
-
- return true;
-}
-
-static void start_duration_base(upb_json_parser *p, const char *ptr) {
- capture_begin(p, ptr);
-}
-
-static bool end_duration_base(upb_json_parser *p, const char *ptr) {
- size_t len;
- const char *buf;
- char seconds_buf[14];
- char nanos_buf[12];
- char *end;
- int64_t seconds = 0;
- int32_t nanos = 0;
- double val = 0.0;
- const char *seconds_membername = "seconds";
- const char *nanos_membername = "nanos";
- size_t fraction_start;
-
- if (!capture_end(p, ptr)) {
- return false;
- }
-
- buf = accumulate_getptr(p, &len);
-
- memset(seconds_buf, 0, 14);
- memset(nanos_buf, 0, 12);
-
- /* Find out base end. The maximus duration is 315576000000, which cannot be
- * represented by double without losing precision. Thus, we need to handle
- * fraction and base separately. */
- for (fraction_start = 0; fraction_start < len && buf[fraction_start] != '.';
- fraction_start++);
-
- /* Parse base */
- memcpy(seconds_buf, buf, fraction_start);
- seconds = strtol(seconds_buf, &end, 10);
- if (errno == ERANGE || end != seconds_buf + fraction_start) {
- upb_status_seterrf(p->status, "error parsing duration: %s",
- seconds_buf);
- return false;
- }
-
- if (seconds > 315576000000) {
- upb_status_seterrf(p->status, "error parsing duration: "
- "maximum acceptable value is "
- "315576000000");
- return false;
- }
-
- if (seconds < -315576000000) {
- upb_status_seterrf(p->status, "error parsing duration: "
- "minimum acceptable value is "
- "-315576000000");
- return false;
- }
-
- /* Parse fraction */
- nanos_buf[0] = '0';
- memcpy(nanos_buf + 1, buf + fraction_start, len - fraction_start);
- val = strtod(nanos_buf, &end);
- if (errno == ERANGE || end != nanos_buf + len - fraction_start + 1) {
- upb_status_seterrf(p->status, "error parsing duration: %s",
- nanos_buf);
- return false;
- }
-
- nanos = val * 1000000000;
- if (seconds < 0) nanos = -nanos;
-
- /* Clean up buffer */
- multipart_end(p);
-
- /* Set seconds */
- start_member(p);
- capture_begin(p, seconds_membername);
- capture_end(p, seconds_membername + 7);
- end_membername(p);
- upb_sink_putint64(p->top->sink, parser_getsel(p), seconds);
- end_member(p);
-
- /* Set nanos */
- start_member(p);
- capture_begin(p, nanos_membername);
- capture_end(p, nanos_membername + 5);
- end_membername(p);
- upb_sink_putint32(p->top->sink, parser_getsel(p), nanos);
- end_member(p);
-
- /* Continue previous arena */
- multipart_startaccum(p);
-
- return true;
-}
-
-static int parse_timestamp_number(upb_json_parser *p) {
- size_t len;
- const char *buf;
- int val;
-
- /* atoi() and friends unfortunately do not support specifying the length of
- * the input string, so we need to force a copy into a NULL-terminated buffer. */
- multipart_text(p, "\0", 1, false);
-
- buf = accumulate_getptr(p, &len);
- val = atoi(buf);
- multipart_end(p);
- multipart_startaccum(p);
-
- return val;
-}
-
-static void start_year(upb_json_parser *p, const char *ptr) {
- capture_begin(p, ptr);
-}
-
-static bool end_year(upb_json_parser *p, const char *ptr) {
- if (!capture_end(p, ptr)) {
- return false;
- }
- p->tm.tm_year = parse_timestamp_number(p) - 1900;
- return true;
-}
-
-static void start_month(upb_json_parser *p, const char *ptr) {
- capture_begin(p, ptr);
-}
-
-static bool end_month(upb_json_parser *p, const char *ptr) {
- if (!capture_end(p, ptr)) {
- return false;
- }
- p->tm.tm_mon = parse_timestamp_number(p) - 1;
- return true;
-}
-
-static void start_day(upb_json_parser *p, const char *ptr) {
- capture_begin(p, ptr);
-}
-
-static bool end_day(upb_json_parser *p, const char *ptr) {
- if (!capture_end(p, ptr)) {
- return false;
- }
- p->tm.tm_mday = parse_timestamp_number(p);
- return true;
-}
-
-static void start_hour(upb_json_parser *p, const char *ptr) {
- capture_begin(p, ptr);
-}
-
-static bool end_hour(upb_json_parser *p, const char *ptr) {
- if (!capture_end(p, ptr)) {
- return false;
- }
- p->tm.tm_hour = parse_timestamp_number(p);
- return true;
-}
-
-static void start_minute(upb_json_parser *p, const char *ptr) {
- capture_begin(p, ptr);
-}
-
-static bool end_minute(upb_json_parser *p, const char *ptr) {
- if (!capture_end(p, ptr)) {
- return false;
- }
- p->tm.tm_min = parse_timestamp_number(p);
- return true;
-}
-
-static void start_second(upb_json_parser *p, const char *ptr) {
- capture_begin(p, ptr);
-}
-
-static bool end_second(upb_json_parser *p, const char *ptr) {
- if (!capture_end(p, ptr)) {
- return false;
- }
- p->tm.tm_sec = parse_timestamp_number(p);
- return true;
-}
-
-static void start_timestamp_base(upb_json_parser *p) {
- memset(&p->tm, 0, sizeof(struct tm));
-}
-
-static void start_timestamp_fraction(upb_json_parser *p, const char *ptr) {
- capture_begin(p, ptr);
-}
-
-static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) {
- size_t len;
- const char *buf;
- char nanos_buf[12];
- char *end;
- double val = 0.0;
- int32_t nanos;
- const char *nanos_membername = "nanos";
-
- memset(nanos_buf, 0, 12);
-
- if (!capture_end(p, ptr)) {
- return false;
- }
-
- buf = accumulate_getptr(p, &len);
-
- if (len > 10) {
- upb_status_seterrf(p->status,
- "error parsing timestamp: at most 9-digit fraction.");
- return false;
- }
-
- /* Parse nanos */
- nanos_buf[0] = '0';
- memcpy(nanos_buf + 1, buf, len);
- val = strtod(nanos_buf, &end);
-
- if (errno == ERANGE || end != nanos_buf + len + 1) {
- upb_status_seterrf(p->status, "error parsing timestamp nanos: %s",
- nanos_buf);
- return false;
- }
-
- nanos = val * 1000000000;
-
- /* Clean up previous environment */
- multipart_end(p);
-
- /* Set nanos */
- start_member(p);
- capture_begin(p, nanos_membername);
- capture_end(p, nanos_membername + 5);
- end_membername(p);
- upb_sink_putint32(p->top->sink, parser_getsel(p), nanos);
- end_member(p);
-
- /* Continue previous environment */
- multipart_startaccum(p);
-
- return true;
-}
-
-static void start_timestamp_zone(upb_json_parser *p, const char *ptr) {
- capture_begin(p, ptr);
-}
-
-static int div_round_up2(int n, int d) {
- return (n + d - 1) / d;
-}
-
-/* epoch_days(1970, 1, 1) == 1970-01-01 == 0. */
-static int epoch_days(int year, int month, int day) {
- static const uint16_t month_yday[12] = {0, 31, 59, 90, 120, 151,
- 181, 212, 243, 273, 304, 334};
- int febs_since_0 = month > 2 ? year + 1 : year;
- int leap_days_since_0 = div_round_up2(febs_since_0, 4) -
- div_round_up2(febs_since_0, 100) +
- div_round_up2(febs_since_0, 400);
- int days_since_0 =
- 365 * year + month_yday[month - 1] + (day - 1) + leap_days_since_0;
-
- /* Convert from 0-epoch (0001-01-01 BC) to Unix Epoch (1970-01-01 AD).
- * Since the "BC" system does not have a year zero, 1 BC == year zero. */
- return days_since_0 - 719528;
-}
-
-static int64_t upb_timegm(const struct tm *tp) {
- int64_t ret = epoch_days(tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday);
- ret = (ret * 24) + tp->tm_hour;
- ret = (ret * 60) + tp->tm_min;
- ret = (ret * 60) + tp->tm_sec;
- return ret;
-}
-
-static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
- size_t len;
- const char *buf;
- int hours;
- int64_t seconds;
- const char *seconds_membername = "seconds";
-
- if (!capture_end(p, ptr)) {
- return false;
- }
-
- buf = accumulate_getptr(p, &len);
-
- if (buf[0] != 'Z') {
- if (sscanf(buf + 1, "%2d:00", &hours) != 1) {
- upb_status_seterrf(p->status, "error parsing timestamp offset");
- return false;
- }
-
- if (buf[0] == '+') {
- hours = -hours;
- }
-
- p->tm.tm_hour += hours;
- }
-
- /* Normalize tm */
- seconds = upb_timegm(&p->tm);
-
- /* Check timestamp boundary */
- if (seconds < -62135596800) {
- upb_status_seterrf(p->status, "error parsing timestamp: "
- "minimum acceptable value is "
- "0001-01-01T00:00:00Z");
- return false;
- }
-
- /* Clean up previous environment */
- multipart_end(p);
-
- /* Set seconds */
- start_member(p);
- capture_begin(p, seconds_membername);
- capture_end(p, seconds_membername + 7);
- end_membername(p);
- upb_sink_putint64(p->top->sink, parser_getsel(p), seconds);
- end_member(p);
-
- /* Continue previous environment */
- multipart_startaccum(p);
-
- return true;
-}
-
-static void start_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
- capture_begin(p, ptr);
-}
-
-static bool end_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
- return capture_end(p, ptr);
-}
-
-static bool start_fieldmask_path(upb_json_parser *p) {
- upb_jsonparser_frame *inner;
- upb_selector_t sel;
-
- if (!check_stack(p)) return false;
-
- /* Start a new parser frame: parser frames correspond one-to-one with
- * handler frames, and string events occur in a sub-frame. */
- inner = start_jsonparser_frame(p);
- sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
- inner->m = p->top->m;
- inner->f = p->top->f;
- p->top = inner;
-
- multipart_startaccum(p);
- return true;
-}
-
-static bool lower_camel_push(
- upb_json_parser *p, upb_selector_t sel, const char *ptr, size_t len) {
- const char *limit = ptr + len;
- bool first = true;
- for (;ptr < limit; ptr++) {
- if (*ptr >= 'A' && *ptr <= 'Z' && !first) {
- char lower = tolower(*ptr);
- upb_sink_putstring(p->top->sink, sel, "_", 1, NULL);
- upb_sink_putstring(p->top->sink, sel, &lower, 1, NULL);
- } else {
- upb_sink_putstring(p->top->sink, sel, ptr, 1, NULL);
- }
- first = false;
- }
- return true;
-}
-
-static bool end_fieldmask_path(upb_json_parser *p) {
- upb_selector_t sel;
-
- if (!lower_camel_push(
- p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
- p->accumulated, p->accumulated_len)) {
- return false;
- }
-
- sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(p->top->sink, sel);
- p->top--;
-
- multipart_end(p);
- return true;
-}
-
-static void start_member(upb_json_parser *p) {
- UPB_ASSERT(!p->top->f);
- multipart_startaccum(p);
-}
-
-/* Helper: invoked during parse_mapentry() to emit the mapentry message's key
- * field based on the current contents of the accumulate buffer. */
-static bool parse_mapentry_key(upb_json_parser *p) {
-
- size_t len;
- const char *buf = accumulate_getptr(p, &len);
-
- /* Emit the key field. We do a bit of ad-hoc parsing here because the
- * parser state machine has already decided that this is a string field
- * name, and we are reinterpreting it as some arbitrary key type. In
- * particular, integer and bool keys are quoted, so we need to parse the
- * quoted string contents here. */
-
- p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
- if (p->top->f == NULL) {
- upb_status_seterrmsg(p->status, "mapentry message has no key");
- return false;
- }
- switch (upb_fielddef_type(p->top->f)) {
- case UPB_TYPE_INT32:
- case UPB_TYPE_INT64:
- case UPB_TYPE_UINT32:
- case UPB_TYPE_UINT64:
- /* Invoke end_number. The accum buffer has the number's text already. */
- if (!parse_number(p, true)) {
- return false;
- }
- break;
- case UPB_TYPE_BOOL:
- if (len == 4 && !strncmp(buf, "true", 4)) {
- if (!parser_putbool(p, true)) {
- return false;
- }
- } else if (len == 5 && !strncmp(buf, "false", 5)) {
- if (!parser_putbool(p, false)) {
- return false;
- }
- } else {
- upb_status_seterrmsg(p->status,
- "Map bool key not 'true' or 'false'");
- return false;
- }
- multipart_end(p);
- break;
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES: {
- upb_sink subsink;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(p->top->sink, sel, len, &subsink);
- sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
- upb_sink_putstring(subsink, sel, buf, len, NULL);
- sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(subsink, sel);
- multipart_end(p);
- break;
- }
- default:
- upb_status_seterrmsg(p->status, "Invalid field type for map key");
- return false;
- }
-
- return true;
-}
-
-/* Helper: emit one map entry (as a submessage in the map field sequence). This
- * is invoked from end_membername(), at the end of the map entry's key string,
- * with the map key in the accumulate buffer. It parses the key from that
- * buffer, emits the handler calls to start the mapentry submessage (setting up
- * its subframe in the process), and sets up state in the subframe so that the
- * value parser (invoked next) will emit the mapentry's value field and then
- * end the mapentry message. */
-
-static bool handle_mapentry(upb_json_parser *p) {
- const upb_fielddef *mapfield;
- const upb_msgdef *mapentrymsg;
- upb_jsonparser_frame *inner;
- upb_selector_t sel;
-
- /* Map entry: p->top->sink is the seq frame, so we need to start a frame
- * for the mapentry itself, and then set |f| in that frame so that the map
- * value field is parsed, and also set a flag to end the frame after the
- * map-entry value is parsed. */
- if (!check_stack(p)) return false;
-
- mapfield = p->top->mapfield;
- mapentrymsg = upb_fielddef_msgsubdef(mapfield);
-
- inner = start_jsonparser_frame(p);
- p->top->f = mapfield;
- sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
- upb_sink_startsubmsg(p->top->sink, sel, &inner->sink);
- inner->m = mapentrymsg;
- inner->mapfield = mapfield;
-
- /* Don't set this to true *yet* -- we reuse parsing handlers below to push
- * the key field value to the sink, and these handlers will pop the frame
- * if they see is_mapentry (when invoked by the parser state machine, they
- * would have just seen the map-entry value, not key). */
- inner->is_mapentry = false;
- p->top = inner;
-
- /* send STARTMSG in submsg frame. */
- upb_sink_startmsg(p->top->sink);
-
- parse_mapentry_key(p);
-
- /* Set up the value field to receive the map-entry value. */
- p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_VALUE);
- p->top->is_mapentry = true; /* set up to pop frame after value is parsed. */
- p->top->mapfield = mapfield;
- if (p->top->f == NULL) {
- upb_status_seterrmsg(p->status, "mapentry message has no value");
- return false;
- }
-
- return true;
-}
-
-static bool end_membername(upb_json_parser *p) {
- UPB_ASSERT(!p->top->f);
-
- if (!p->top->m) {
- p->top->is_unknown_field = true;
- multipart_end(p);
- return true;
- }
-
- if (p->top->is_any) {
- return end_any_membername(p);
- } else if (p->top->is_map) {
- return handle_mapentry(p);
- } else {
- size_t len;
- const char *buf = accumulate_getptr(p, &len);
- upb_value v;
-
- if (upb_strtable_lookup2(p->top->name_table, buf, len, &v)) {
- p->top->f = upb_value_getconstptr(v);
- multipart_end(p);
-
- return true;
- } else if (p->ignore_json_unknown) {
- p->top->is_unknown_field = true;
- multipart_end(p);
- return true;
- } else {
- upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf);
- return false;
- }
- }
-}
-
-static bool end_any_membername(upb_json_parser *p) {
- size_t len;
- const char *buf = accumulate_getptr(p, &len);
- upb_value v;
-
- if (len == 5 && strncmp(buf, "@type", len) == 0) {
- upb_strtable_lookup2(p->top->name_table, "type_url", 8, &v);
- p->top->f = upb_value_getconstptr(v);
- multipart_end(p);
- return true;
- } else {
- p->top->is_unknown_field = true;
- multipart_end(p);
- return true;
- }
-}
-
-static void end_member(upb_json_parser *p) {
- /* If we just parsed a map-entry value, end that frame too. */
- if (p->top->is_mapentry) {
- upb_selector_t sel;
- bool ok;
- const upb_fielddef *mapfield;
-
- UPB_ASSERT(p->top > p->stack);
- /* send ENDMSG on submsg. */
- upb_sink_endmsg(p->top->sink, p->status);
- mapfield = p->top->mapfield;
-
- /* send ENDSUBMSG in repeated-field-of-mapentries frame. */
- p->top--;
- ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
- UPB_ASSUME(ok);
- upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel);
- }
-
- p->top->f = NULL;
- p->top->is_unknown_field = false;
-}
-
-static void start_any_member(upb_json_parser *p, const char *ptr) {
- start_member(p);
- json_parser_any_frame_set_after_type_url_start_once(p->top->any_frame, ptr);
-}
-
-static void end_any_member(upb_json_parser *p, const char *ptr) {
- json_parser_any_frame_set_before_type_url_end(p->top->any_frame, ptr);
- end_member(p);
-}
-
-static bool start_subobject(upb_json_parser *p) {
- if (p->top->is_unknown_field) {
- if (!check_stack(p)) return false;
-
- p->top = start_jsonparser_frame(p);
- return true;
- }
-
- if (upb_fielddef_ismap(p->top->f)) {
- upb_jsonparser_frame *inner;
- upb_selector_t sel;
-
- /* Beginning of a map. Start a new parser frame in a repeated-field
- * context. */
- if (!check_stack(p)) return false;
-
- inner = start_jsonparser_frame(p);
- sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
- upb_sink_startseq(p->top->sink, sel, &inner->sink);
- inner->m = upb_fielddef_msgsubdef(p->top->f);
- inner->mapfield = p->top->f;
- inner->is_map = true;
- p->top = inner;
-
- return true;
- } else if (upb_fielddef_issubmsg(p->top->f)) {
- upb_jsonparser_frame *inner;
- upb_selector_t sel;
-
- /* Beginning of a subobject. Start a new parser frame in the submsg
- * context. */
- if (!check_stack(p)) return false;
-
- inner = start_jsonparser_frame(p);
- sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
- upb_sink_startsubmsg(p->top->sink, sel, &inner->sink);
- inner->m = upb_fielddef_msgsubdef(p->top->f);
- set_name_table(p, inner);
- p->top = inner;
-
- if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) {
- p->top->is_any = true;
- p->top->any_frame = json_parser_any_frame_new(p);
- } else {
- p->top->is_any = false;
- p->top->any_frame = NULL;
- }
-
- return true;
- } else {
- upb_status_seterrf(p->status,
- "Object specified for non-message/group field: %s",
- upb_fielddef_name(p->top->f));
- return false;
- }
-}
-
-static bool start_subobject_full(upb_json_parser *p) {
- if (is_top_level(p)) {
- if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
- start_value_object(p, VALUE_STRUCTVALUE);
- if (!start_subobject(p)) return false;
- start_structvalue_object(p);
- } else if (is_wellknown_msg(p, UPB_WELLKNOWN_STRUCT)) {
- start_structvalue_object(p);
- } else {
- return true;
- }
- } else if (is_wellknown_field(p, UPB_WELLKNOWN_STRUCT)) {
- if (!start_subobject(p)) return false;
- start_structvalue_object(p);
- } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
- if (!start_subobject(p)) return false;
- start_value_object(p, VALUE_STRUCTVALUE);
- if (!start_subobject(p)) return false;
- start_structvalue_object(p);
- }
-
- return start_subobject(p);
-}
-
-static void end_subobject(upb_json_parser *p) {
- if (is_top_level(p)) {
- return;
- }
-
- if (p->top->is_map) {
- upb_selector_t sel;
- p->top--;
- sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
- upb_sink_endseq(p->top->sink, sel);
- } else {
- upb_selector_t sel;
- bool is_unknown = p->top->m == NULL;
- p->top--;
- if (!is_unknown) {
- sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
- upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel);
- }
- }
-}
-
-static void end_subobject_full(upb_json_parser *p) {
- end_subobject(p);
-
- if (is_wellknown_msg(p, UPB_WELLKNOWN_STRUCT)) {
- end_structvalue_object(p);
- if (!is_top_level(p)) {
- end_subobject(p);
- }
- }
-
- if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
- end_value_object(p);
- if (!is_top_level(p)) {
- end_subobject(p);
- }
- }
-}
-
-static bool start_array(upb_json_parser *p) {
- upb_jsonparser_frame *inner;
- upb_selector_t sel;
-
- if (is_top_level(p)) {
- if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
- start_value_object(p, VALUE_LISTVALUE);
- if (!start_subobject(p)) return false;
- start_listvalue_object(p);
- } else if (is_wellknown_msg(p, UPB_WELLKNOWN_LISTVALUE)) {
- start_listvalue_object(p);
- } else {
- return false;
- }
- } else if (is_wellknown_field(p, UPB_WELLKNOWN_LISTVALUE) &&
- (!upb_fielddef_isseq(p->top->f) ||
- p->top->is_repeated)) {
- if (!start_subobject(p)) return false;
- start_listvalue_object(p);
- } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE) &&
- (!upb_fielddef_isseq(p->top->f) ||
- p->top->is_repeated)) {
- if (!start_subobject(p)) return false;
- start_value_object(p, VALUE_LISTVALUE);
- if (!start_subobject(p)) return false;
- start_listvalue_object(p);
- }
-
- if (p->top->is_unknown_field) {
- inner = start_jsonparser_frame(p);
- inner->is_unknown_field = true;
- p->top = inner;
-
- return true;
- }
-
- if (!upb_fielddef_isseq(p->top->f)) {
- upb_status_seterrf(p->status,
- "Array specified for non-repeated field: %s",
- upb_fielddef_name(p->top->f));
- return false;
- }
-
- if (!check_stack(p)) return false;
-
- inner = start_jsonparser_frame(p);
- sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
- upb_sink_startseq(p->top->sink, sel, &inner->sink);
- inner->m = p->top->m;
- inner->f = p->top->f;
- inner->is_repeated = true;
- p->top = inner;
-
- return true;
-}
-
-static void end_array(upb_json_parser *p) {
- upb_selector_t sel;
-
- UPB_ASSERT(p->top > p->stack);
-
- p->top--;
-
- if (p->top->is_unknown_field) {
- return;
- }
-
- sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
- upb_sink_endseq(p->top->sink, sel);
-
- if (is_wellknown_msg(p, UPB_WELLKNOWN_LISTVALUE)) {
- end_listvalue_object(p);
- if (!is_top_level(p)) {
- end_subobject(p);
- }
- }
-
- if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
- end_value_object(p);
- if (!is_top_level(p)) {
- end_subobject(p);
- }
- }
-}
-
-static void start_object(upb_json_parser *p) {
- if (!p->top->is_map && p->top->m != NULL) {
- upb_sink_startmsg(p->top->sink);
- }
-}
-
-static void end_object(upb_json_parser *p) {
- if (!p->top->is_map && p->top->m != NULL) {
- upb_sink_endmsg(p->top->sink, p->status);
- }
-}
-
-static void start_any_object(upb_json_parser *p, const char *ptr) {
- start_object(p);
- p->top->any_frame->before_type_url_start = ptr;
- p->top->any_frame->before_type_url_end = ptr;
-}
-
-static bool end_any_object(upb_json_parser *p, const char *ptr) {
- const char *value_membername = "value";
- bool is_well_known_packed = false;
- const char *packed_end = ptr + 1;
- upb_selector_t sel;
- upb_jsonparser_frame *inner;
-
- if (json_parser_any_frame_has_value(p->top->any_frame) &&
- !json_parser_any_frame_has_type_url(p->top->any_frame)) {
- upb_status_seterrmsg(p->status, "No valid type url");
- return false;
- }
-
- /* Well known types data is represented as value field. */
- if (upb_msgdef_wellknowntype(p->top->any_frame->parser->top->m) !=
- UPB_WELLKNOWN_UNSPECIFIED) {
- is_well_known_packed = true;
-
- if (json_parser_any_frame_has_value_before_type_url(p->top->any_frame)) {
- p->top->any_frame->before_type_url_start =
- memchr(p->top->any_frame->before_type_url_start, ':',
- p->top->any_frame->before_type_url_end -
- p->top->any_frame->before_type_url_start);
- if (p->top->any_frame->before_type_url_start == NULL) {
- upb_status_seterrmsg(p->status, "invalid data for well known type.");
- return false;
- }
- p->top->any_frame->before_type_url_start++;
- }
-
- if (json_parser_any_frame_has_value_after_type_url(p->top->any_frame)) {
- p->top->any_frame->after_type_url_start =
- memchr(p->top->any_frame->after_type_url_start, ':',
- (ptr + 1) -
- p->top->any_frame->after_type_url_start);
- if (p->top->any_frame->after_type_url_start == NULL) {
- upb_status_seterrmsg(p->status, "Invalid data for well known type.");
- return false;
- }
- p->top->any_frame->after_type_url_start++;
- packed_end = ptr;
- }
- }
-
- if (json_parser_any_frame_has_value_before_type_url(p->top->any_frame)) {
- if (!parse(p->top->any_frame->parser, NULL,
- p->top->any_frame->before_type_url_start,
- p->top->any_frame->before_type_url_end -
- p->top->any_frame->before_type_url_start, NULL)) {
- return false;
- }
- } else {
- if (!is_well_known_packed) {
- if (!parse(p->top->any_frame->parser, NULL, "{", 1, NULL)) {
- return false;
- }
- }
- }
-
- if (json_parser_any_frame_has_value_before_type_url(p->top->any_frame) &&
- json_parser_any_frame_has_value_after_type_url(p->top->any_frame)) {
- if (!parse(p->top->any_frame->parser, NULL, ",", 1, NULL)) {
- return false;
- }
- }
-
- if (json_parser_any_frame_has_value_after_type_url(p->top->any_frame)) {
- if (!parse(p->top->any_frame->parser, NULL,
- p->top->any_frame->after_type_url_start,
- packed_end - p->top->any_frame->after_type_url_start, NULL)) {
- return false;
- }
- } else {
- if (!is_well_known_packed) {
- if (!parse(p->top->any_frame->parser, NULL, "}", 1, NULL)) {
- return false;
- }
- }
- }
-
- if (!end(p->top->any_frame->parser, NULL)) {
- return false;
- }
-
- p->top->is_any = false;
-
- /* Set value */
- start_member(p);
- capture_begin(p, value_membername);
- capture_end(p, value_membername + 5);
- end_membername(p);
-
- if (!check_stack(p)) return false;
- inner = p->top + 1;
-
- sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
- sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
- upb_sink_putstring(inner->sink, sel, p->top->any_frame->stringsink.ptr,
- p->top->any_frame->stringsink.len, NULL);
- sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(inner->sink, sel);
-
- end_member(p);
-
- end_object(p);
-
- /* Deallocate any parse frame. */
- json_parser_any_frame_free(p->top->any_frame);
-
- return true;
-}
-
-static bool is_string_wrapper(const upb_msgdef *m) {
- upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
- return type == UPB_WELLKNOWN_STRINGVALUE ||
- type == UPB_WELLKNOWN_BYTESVALUE;
-}
-
-static bool is_fieldmask(const upb_msgdef *m) {
- upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
- return type == UPB_WELLKNOWN_FIELDMASK;
-}
-
-static void start_fieldmask_object(upb_json_parser *p) {
- const char *membername = "paths";
-
- start_object(p);
-
- /* Set up context for parsing value */
- start_member(p);
- capture_begin(p, membername);
- capture_end(p, membername + 5);
- end_membername(p);
-
- start_array(p);
-}
-
-static void end_fieldmask_object(upb_json_parser *p) {
- end_array(p);
- end_member(p);
- end_object(p);
-}
-
-static void start_wrapper_object(upb_json_parser *p) {
- const char *membername = "value";
-
- start_object(p);
-
- /* Set up context for parsing value */
- start_member(p);
- capture_begin(p, membername);
- capture_end(p, membername + 5);
- end_membername(p);
-}
-
-static void end_wrapper_object(upb_json_parser *p) {
- end_member(p);
- end_object(p);
-}
-
-static void start_value_object(upb_json_parser *p, int value_type) {
- const char *nullmember = "null_value";
- const char *numbermember = "number_value";
- const char *stringmember = "string_value";
- const char *boolmember = "bool_value";
- const char *structmember = "struct_value";
- const char *listmember = "list_value";
- const char *membername = "";
-
- switch (value_type) {
- case VALUE_NULLVALUE:
- membername = nullmember;
- break;
- case VALUE_NUMBERVALUE:
- membername = numbermember;
- break;
- case VALUE_STRINGVALUE:
- membername = stringmember;
- break;
- case VALUE_BOOLVALUE:
- membername = boolmember;
- break;
- case VALUE_STRUCTVALUE:
- membername = structmember;
- break;
- case VALUE_LISTVALUE:
- membername = listmember;
- break;
- }
-
- start_object(p);
-
- /* Set up context for parsing value */
- start_member(p);
- capture_begin(p, membername);
- capture_end(p, membername + strlen(membername));
- end_membername(p);
-}
-
-static void end_value_object(upb_json_parser *p) {
- end_member(p);
- end_object(p);
-}
-
-static void start_listvalue_object(upb_json_parser *p) {
- const char *membername = "values";
-
- start_object(p);
-
- /* Set up context for parsing value */
- start_member(p);
- capture_begin(p, membername);
- capture_end(p, membername + strlen(membername));
- end_membername(p);
-}
-
-static void end_listvalue_object(upb_json_parser *p) {
- end_member(p);
- end_object(p);
-}
-
-static void start_structvalue_object(upb_json_parser *p) {
- const char *membername = "fields";
-
- start_object(p);
-
- /* Set up context for parsing value */
- start_member(p);
- capture_begin(p, membername);
- capture_end(p, membername + strlen(membername));
- end_membername(p);
-}
-
-static void end_structvalue_object(upb_json_parser *p) {
- end_member(p);
- end_object(p);
-}
-
-static bool is_top_level(upb_json_parser *p) {
- return p->top == p->stack && p->top->f == NULL && !p->top->is_unknown_field;
-}
-
-static bool is_wellknown_msg(upb_json_parser *p, upb_wellknowntype_t type) {
- return p->top->m != NULL && upb_msgdef_wellknowntype(p->top->m) == type;
-}
-
-static bool is_wellknown_field(upb_json_parser *p, upb_wellknowntype_t type) {
- return p->top->f != NULL &&
- upb_fielddef_issubmsg(p->top->f) &&
- (upb_msgdef_wellknowntype(upb_fielddef_msgsubdef(p->top->f))
- == type);
-}
-
-static bool does_number_wrapper_start(upb_json_parser *p) {
- return p->top->f != NULL &&
- upb_fielddef_issubmsg(p->top->f) &&
- upb_msgdef_isnumberwrapper(upb_fielddef_msgsubdef(p->top->f));
-}
-
-static bool does_number_wrapper_end(upb_json_parser *p) {
- return p->top->m != NULL && upb_msgdef_isnumberwrapper(p->top->m);
-}
-
-static bool is_number_wrapper_object(upb_json_parser *p) {
- return p->top->m != NULL && upb_msgdef_isnumberwrapper(p->top->m);
-}
-
-static bool does_string_wrapper_start(upb_json_parser *p) {
- return p->top->f != NULL &&
- upb_fielddef_issubmsg(p->top->f) &&
- is_string_wrapper(upb_fielddef_msgsubdef(p->top->f));
-}
-
-static bool does_string_wrapper_end(upb_json_parser *p) {
- return p->top->m != NULL && is_string_wrapper(p->top->m);
-}
-
-static bool is_string_wrapper_object(upb_json_parser *p) {
- return p->top->m != NULL && is_string_wrapper(p->top->m);
-}
-
-static bool does_fieldmask_start(upb_json_parser *p) {
- return p->top->f != NULL &&
- upb_fielddef_issubmsg(p->top->f) &&
- is_fieldmask(upb_fielddef_msgsubdef(p->top->f));
-}
-
-static bool does_fieldmask_end(upb_json_parser *p) {
- return p->top->m != NULL && is_fieldmask(p->top->m);
-}
-
-#define CHECK_RETURN_TOP(x) if (!(x)) goto error
-
-
-/* The actual parser **********************************************************/
-
-/* What follows is the Ragel parser itself. The language is specified in Ragel
- * and the actions call our C functions above.
- *
- * Ragel has an extensive set of functionality, and we use only a small part of
- * it. There are many action types but we only use a few:
- *
- * ">" -- transition into a machine
- * "%" -- transition out of a machine
- * "@" -- transition into a final state of a machine.
- *
- * "@" transitions are tricky because a machine can transition into a final
- * state repeatedly. But in some cases we know this can't happen, for example
- * a string which is delimited by a final '"' can only transition into its
- * final state once, when the closing '"' is seen. */
-
-
-#line 2787 "upb/json/parser.rl"
-
-
-
-#line 2590 "upb/json/parser.c"
-static const char _json_actions[] = {
- 0, 1, 0, 1, 1, 1, 3, 1,
- 4, 1, 6, 1, 7, 1, 8, 1,
- 9, 1, 11, 1, 12, 1, 13, 1,
- 14, 1, 15, 1, 16, 1, 17, 1,
- 18, 1, 19, 1, 20, 1, 22, 1,
- 23, 1, 24, 1, 35, 1, 37, 1,
- 39, 1, 40, 1, 42, 1, 43, 1,
- 44, 1, 46, 1, 48, 1, 49, 1,
- 50, 1, 51, 1, 53, 1, 54, 2,
- 4, 9, 2, 5, 6, 2, 7, 3,
- 2, 7, 9, 2, 21, 26, 2, 25,
- 10, 2, 27, 28, 2, 29, 30, 2,
- 32, 34, 2, 33, 31, 2, 38, 36,
- 2, 40, 42, 2, 45, 2, 2, 46,
- 54, 2, 47, 36, 2, 49, 54, 2,
- 50, 54, 2, 51, 54, 2, 52, 41,
- 2, 53, 54, 3, 32, 34, 35, 4,
- 21, 26, 27, 28
-};
-
-static const short _json_key_offsets[] = {
- 0, 0, 12, 13, 18, 23, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 43, 44, 48, 53, 58, 63, 67,
- 71, 74, 77, 79, 83, 87, 89, 91,
- 96, 98, 100, 109, 115, 121, 127, 133,
- 135, 139, 142, 144, 146, 149, 150, 154,
- 156, 158, 160, 162, 163, 165, 167, 168,
- 170, 172, 173, 175, 177, 178, 180, 182,
- 183, 185, 187, 191, 193, 195, 196, 197,
- 198, 199, 201, 206, 208, 210, 212, 221,
- 222, 222, 222, 227, 232, 237, 238, 239,
- 240, 241, 241, 242, 243, 244, 244, 245,
- 246, 247, 247, 252, 253, 257, 262, 267,
- 272, 276, 276, 279, 282, 285, 288, 291,
- 294, 294, 294, 294, 294, 294
-};
-
-static const char _json_trans_keys[] = {
- 32, 34, 45, 91, 102, 110, 116, 123,
- 9, 13, 48, 57, 34, 32, 93, 125,
- 9, 13, 32, 44, 93, 9, 13, 32,
- 93, 125, 9, 13, 97, 108, 115, 101,
- 117, 108, 108, 114, 117, 101, 32, 34,
- 125, 9, 13, 34, 32, 58, 9, 13,
- 32, 93, 125, 9, 13, 32, 44, 125,
- 9, 13, 32, 44, 125, 9, 13, 32,
- 34, 9, 13, 45, 48, 49, 57, 48,
- 49, 57, 46, 69, 101, 48, 57, 69,
- 101, 48, 57, 43, 45, 48, 57, 48,
- 57, 48, 57, 46, 69, 101, 48, 57,
- 34, 92, 34, 92, 34, 47, 92, 98,
- 102, 110, 114, 116, 117, 48, 57, 65,
- 70, 97, 102, 48, 57, 65, 70, 97,
- 102, 48, 57, 65, 70, 97, 102, 48,
- 57, 65, 70, 97, 102, 34, 92, 45,
- 48, 49, 57, 48, 49, 57, 46, 115,
- 48, 57, 115, 48, 57, 34, 46, 115,
- 48, 57, 48, 57, 48, 57, 48, 57,
- 48, 57, 45, 48, 57, 48, 57, 45,
- 48, 57, 48, 57, 84, 48, 57, 48,
- 57, 58, 48, 57, 48, 57, 58, 48,
- 57, 48, 57, 43, 45, 46, 90, 48,
- 57, 48, 57, 58, 48, 48, 34, 48,
- 57, 43, 45, 90, 48, 57, 34, 44,
- 34, 44, 34, 44, 34, 45, 91, 102,
- 110, 116, 123, 48, 57, 34, 32, 93,
- 125, 9, 13, 32, 44, 93, 9, 13,
- 32, 93, 125, 9, 13, 97, 108, 115,
- 101, 117, 108, 108, 114, 117, 101, 32,
- 34, 125, 9, 13, 34, 32, 58, 9,
- 13, 32, 93, 125, 9, 13, 32, 44,
- 125, 9, 13, 32, 44, 125, 9, 13,
- 32, 34, 9, 13, 32, 9, 13, 32,
- 9, 13, 32, 9, 13, 32, 9, 13,
- 32, 9, 13, 32, 9, 13, 0
-};
-
-static const char _json_single_lengths[] = {
- 0, 8, 1, 3, 3, 3, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 3, 1, 2, 3, 3, 3, 2, 2,
- 1, 3, 0, 2, 2, 0, 0, 3,
- 2, 2, 9, 0, 0, 0, 0, 2,
- 2, 1, 2, 0, 1, 1, 2, 0,
- 0, 0, 0, 1, 0, 0, 1, 0,
- 0, 1, 0, 0, 1, 0, 0, 1,
- 0, 0, 4, 0, 0, 1, 1, 1,
- 1, 0, 3, 2, 2, 2, 7, 1,
- 0, 0, 3, 3, 3, 1, 1, 1,
- 1, 0, 1, 1, 1, 0, 1, 1,
- 1, 0, 3, 1, 2, 3, 3, 3,
- 2, 0, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0
-};
-
-static const char _json_range_lengths[] = {
- 0, 2, 0, 1, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 0, 1, 1, 1, 1, 1, 1,
- 1, 0, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 3, 3, 3, 3, 0,
- 1, 1, 0, 1, 1, 0, 1, 1,
- 1, 1, 1, 0, 1, 1, 0, 1,
- 1, 0, 1, 1, 0, 1, 1, 0,
- 1, 1, 0, 1, 1, 0, 0, 0,
- 0, 1, 1, 0, 0, 0, 1, 0,
- 0, 0, 1, 1, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 0, 1, 1, 1, 1,
- 1, 0, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0
-};
-
-static const short _json_index_offsets[] = {
- 0, 0, 11, 13, 18, 23, 28, 30,
- 32, 34, 36, 38, 40, 42, 44, 46,
- 48, 53, 55, 59, 64, 69, 74, 78,
- 82, 85, 89, 91, 95, 99, 101, 103,
- 108, 111, 114, 124, 128, 132, 136, 140,
- 143, 147, 150, 153, 155, 158, 160, 164,
- 166, 168, 170, 172, 174, 176, 178, 180,
- 182, 184, 186, 188, 190, 192, 194, 196,
- 198, 200, 202, 207, 209, 211, 213, 215,
- 217, 219, 221, 226, 229, 232, 235, 244,
- 246, 247, 248, 253, 258, 263, 265, 267,
- 269, 271, 272, 274, 276, 278, 279, 281,
- 283, 285, 286, 291, 293, 297, 302, 307,
- 312, 316, 317, 320, 323, 326, 329, 332,
- 335, 336, 337, 338, 339, 340
-};
-
-static const unsigned char _json_indicies[] = {
- 0, 2, 3, 4, 5, 6, 7, 8,
- 0, 3, 1, 9, 1, 11, 12, 1,
- 11, 10, 13, 14, 12, 13, 1, 14,
- 1, 1, 14, 10, 15, 1, 16, 1,
- 17, 1, 18, 1, 19, 1, 20, 1,
- 21, 1, 22, 1, 23, 1, 24, 1,
- 25, 26, 27, 25, 1, 28, 1, 29,
- 30, 29, 1, 30, 1, 1, 30, 31,
- 32, 33, 34, 32, 1, 35, 36, 27,
- 35, 1, 36, 26, 36, 1, 37, 38,
- 39, 1, 38, 39, 1, 41, 42, 42,
- 40, 43, 1, 42, 42, 43, 40, 44,
- 44, 45, 1, 45, 1, 45, 40, 41,
- 42, 42, 39, 40, 47, 48, 46, 50,
- 51, 49, 52, 52, 52, 52, 52, 52,
- 52, 52, 53, 1, 54, 54, 54, 1,
- 55, 55, 55, 1, 56, 56, 56, 1,
- 57, 57, 57, 1, 59, 60, 58, 61,
- 62, 63, 1, 64, 65, 1, 66, 67,
- 1, 68, 1, 67, 68, 1, 69, 1,
- 66, 67, 65, 1, 70, 1, 71, 1,
- 72, 1, 73, 1, 74, 1, 75, 1,
- 76, 1, 77, 1, 78, 1, 79, 1,
- 80, 1, 81, 1, 82, 1, 83, 1,
- 84, 1, 85, 1, 86, 1, 87, 1,
- 88, 1, 89, 89, 90, 91, 1, 92,
- 1, 93, 1, 94, 1, 95, 1, 96,
- 1, 97, 1, 98, 1, 99, 99, 100,
- 98, 1, 102, 1, 101, 104, 105, 103,
- 1, 1, 101, 106, 107, 108, 109, 110,
- 111, 112, 107, 1, 113, 1, 114, 115,
- 117, 118, 1, 117, 116, 119, 120, 118,
- 119, 1, 120, 1, 1, 120, 116, 121,
- 1, 122, 1, 123, 1, 124, 1, 125,
- 126, 1, 127, 1, 128, 1, 129, 130,
- 1, 131, 1, 132, 1, 133, 134, 135,
- 136, 134, 1, 137, 1, 138, 139, 138,
- 1, 139, 1, 1, 139, 140, 141, 142,
- 143, 141, 1, 144, 145, 136, 144, 1,
- 145, 135, 145, 1, 146, 147, 147, 1,
- 148, 148, 1, 149, 149, 1, 150, 150,
- 1, 151, 151, 1, 152, 152, 1, 1,
- 1, 1, 1, 1, 1, 0
-};
-
-static const char _json_trans_targs[] = {
- 1, 0, 2, 107, 3, 6, 10, 13,
- 16, 106, 4, 3, 106, 4, 5, 7,
- 8, 9, 108, 11, 12, 109, 14, 15,
- 110, 16, 17, 111, 18, 18, 19, 20,
- 21, 22, 111, 21, 22, 24, 25, 31,
- 112, 26, 28, 27, 29, 30, 33, 113,
- 34, 33, 113, 34, 32, 35, 36, 37,
- 38, 39, 33, 113, 34, 41, 42, 46,
- 42, 46, 43, 45, 44, 114, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, 64, 65,
- 66, 67, 73, 72, 68, 69, 70, 71,
- 72, 115, 74, 67, 72, 76, 116, 76,
- 116, 77, 79, 81, 82, 85, 90, 94,
- 98, 80, 117, 117, 83, 82, 80, 83,
- 84, 86, 87, 88, 89, 117, 91, 92,
- 93, 117, 95, 96, 97, 117, 98, 99,
- 105, 100, 100, 101, 102, 103, 104, 105,
- 103, 104, 117, 106, 106, 106, 106, 106,
- 106
-};
-
-static const unsigned char _json_trans_actions[] = {
- 0, 0, 113, 107, 53, 0, 0, 0,
- 125, 59, 45, 0, 55, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 101, 51, 47, 0, 0, 45,
- 49, 49, 104, 0, 0, 0, 0, 0,
- 3, 0, 0, 0, 0, 0, 5, 15,
- 0, 0, 71, 7, 13, 0, 74, 9,
- 9, 9, 77, 80, 11, 37, 37, 37,
- 0, 0, 0, 39, 0, 41, 86, 0,
- 0, 0, 17, 19, 0, 21, 23, 0,
- 25, 27, 0, 29, 31, 0, 33, 35,
- 0, 135, 83, 135, 0, 0, 0, 0,
- 0, 92, 0, 89, 89, 98, 43, 0,
- 131, 95, 113, 107, 53, 0, 0, 0,
- 125, 59, 69, 110, 45, 0, 55, 0,
- 0, 0, 0, 0, 0, 119, 0, 0,
- 0, 122, 0, 0, 0, 116, 0, 101,
- 51, 47, 0, 0, 45, 49, 49, 104,
- 0, 0, 128, 0, 57, 63, 65, 61,
- 67
-};
-
-static const unsigned char _json_eof_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 0, 1, 0, 0, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 57, 63, 65, 61, 67,
- 0, 0, 0, 0, 0, 0
-};
-
-static const int json_start = 1;
-
-static const int json_en_number_machine = 23;
-static const int json_en_string_machine = 32;
-static const int json_en_duration_machine = 40;
-static const int json_en_timestamp_machine = 47;
-static const int json_en_fieldmask_machine = 75;
-static const int json_en_value_machine = 78;
-static const int json_en_main = 1;
-
-
-#line 2790 "upb/json/parser.rl"
-
-size_t parse(void *closure, const void *hd, const char *buf, size_t size,
- const upb_bufhandle *handle) {
- upb_json_parser *parser = closure;
-
- /* Variables used by Ragel's generated code. */
- int cs = parser->current_state;
- int *stack = parser->parser_stack;
- int top = parser->parser_top;
-
- const char *p = buf;
- const char *pe = buf + size;
- const char *eof = &eof_ch;
-
- parser->handle = handle;
-
- UPB_UNUSED(hd);
- UPB_UNUSED(handle);
-
- capture_resume(parser, buf);
-
-
-#line 2868 "upb/json/parser.c"
- {
- int _klen;
- unsigned int _trans;
- const char *_acts;
- unsigned int _nacts;
- const char *_keys;
-
- if ( p == pe )
- goto _test_eof;
- if ( cs == 0 )
- goto _out;
-_resume:
- _keys = _json_trans_keys + _json_key_offsets[cs];
- _trans = _json_index_offsets[cs];
-
- _klen = _json_single_lengths[cs];
- if ( _klen > 0 ) {
- const char *_lower = _keys;
- const char *_mid;
- const char *_upper = _keys + _klen - 1;
- while (1) {
- if ( _upper < _lower )
- break;
-
- _mid = _lower + ((_upper-_lower) >> 1);
- if ( (*p) < *_mid )
- _upper = _mid - 1;
- else if ( (*p) > *_mid )
- _lower = _mid + 1;
- else {
- _trans += (unsigned int)(_mid - _keys);
- goto _match;
- }
- }
- _keys += _klen;
- _trans += _klen;
- }
-
- _klen = _json_range_lengths[cs];
- if ( _klen > 0 ) {
- const char *_lower = _keys;
- const char *_mid;
- const char *_upper = _keys + (_klen<<1) - 2;
- while (1) {
- if ( _upper < _lower )
- break;
-
- _mid = _lower + (((_upper-_lower) >> 1) & ~1);
- if ( (*p) < _mid[0] )
- _upper = _mid - 2;
- else if ( (*p) > _mid[1] )
- _lower = _mid + 2;
- else {
- _trans += (unsigned int)((_mid - _keys)>>1);
- goto _match;
- }
- }
- _trans += _klen;
- }
-
-_match:
- _trans = _json_indicies[_trans];
- cs = _json_trans_targs[_trans];
-
- if ( _json_trans_actions[_trans] == 0 )
- goto _again;
-
- _acts = _json_actions + _json_trans_actions[_trans];
- _nacts = (unsigned int) *_acts++;
- while ( _nacts-- > 0 )
- {
- switch ( *_acts++ )
- {
- case 1:
-#line 2595 "upb/json/parser.rl"
- { p--; {cs = stack[--top]; goto _again;} }
- break;
- case 2:
-#line 2597 "upb/json/parser.rl"
- { p--; {stack[top++] = cs; cs = 23;goto _again;} }
- break;
- case 3:
-#line 2601 "upb/json/parser.rl"
- { start_text(parser, p); }
- break;
- case 4:
-#line 2602 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_text(parser, p)); }
- break;
- case 5:
-#line 2608 "upb/json/parser.rl"
- { start_hex(parser); }
- break;
- case 6:
-#line 2609 "upb/json/parser.rl"
- { hexdigit(parser, p); }
- break;
- case 7:
-#line 2610 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_hex(parser)); }
- break;
- case 8:
-#line 2616 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(escape(parser, p)); }
- break;
- case 9:
-#line 2622 "upb/json/parser.rl"
- { p--; {cs = stack[--top]; goto _again;} }
- break;
- case 10:
-#line 2627 "upb/json/parser.rl"
- { start_year(parser, p); }
- break;
- case 11:
-#line 2628 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_year(parser, p)); }
- break;
- case 12:
-#line 2632 "upb/json/parser.rl"
- { start_month(parser, p); }
- break;
- case 13:
-#line 2633 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_month(parser, p)); }
- break;
- case 14:
-#line 2637 "upb/json/parser.rl"
- { start_day(parser, p); }
- break;
- case 15:
-#line 2638 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_day(parser, p)); }
- break;
- case 16:
-#line 2642 "upb/json/parser.rl"
- { start_hour(parser, p); }
- break;
- case 17:
-#line 2643 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_hour(parser, p)); }
- break;
- case 18:
-#line 2647 "upb/json/parser.rl"
- { start_minute(parser, p); }
- break;
- case 19:
-#line 2648 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_minute(parser, p)); }
- break;
- case 20:
-#line 2652 "upb/json/parser.rl"
- { start_second(parser, p); }
- break;
- case 21:
-#line 2653 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_second(parser, p)); }
- break;
- case 22:
-#line 2658 "upb/json/parser.rl"
- { start_duration_base(parser, p); }
- break;
- case 23:
-#line 2659 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_duration_base(parser, p)); }
- break;
- case 24:
-#line 2661 "upb/json/parser.rl"
- { p--; {cs = stack[--top]; goto _again;} }
- break;
- case 25:
-#line 2666 "upb/json/parser.rl"
- { start_timestamp_base(parser); }
- break;
- case 26:
-#line 2668 "upb/json/parser.rl"
- { start_timestamp_fraction(parser, p); }
- break;
- case 27:
-#line 2669 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); }
- break;
- case 28:
-#line 2671 "upb/json/parser.rl"
- { start_timestamp_zone(parser, p); }
- break;
- case 29:
-#line 2672 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); }
- break;
- case 30:
-#line 2674 "upb/json/parser.rl"
- { p--; {cs = stack[--top]; goto _again;} }
- break;
- case 31:
-#line 2679 "upb/json/parser.rl"
- { start_fieldmask_path_text(parser, p); }
- break;
- case 32:
-#line 2680 "upb/json/parser.rl"
- { end_fieldmask_path_text(parser, p); }
- break;
- case 33:
-#line 2685 "upb/json/parser.rl"
- { start_fieldmask_path(parser); }
- break;
- case 34:
-#line 2686 "upb/json/parser.rl"
- { end_fieldmask_path(parser); }
- break;
- case 35:
-#line 2692 "upb/json/parser.rl"
- { p--; {cs = stack[--top]; goto _again;} }
- break;
- case 36:
-#line 2697 "upb/json/parser.rl"
- {
- if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) {
- {stack[top++] = cs; cs = 47;goto _again;}
- } else if (is_wellknown_msg(parser, UPB_WELLKNOWN_DURATION)) {
- {stack[top++] = cs; cs = 40;goto _again;}
- } else if (is_wellknown_msg(parser, UPB_WELLKNOWN_FIELDMASK)) {
- {stack[top++] = cs; cs = 75;goto _again;}
- } else {
- {stack[top++] = cs; cs = 32;goto _again;}
- }
- }
- break;
- case 37:
-#line 2710 "upb/json/parser.rl"
- { p--; {stack[top++] = cs; cs = 78;goto _again;} }
- break;
- case 38:
-#line 2715 "upb/json/parser.rl"
- {
- if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
- start_any_member(parser, p);
- } else {
- start_member(parser);
- }
- }
- break;
- case 39:
-#line 2722 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_membername(parser)); }
- break;
- case 40:
-#line 2725 "upb/json/parser.rl"
- {
- if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
- end_any_member(parser, p);
- } else {
- end_member(parser);
- }
- }
- break;
- case 41:
-#line 2736 "upb/json/parser.rl"
- {
- if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
- start_any_object(parser, p);
- } else {
- start_object(parser);
- }
- }
- break;
- case 42:
-#line 2745 "upb/json/parser.rl"
- {
- if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
- CHECK_RETURN_TOP(end_any_object(parser, p));
- } else {
- end_object(parser);
- }
- }
- break;
- case 43:
-#line 2757 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(start_array(parser)); }
- break;
- case 44:
-#line 2761 "upb/json/parser.rl"
- { end_array(parser); }
- break;
- case 45:
-#line 2766 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(start_number(parser, p)); }
- break;
- case 46:
-#line 2767 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_number(parser, p)); }
- break;
- case 47:
-#line 2769 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(start_stringval(parser)); }
- break;
- case 48:
-#line 2770 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_stringval(parser)); }
- break;
- case 49:
-#line 2772 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_bool(parser, true)); }
- break;
- case 50:
-#line 2774 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_bool(parser, false)); }
- break;
- case 51:
-#line 2776 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_null(parser)); }
- break;
- case 52:
-#line 2778 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(start_subobject_full(parser)); }
- break;
- case 53:
-#line 2779 "upb/json/parser.rl"
- { end_subobject_full(parser); }
- break;
- case 54:
-#line 2784 "upb/json/parser.rl"
- { p--; {cs = stack[--top]; goto _again;} }
- break;
-#line 3192 "upb/json/parser.c"
- }
- }
-
-_again:
- if ( cs == 0 )
- goto _out;
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- const char *__acts = _json_actions + _json_eof_actions[cs];
- unsigned int __nacts = (unsigned int) *__acts++;
- while ( __nacts-- > 0 ) {
- switch ( *__acts++ ) {
- case 0:
-#line 2593 "upb/json/parser.rl"
- { p--; {cs = stack[--top]; if ( p == pe )
- goto _test_eof;
-goto _again;} }
- break;
- case 46:
-#line 2767 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_number(parser, p)); }
- break;
- case 49:
-#line 2772 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_bool(parser, true)); }
- break;
- case 50:
-#line 2774 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_bool(parser, false)); }
- break;
- case 51:
-#line 2776 "upb/json/parser.rl"
- { CHECK_RETURN_TOP(end_null(parser)); }
- break;
- case 53:
-#line 2779 "upb/json/parser.rl"
- { end_subobject_full(parser); }
- break;
-#line 3234 "upb/json/parser.c"
- }
- }
- }
-
- _out: {}
- }
-
-#line 2812 "upb/json/parser.rl"
-
- if (p != pe) {
- upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p);
- } else {
- capture_suspend(parser, &p);
- }
-
-error:
- /* Save parsing state back to parser. */
- parser->current_state = cs;
- parser->parser_top = top;
-
- return p - buf;
-}
-
-static bool end(void *closure, const void *hd) {
- upb_json_parser *parser = closure;
-
- /* Prevent compile warning on unused static constants. */
- UPB_UNUSED(json_start);
- UPB_UNUSED(json_en_duration_machine);
- UPB_UNUSED(json_en_fieldmask_machine);
- UPB_UNUSED(json_en_number_machine);
- UPB_UNUSED(json_en_string_machine);
- UPB_UNUSED(json_en_timestamp_machine);
- UPB_UNUSED(json_en_value_machine);
- UPB_UNUSED(json_en_main);
-
- parse(parser, hd, &eof_ch, 0, NULL);
-
- return parser->current_state >= 106;
-}
-
-static void json_parser_reset(upb_json_parser *p) {
- int cs;
- int top;
-
- p->top = p->stack;
- init_frame(p->top);
-
- /* Emit Ragel initialization of the parser. */
-
-#line 3285 "upb/json/parser.c"
- {
- cs = json_start;
- top = 0;
- }
-
-#line 2854 "upb/json/parser.rl"
- p->current_state = cs;
- p->parser_top = top;
- accumulate_clear(p);
- p->multipart_state = MULTIPART_INACTIVE;
- p->capture = NULL;
- p->accumulated = NULL;
-}
-
-static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c,
- const upb_msgdef *md) {
- upb_msg_field_iter i;
- upb_alloc *alloc = upb_arena_alloc(c->arena);
-
- upb_json_parsermethod *m = upb_malloc(alloc, sizeof(*m));
-
- m->cache = c;
-
- upb_byteshandler_init(&m->input_handler_);
- upb_byteshandler_setstring(&m->input_handler_, parse, m);
- upb_byteshandler_setendstr(&m->input_handler_, end, m);
-
- upb_strtable_init2(&m->name_table, UPB_CTYPE_CONSTPTR, alloc);
-
- /* Build name_table */
-
- for(upb_msg_field_begin(&i, md);
- !upb_msg_field_done(&i);
- upb_msg_field_next(&i)) {
- const upb_fielddef *f = upb_msg_iter_field(&i);
- upb_value v = upb_value_constptr(f);
- const char *name;
-
- /* Add an entry for the JSON name. */
- name = upb_fielddef_jsonname(f);
- upb_strtable_insert3(&m->name_table, name, strlen(name), v, alloc);
-
- if (strcmp(name, upb_fielddef_name(f)) != 0) {
- /* Since the JSON name is different from the regular field name, add an
- * entry for the raw name (compliant proto3 JSON parsers must accept
- * both). */
- const char *name = upb_fielddef_name(f);
- upb_strtable_insert3(&m->name_table, name, strlen(name), v, alloc);
- }
- }
-
- return m;
-}
-
-/* Public API *****************************************************************/
-
-upb_json_parser *upb_json_parser_create(upb_arena *arena,
- const upb_json_parsermethod *method,
- const upb_symtab* symtab,
- upb_sink output,
- upb_status *status,
- bool ignore_json_unknown) {
- upb_json_parser *p = upb_arena_malloc(arena, sizeof(upb_json_parser));
- if (!p) return false;
-
- p->arena = arena;
- p->method = method;
- p->status = status;
- p->limit = p->stack + UPB_JSON_MAX_DEPTH;
- p->accumulate_buf = NULL;
- p->accumulate_buf_size = 0;
- upb_bytessink_reset(&p->input_, &method->input_handler_, p);
-
- json_parser_reset(p);
- p->top->sink = output;
- p->top->m = upb_handlers_msgdef(output.handlers);
- if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) {
- p->top->is_any = true;
- p->top->any_frame = json_parser_any_frame_new(p);
- } else {
- p->top->is_any = false;
- p->top->any_frame = NULL;
- }
- set_name_table(p, p->top);
- p->symtab = symtab;
-
- p->ignore_json_unknown = ignore_json_unknown;
-
- return p;
-}
-
-upb_bytessink upb_json_parser_input(upb_json_parser *p) {
- return p->input_;
-}
-
-const upb_byteshandler *upb_json_parsermethod_inputhandler(
- const upb_json_parsermethod *m) {
- return &m->input_handler_;
-}
-
-upb_json_codecache *upb_json_codecache_new(void) {
- upb_alloc *alloc;
- upb_json_codecache *c;
-
- c = upb_gmalloc(sizeof(*c));
-
- c->arena = upb_arena_new();
- alloc = upb_arena_alloc(c->arena);
-
- upb_inttable_init2(&c->methods, UPB_CTYPE_CONSTPTR, alloc);
-
- return c;
-}
-
-void upb_json_codecache_free(upb_json_codecache *c) {
- upb_arena_free(c->arena);
- upb_gfree(c);
-}
-
-const upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c,
- const upb_msgdef *md) {
- upb_json_parsermethod *m;
- upb_value v;
- upb_msg_field_iter i;
- upb_alloc *alloc = upb_arena_alloc(c->arena);
-
- if (upb_inttable_lookupptr(&c->methods, md, &v)) {
- return upb_value_getconstptr(v);
- }
-
- m = parsermethod_new(c, md);
- v = upb_value_constptr(m);
-
- if (!m) return NULL;
- if (!upb_inttable_insertptr2(&c->methods, md, v, alloc)) return NULL;
-
- /* Populate parser methods for all submessages, so the name tables will
- * be available during parsing. */
- for(upb_msg_field_begin(&i, md);
- !upb_msg_field_done(&i);
- upb_msg_field_next(&i)) {
- upb_fielddef *f = upb_msg_iter_field(&i);
-
- if (upb_fielddef_issubmsg(f)) {
- const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
- const upb_json_parsermethod *sub_method =
- upb_json_codecache_get(c, subdef);
-
- if (!sub_method) return NULL;
- }
- }
-
- return m;
-}
-/*
-** This currently uses snprintf() to format primitives, and could be optimized
-** further.
-*/
-
-
-#include
-#include
-#include
-#include
-#include
-
-
-struct upb_json_printer {
- upb_sink input_;
- /* BytesSink closure. */
- void *subc_;
- upb_bytessink output_;
-
- /* We track the depth so that we know when to emit startstr/endstr on the
- * output. */
- int depth_;
-
- /* Have we emitted the first element? This state is necessary to emit commas
- * without leaving a trailing comma in arrays/maps. We keep this state per
- * frame depth.
- *
- * Why max_depth * 2? UPB_MAX_HANDLER_DEPTH counts depth as nested messages.
- * We count frames (contexts in which we separate elements by commas) as both
- * repeated fields and messages (maps), and the worst case is a
- * message->repeated field->submessage->repeated field->... nesting. */
- bool first_elem_[UPB_MAX_HANDLER_DEPTH * 2];
-
- /* To print timestamp, printer needs to cache its seconds and nanos values
- * and convert them when ending timestamp message. See comments of
- * printer_sethandlers_timestamp for more detail. */
- int64_t seconds;
- int32_t nanos;
-};
-
-/* StringPiece; a pointer plus a length. */
-typedef struct {
- char *ptr;
- size_t len;
-} strpc;
-
-void freestrpc(void *ptr) {
- strpc *pc = ptr;
- upb_gfree(pc->ptr);
- upb_gfree(pc);
-}
-
-typedef struct {
- bool preserve_fieldnames;
-} upb_json_printercache;
-
-/* Convert fielddef name to JSON name and return as a string piece. */
-strpc *newstrpc(upb_handlers *h, const upb_fielddef *f,
- bool preserve_fieldnames) {
- /* TODO(haberman): handle malloc failure. */
- strpc *ret = upb_gmalloc(sizeof(*ret));
- if (preserve_fieldnames) {
- ret->ptr = upb_gstrdup(upb_fielddef_name(f));
- ret->len = strlen(ret->ptr);
- } else {
- ret->ptr = upb_gstrdup(upb_fielddef_jsonname(f));
- ret->len = strlen(ret->ptr);
- }
-
- upb_handlers_addcleanup(h, ret, freestrpc);
- return ret;
-}
-
-/* Convert a null-terminated const char* to a string piece. */
-strpc *newstrpc_str(upb_handlers *h, const char * str) {
- strpc * ret = upb_gmalloc(sizeof(*ret));
- ret->ptr = upb_gstrdup(str);
- ret->len = strlen(str);
- upb_handlers_addcleanup(h, ret, freestrpc);
- return ret;
-}
-
-/* ------------ JSON string printing: values, maps, arrays ------------------ */
-
-static void print_data(
- upb_json_printer *p, const char *buf, size_t len) {
- /* TODO: Will need to change if we support pushback from the sink. */
- size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL);
- UPB_ASSERT(n == len);
-}
-
-static void print_comma(upb_json_printer *p) {
- if (!p->first_elem_[p->depth_]) {
- print_data(p, ",", 1);
- }
- p->first_elem_[p->depth_] = false;
-}
-
-/* Helpers that print properly formatted elements to the JSON output stream. */
-
-/* Used for escaping control chars in strings. */
-static const char kControlCharLimit = 0x20;
-
-UPB_INLINE bool is_json_escaped(char c) {
- /* See RFC 4627. */
- unsigned char uc = (unsigned char)c;
- return uc < kControlCharLimit || uc == '"' || uc == '\\';
-}
-
-UPB_INLINE const char* json_nice_escape(char c) {
- switch (c) {
- case '"': return "\\\"";
- case '\\': return "\\\\";
- case '\b': return "\\b";
- case '\f': return "\\f";
- case '\n': return "\\n";
- case '\r': return "\\r";
- case '\t': return "\\t";
- default: return NULL;
- }
-}
-
-/* Write a properly escaped string chunk. The surrounding quotes are *not*
- * printed; this is so that the caller has the option of emitting the string
- * content in chunks. */
-static void putstring(upb_json_printer *p, const char *buf, size_t len) {
- const char* unescaped_run = NULL;
- unsigned int i;
- for (i = 0; i < len; i++) {
- char c = buf[i];
- /* Handle escaping. */
- if (is_json_escaped(c)) {
- /* Use a "nice" escape, like \n, if one exists for this character. */
- const char* escape = json_nice_escape(c);
- /* If we don't have a specific 'nice' escape code, use a \uXXXX-style
- * escape. */
- char escape_buf[8];
- if (!escape) {
- unsigned char byte = (unsigned char)c;
- _upb_snprintf(escape_buf, sizeof(escape_buf), "\\u%04x", (int)byte);
- escape = escape_buf;
- }
-
- /* N.B. that we assume that the input encoding is equal to the output
- * encoding (both UTF-8 for now), so for chars >= 0x20 and != \, ", we
- * can simply pass the bytes through. */
-
- /* If there's a current run of unescaped chars, print that run first. */
- if (unescaped_run) {
- print_data(p, unescaped_run, &buf[i] - unescaped_run);
- unescaped_run = NULL;
- }
- /* Then print the escape code. */
- print_data(p, escape, strlen(escape));
- } else {
- /* Add to the current unescaped run of characters. */
- if (unescaped_run == NULL) {
- unescaped_run = &buf[i];
- }
- }
- }
-
- /* If the string ended in a run of unescaped characters, print that last run. */
- if (unescaped_run) {
- print_data(p, unescaped_run, &buf[len] - unescaped_run);
- }
-}
-
-#define CHKLENGTH(x) if (!(x)) return -1;
-
-/* Helpers that format floating point values according to our custom formats.
- * Right now we use %.8g and %.17g for float/double, respectively, to match
- * proto2::util::JsonFormat's defaults. May want to change this later. */
-
-const char neginf[] = "\"-Infinity\"";
-const char inf[] = "\"Infinity\"";
-
-static size_t fmt_double(double val, char* buf, size_t length) {
- if (val == UPB_INFINITY) {
- CHKLENGTH(length >= strlen(inf));
- strcpy(buf, inf);
- return strlen(inf);
- } else if (val == -UPB_INFINITY) {
- CHKLENGTH(length >= strlen(neginf));
- strcpy(buf, neginf);
- return strlen(neginf);
- } else {
- size_t n = _upb_snprintf(buf, length, "%.17g", val);
- CHKLENGTH(n > 0 && n < length);
- return n;
- }
-}
-
-static size_t fmt_float(float val, char* buf, size_t length) {
- size_t n = _upb_snprintf(buf, length, "%.8g", val);
- CHKLENGTH(n > 0 && n < length);
- return n;
-}
-
-static size_t fmt_bool(bool val, char* buf, size_t length) {
- size_t n = _upb_snprintf(buf, length, "%s", (val ? "true" : "false"));
- CHKLENGTH(n > 0 && n < length);
- return n;
-}
-
-static size_t fmt_int64_as_number(int64_t val, char* buf, size_t length) {
- size_t n = _upb_snprintf(buf, length, "%" PRId64, val);
- CHKLENGTH(n > 0 && n < length);
- return n;
-}
-
-static size_t fmt_uint64_as_number(uint64_t val, char* buf, size_t length) {
- size_t n = _upb_snprintf(buf, length, "%" PRIu64, val);
- CHKLENGTH(n > 0 && n < length);
- return n;
-}
-
-static size_t fmt_int64_as_string(int64_t val, char* buf, size_t length) {
- size_t n = _upb_snprintf(buf, length, "\"%" PRId64 "\"", val);
- CHKLENGTH(n > 0 && n < length);
- return n;
-}
-
-static size_t fmt_uint64_as_string(uint64_t val, char* buf, size_t length) {
- size_t n = _upb_snprintf(buf, length, "\"%" PRIu64 "\"", val);
- CHKLENGTH(n > 0 && n < length);
- return n;
-}
-
-/* Print a map key given a field name. Called by scalar field handlers and by
- * startseq for repeated fields. */
-static bool putkey(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- const strpc *key = handler_data;
- print_comma(p);
- print_data(p, "\"", 1);
- putstring(p, key->ptr, key->len);
- print_data(p, "\":", 2);
- return true;
-}
-
-#define CHKFMT(val) if ((val) == (size_t)-1) return false;
-#define CHK(val) if (!(val)) return false;
-
-#define TYPE_HANDLERS(type, fmt_func) \
- static bool put##type(void *closure, const void *handler_data, type val) { \
- upb_json_printer *p = closure; \
- char data[64]; \
- size_t length = fmt_func(val, data, sizeof(data)); \
- UPB_UNUSED(handler_data); \
- CHKFMT(length); \
- print_data(p, data, length); \
- return true; \
- } \
- static bool scalar_##type(void *closure, const void *handler_data, \
- type val) { \
- CHK(putkey(closure, handler_data)); \
- CHK(put##type(closure, handler_data, val)); \
- return true; \
- } \
- static bool repeated_##type(void *closure, const void *handler_data, \
- type val) { \
- upb_json_printer *p = closure; \
- print_comma(p); \
- CHK(put##type(closure, handler_data, val)); \
- return true; \
- }
-
-#define TYPE_HANDLERS_MAPKEY(type, fmt_func) \
- static bool putmapkey_##type(void *closure, const void *handler_data, \
- type val) { \
- upb_json_printer *p = closure; \
- char data[64]; \
- size_t length = fmt_func(val, data, sizeof(data)); \
- UPB_UNUSED(handler_data); \
- print_data(p, "\"", 1); \
- print_data(p, data, length); \
- print_data(p, "\":", 2); \
- return true; \
- }
-
-TYPE_HANDLERS(double, fmt_double)
-TYPE_HANDLERS(float, fmt_float)
-TYPE_HANDLERS(bool, fmt_bool)
-TYPE_HANDLERS(int32_t, fmt_int64_as_number)
-TYPE_HANDLERS(uint32_t, fmt_int64_as_number)
-TYPE_HANDLERS(int64_t, fmt_int64_as_string)
-TYPE_HANDLERS(uint64_t, fmt_uint64_as_string)
-
-/* double and float are not allowed to be map keys. */
-TYPE_HANDLERS_MAPKEY(bool, fmt_bool)
-TYPE_HANDLERS_MAPKEY(int32_t, fmt_int64_as_number)
-TYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64_as_number)
-TYPE_HANDLERS_MAPKEY(int64_t, fmt_int64_as_number)
-TYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64_as_number)
-
-#undef TYPE_HANDLERS
-#undef TYPE_HANDLERS_MAPKEY
-
-typedef struct {
- void *keyname;
- const upb_enumdef *enumdef;
-} EnumHandlerData;
-
-static bool scalar_enum(void *closure, const void *handler_data,
- int32_t val) {
- const EnumHandlerData *hd = handler_data;
- upb_json_printer *p = closure;
- const char *symbolic_name;
-
- CHK(putkey(closure, hd->keyname));
-
- symbolic_name = upb_enumdef_iton(hd->enumdef, val);
- if (symbolic_name) {
- print_data(p, "\"", 1);
- putstring(p, symbolic_name, strlen(symbolic_name));
- print_data(p, "\"", 1);
- } else {
- putint32_t(closure, NULL, val);
- }
-
- return true;
-}
-
-static void print_enum_symbolic_name(upb_json_printer *p,
- const upb_enumdef *def,
- int32_t val) {
- const char *symbolic_name = upb_enumdef_iton(def, val);
- if (symbolic_name) {
- print_data(p, "\"", 1);
- putstring(p, symbolic_name, strlen(symbolic_name));
- print_data(p, "\"", 1);
- } else {
- putint32_t(p, NULL, val);
- }
-}
-
-static bool repeated_enum(void *closure, const void *handler_data,
- int32_t val) {
- const EnumHandlerData *hd = handler_data;
- upb_json_printer *p = closure;
- print_comma(p);
-
- print_enum_symbolic_name(p, hd->enumdef, val);
-
- return true;
-}
-
-static bool mapvalue_enum(void *closure, const void *handler_data,
- int32_t val) {
- const EnumHandlerData *hd = handler_data;
- upb_json_printer *p = closure;
-
- print_enum_symbolic_name(p, hd->enumdef, val);
-
- return true;
-}
-
-static void *scalar_startsubmsg(void *closure, const void *handler_data) {
- return putkey(closure, handler_data) ? closure : UPB_BREAK;
-}
-
-static void *repeated_startsubmsg(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- print_comma(p);
- return closure;
-}
-
-static void start_frame(upb_json_printer *p) {
- p->depth_++;
- p->first_elem_[p->depth_] = true;
- print_data(p, "{", 1);
-}
-
-static void end_frame(upb_json_printer *p) {
- print_data(p, "}", 1);
- p->depth_--;
-}
-
-static bool printer_startmsg(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- if (p->depth_ == 0) {
- upb_bytessink_start(p->output_, 0, &p->subc_);
- }
- start_frame(p);
- return true;
-}
-
-static bool printer_endmsg(void *closure, const void *handler_data, upb_status *s) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- UPB_UNUSED(s);
- end_frame(p);
- if (p->depth_ == 0) {
- upb_bytessink_end(p->output_);
- }
- return true;
-}
-
-static void *startseq(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- CHK(putkey(closure, handler_data));
- p->depth_++;
- p->first_elem_[p->depth_] = true;
- print_data(p, "[", 1);
- return closure;
-}
-
-static bool endseq(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- print_data(p, "]", 1);
- p->depth_--;
- return true;
-}
-
-static void *startmap(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- CHK(putkey(closure, handler_data));
- p->depth_++;
- p->first_elem_[p->depth_] = true;
- print_data(p, "{", 1);
- return closure;
-}
-
-static bool endmap(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- print_data(p, "}", 1);
- p->depth_--;
- return true;
-}
-
-static size_t putstr(void *closure, const void *handler_data, const char *str,
- size_t len, const upb_bufhandle *handle) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- UPB_UNUSED(handle);
- putstring(p, str, len);
- return len;
-}
-
-/* This has to Base64 encode the bytes, because JSON has no "bytes" type. */
-static size_t putbytes(void *closure, const void *handler_data, const char *str,
- size_t len, const upb_bufhandle *handle) {
- upb_json_printer *p = closure;
-
- /* This is the regular base64, not the "web-safe" version. */
- static const char base64[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- /* Base64-encode. */
- char data[16000];
- const char *limit = data + sizeof(data);
- const unsigned char *from = (const unsigned char*)str;
- char *to = data;
- size_t remaining = len;
- size_t bytes;
-
- UPB_UNUSED(handler_data);
- UPB_UNUSED(handle);
-
- print_data(p, "\"", 1);
-
- while (remaining > 2) {
- if (limit - to < 4) {
- bytes = to - data;
- putstring(p, data, bytes);
- to = data;
- }
-
- to[0] = base64[from[0] >> 2];
- to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
- to[2] = base64[((from[1] & 0xf) << 2) | (from[2] >> 6)];
- to[3] = base64[from[2] & 0x3f];
-
- remaining -= 3;
- to += 4;
- from += 3;
- }
-
- switch (remaining) {
- case 2:
- to[0] = base64[from[0] >> 2];
- to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
- to[2] = base64[(from[1] & 0xf) << 2];
- to[3] = '=';
- to += 4;
- from += 2;
- break;
- case 1:
- to[0] = base64[from[0] >> 2];
- to[1] = base64[((from[0] & 0x3) << 4)];
- to[2] = '=';
- to[3] = '=';
- to += 4;
- from += 1;
- break;
- }
-
- bytes = to - data;
- putstring(p, data, bytes);
- print_data(p, "\"", 1);
- return len;
-}
-
-static void *scalar_startstr(void *closure, const void *handler_data,
- size_t size_hint) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- UPB_UNUSED(size_hint);
- CHK(putkey(closure, handler_data));
- print_data(p, "\"", 1);
- return p;
-}
-
-static size_t scalar_str(void *closure, const void *handler_data,
- const char *str, size_t len,
- const upb_bufhandle *handle) {
- CHK(putstr(closure, handler_data, str, len, handle));
- return len;
-}
-
-static bool scalar_endstr(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- print_data(p, "\"", 1);
- return true;
-}
-
-static void *repeated_startstr(void *closure, const void *handler_data,
- size_t size_hint) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- UPB_UNUSED(size_hint);
- print_comma(p);
- print_data(p, "\"", 1);
- return p;
-}
-
-static size_t repeated_str(void *closure, const void *handler_data,
- const char *str, size_t len,
- const upb_bufhandle *handle) {
- CHK(putstr(closure, handler_data, str, len, handle));
- return len;
-}
-
-static bool repeated_endstr(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- print_data(p, "\"", 1);
- return true;
-}
-
-static void *mapkeyval_startstr(void *closure, const void *handler_data,
- size_t size_hint) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- UPB_UNUSED(size_hint);
- print_data(p, "\"", 1);
- return p;
-}
-
-static size_t mapkey_str(void *closure, const void *handler_data,
- const char *str, size_t len,
- const upb_bufhandle *handle) {
- CHK(putstr(closure, handler_data, str, len, handle));
- return len;
-}
-
-static bool mapkey_endstr(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- print_data(p, "\":", 2);
- return true;
-}
-
-static bool mapvalue_endstr(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- print_data(p, "\"", 1);
- return true;
-}
-
-static size_t scalar_bytes(void *closure, const void *handler_data,
- const char *str, size_t len,
- const upb_bufhandle *handle) {
- CHK(putkey(closure, handler_data));
- CHK(putbytes(closure, handler_data, str, len, handle));
- return len;
-}
-
-static size_t repeated_bytes(void *closure, const void *handler_data,
- const char *str, size_t len,
- const upb_bufhandle *handle) {
- upb_json_printer *p = closure;
- print_comma(p);
- CHK(putbytes(closure, handler_data, str, len, handle));
- return len;
-}
-
-static size_t mapkey_bytes(void *closure, const void *handler_data,
- const char *str, size_t len,
- const upb_bufhandle *handle) {
- upb_json_printer *p = closure;
- CHK(putbytes(closure, handler_data, str, len, handle));
- print_data(p, ":", 1);
- return len;
-}
-
-static void set_enum_hd(upb_handlers *h,
- const upb_fielddef *f,
- bool preserve_fieldnames,
- upb_handlerattr *attr) {
- EnumHandlerData *hd = upb_gmalloc(sizeof(EnumHandlerData));
- hd->enumdef = upb_fielddef_enumsubdef(f);
- hd->keyname = newstrpc(h, f, preserve_fieldnames);
- upb_handlers_addcleanup(h, hd, upb_gfree);
- attr->handler_data = hd;
-}
-
-/* Set up handlers for a mapentry submessage (i.e., an individual key/value pair
- * in a map).
- *
- * TODO: Handle missing key, missing value, out-of-order key/value, or repeated
- * key or value cases properly. The right way to do this is to allocate a
- * temporary structure at the start of a mapentry submessage, store key and
- * value data in it as key and value handlers are called, and then print the
- * key/value pair once at the end of the submessage. If we don't do this, we
- * should at least detect the case and throw an error. However, so far all of
- * our sources that emit mapentry messages do so canonically (with one key
- * field, and then one value field), so this is not a pressing concern at the
- * moment. */
-void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames,
- upb_handlers *h) {
- const upb_msgdef *md = upb_handlers_msgdef(h);
-
- /* A mapentry message is printed simply as '"key": value'. Rather than
- * special-case key and value for every type below, we just handle both
- * fields explicitly here. */
- const upb_fielddef* key_field = upb_msgdef_itof(md, UPB_MAPENTRY_KEY);
- const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_MAPENTRY_VALUE);
-
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
- UPB_UNUSED(closure);
-
- switch (upb_fielddef_type(key_field)) {
- case UPB_TYPE_INT32:
- upb_handlers_setint32(h, key_field, putmapkey_int32_t, &empty_attr);
- break;
- case UPB_TYPE_INT64:
- upb_handlers_setint64(h, key_field, putmapkey_int64_t, &empty_attr);
- break;
- case UPB_TYPE_UINT32:
- upb_handlers_setuint32(h, key_field, putmapkey_uint32_t, &empty_attr);
- break;
- case UPB_TYPE_UINT64:
- upb_handlers_setuint64(h, key_field, putmapkey_uint64_t, &empty_attr);
- break;
- case UPB_TYPE_BOOL:
- upb_handlers_setbool(h, key_field, putmapkey_bool, &empty_attr);
- break;
- case UPB_TYPE_STRING:
- upb_handlers_setstartstr(h, key_field, mapkeyval_startstr, &empty_attr);
- upb_handlers_setstring(h, key_field, mapkey_str, &empty_attr);
- upb_handlers_setendstr(h, key_field, mapkey_endstr, &empty_attr);
- break;
- case UPB_TYPE_BYTES:
- upb_handlers_setstring(h, key_field, mapkey_bytes, &empty_attr);
- break;
- default:
- UPB_ASSERT(false);
- break;
- }
-
- switch (upb_fielddef_type(value_field)) {
- case UPB_TYPE_INT32:
- upb_handlers_setint32(h, value_field, putint32_t, &empty_attr);
- break;
- case UPB_TYPE_INT64:
- upb_handlers_setint64(h, value_field, putint64_t, &empty_attr);
- break;
- case UPB_TYPE_UINT32:
- upb_handlers_setuint32(h, value_field, putuint32_t, &empty_attr);
- break;
- case UPB_TYPE_UINT64:
- upb_handlers_setuint64(h, value_field, putuint64_t, &empty_attr);
- break;
- case UPB_TYPE_BOOL:
- upb_handlers_setbool(h, value_field, putbool, &empty_attr);
- break;
- case UPB_TYPE_FLOAT:
- upb_handlers_setfloat(h, value_field, putfloat, &empty_attr);
- break;
- case UPB_TYPE_DOUBLE:
- upb_handlers_setdouble(h, value_field, putdouble, &empty_attr);
- break;
- case UPB_TYPE_STRING:
- upb_handlers_setstartstr(h, value_field, mapkeyval_startstr, &empty_attr);
- upb_handlers_setstring(h, value_field, putstr, &empty_attr);
- upb_handlers_setendstr(h, value_field, mapvalue_endstr, &empty_attr);
- break;
- case UPB_TYPE_BYTES:
- upb_handlers_setstring(h, value_field, putbytes, &empty_attr);
- break;
- case UPB_TYPE_ENUM: {
- upb_handlerattr enum_attr = UPB_HANDLERATTR_INIT;
- set_enum_hd(h, value_field, preserve_fieldnames, &enum_attr);
- upb_handlers_setint32(h, value_field, mapvalue_enum, &enum_attr);
- break;
- }
- case UPB_TYPE_MESSAGE:
- /* No handler necessary -- the submsg handlers will print the message
- * as appropriate. */
- break;
- }
-}
-
-static bool putseconds(void *closure, const void *handler_data,
- int64_t seconds) {
- upb_json_printer *p = closure;
- p->seconds = seconds;
- UPB_UNUSED(handler_data);
- return true;
-}
-
-static bool putnanos(void *closure, const void *handler_data,
- int32_t nanos) {
- upb_json_printer *p = closure;
- p->nanos = nanos;
- UPB_UNUSED(handler_data);
- return true;
-}
-
-static void *scalar_startstr_nokey(void *closure, const void *handler_data,
- size_t size_hint) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- UPB_UNUSED(size_hint);
- print_data(p, "\"", 1);
- return p;
-}
-
-static size_t putstr_nokey(void *closure, const void *handler_data,
- const char *str, size_t len,
- const upb_bufhandle *handle) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- UPB_UNUSED(handle);
- print_data(p, "\"", 1);
- putstring(p, str, len);
- print_data(p, "\"", 1);
- return len + 2;
-}
-
-static void *startseq_nokey(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- p->depth_++;
- p->first_elem_[p->depth_] = true;
- print_data(p, "[", 1);
- return closure;
-}
-
-static void *startseq_fieldmask(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- p->depth_++;
- p->first_elem_[p->depth_] = true;
- return closure;
-}
-
-static bool endseq_fieldmask(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- p->depth_--;
- return true;
-}
-
-static void *repeated_startstr_fieldmask(
- void *closure, const void *handler_data,
- size_t size_hint) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- UPB_UNUSED(size_hint);
- print_comma(p);
- return p;
-}
-
-static size_t repeated_str_fieldmask(
- void *closure, const void *handler_data,
- const char *str, size_t len,
- const upb_bufhandle *handle) {
- const char* limit = str + len;
- bool upper = false;
- size_t result_len = 0;
- for (; str < limit; str++) {
- if (*str == '_') {
- upper = true;
- continue;
- }
- if (upper && *str >= 'a' && *str <= 'z') {
- char upper_char = toupper(*str);
- CHK(putstr(closure, handler_data, &upper_char, 1, handle));
- } else {
- CHK(putstr(closure, handler_data, str, 1, handle));
- }
- upper = false;
- result_len++;
- }
- return result_len;
-}
-
-static void *startmap_nokey(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- p->depth_++;
- p->first_elem_[p->depth_] = true;
- print_data(p, "{", 1);
- return closure;
-}
-
-static bool putnull(void *closure, const void *handler_data,
- int32_t null) {
- upb_json_printer *p = closure;
- print_data(p, "null", 4);
- UPB_UNUSED(handler_data);
- UPB_UNUSED(null);
- return true;
-}
-
-static bool printer_startdurationmsg(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- if (p->depth_ == 0) {
- upb_bytessink_start(p->output_, 0, &p->subc_);
- }
- return true;
-}
-
-#define UPB_DURATION_MAX_JSON_LEN 23
-#define UPB_DURATION_MAX_NANO_LEN 9
-
-static bool printer_enddurationmsg(void *closure, const void *handler_data,
- upb_status *s) {
- upb_json_printer *p = closure;
- char buffer[UPB_DURATION_MAX_JSON_LEN];
- size_t base_len;
- size_t curr;
- size_t i;
-
- memset(buffer, 0, UPB_DURATION_MAX_JSON_LEN);
-
- if (p->seconds < -315576000000) {
- upb_status_seterrf(s, "error parsing duration: "
- "minimum acceptable value is "
- "-315576000000");
- return false;
- }
-
- if (p->seconds > 315576000000) {
- upb_status_seterrf(s, "error serializing duration: "
- "maximum acceptable value is "
- "315576000000");
- return false;
- }
-
- _upb_snprintf(buffer, sizeof(buffer), "%ld", (long)p->seconds);
- base_len = strlen(buffer);
-
- if (p->nanos != 0) {
- char nanos_buffer[UPB_DURATION_MAX_NANO_LEN + 3];
- _upb_snprintf(nanos_buffer, sizeof(nanos_buffer), "%.9f",
- p->nanos / 1000000000.0);
- /* Remove trailing 0. */
- for (i = UPB_DURATION_MAX_NANO_LEN + 2;
- nanos_buffer[i] == '0'; i--) {
- nanos_buffer[i] = 0;
- }
- strcpy(buffer + base_len, nanos_buffer + 1);
- }
-
- curr = strlen(buffer);
- strcpy(buffer + curr, "s");
-
- p->seconds = 0;
- p->nanos = 0;
-
- print_data(p, "\"", 1);
- print_data(p, buffer, strlen(buffer));
- print_data(p, "\"", 1);
-
- if (p->depth_ == 0) {
- upb_bytessink_end(p->output_);
- }
-
- UPB_UNUSED(handler_data);
- return true;
-}
-
-static bool printer_starttimestampmsg(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- if (p->depth_ == 0) {
- upb_bytessink_start(p->output_, 0, &p->subc_);
- }
- return true;
-}
-
-#define UPB_TIMESTAMP_MAX_JSON_LEN 31
-#define UPB_TIMESTAMP_BEFORE_NANO_LEN 19
-#define UPB_TIMESTAMP_MAX_NANO_LEN 9
-
-static bool printer_endtimestampmsg(void *closure, const void *handler_data,
- upb_status *s) {
- upb_json_printer *p = closure;
- char buffer[UPB_TIMESTAMP_MAX_JSON_LEN];
- time_t time = p->seconds;
- size_t curr;
- size_t i;
- size_t year_length =
- strftime(buffer, UPB_TIMESTAMP_MAX_JSON_LEN, "%Y", gmtime(&time));
-
- if (p->seconds < -62135596800) {
- upb_status_seterrf(s, "error parsing timestamp: "
- "minimum acceptable value is "
- "0001-01-01T00:00:00Z");
- return false;
- }
-
- if (p->seconds > 253402300799) {
- upb_status_seterrf(s, "error parsing timestamp: "
- "maximum acceptable value is "
- "9999-12-31T23:59:59Z");
- return false;
- }
-
- /* strftime doesn't guarantee 4 digits for year. Prepend 0 by ourselves. */
- for (i = 0; i < 4 - year_length; i++) {
- buffer[i] = '0';
- }
-
- strftime(buffer + (4 - year_length), UPB_TIMESTAMP_MAX_JSON_LEN,
- "%Y-%m-%dT%H:%M:%S", gmtime(&time));
- if (p->nanos != 0) {
- char nanos_buffer[UPB_TIMESTAMP_MAX_NANO_LEN + 3];
- _upb_snprintf(nanos_buffer, sizeof(nanos_buffer), "%.9f",
- p->nanos / 1000000000.0);
- /* Remove trailing 0. */
- for (i = UPB_TIMESTAMP_MAX_NANO_LEN + 2;
- nanos_buffer[i] == '0'; i--) {
- nanos_buffer[i] = 0;
- }
- strcpy(buffer + UPB_TIMESTAMP_BEFORE_NANO_LEN, nanos_buffer + 1);
- }
-
- curr = strlen(buffer);
- strcpy(buffer + curr, "Z");
-
- p->seconds = 0;
- p->nanos = 0;
-
- print_data(p, "\"", 1);
- print_data(p, buffer, strlen(buffer));
- print_data(p, "\"", 1);
-
- if (p->depth_ == 0) {
- upb_bytessink_end(p->output_);
- }
-
- UPB_UNUSED(handler_data);
- UPB_UNUSED(s);
- return true;
-}
-
-static bool printer_startmsg_noframe(void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- if (p->depth_ == 0) {
- upb_bytessink_start(p->output_, 0, &p->subc_);
- }
- return true;
-}
-
-static bool printer_endmsg_noframe(
- void *closure, const void *handler_data, upb_status *s) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- UPB_UNUSED(s);
- if (p->depth_ == 0) {
- upb_bytessink_end(p->output_);
- }
- return true;
-}
-
-static bool printer_startmsg_fieldmask(
- void *closure, const void *handler_data) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- if (p->depth_ == 0) {
- upb_bytessink_start(p->output_, 0, &p->subc_);
- }
- print_data(p, "\"", 1);
- return true;
-}
-
-static bool printer_endmsg_fieldmask(
- void *closure, const void *handler_data, upb_status *s) {
- upb_json_printer *p = closure;
- UPB_UNUSED(handler_data);
- UPB_UNUSED(s);
- print_data(p, "\"", 1);
- if (p->depth_ == 0) {
- upb_bytessink_end(p->output_);
- }
- return true;
-}
-
-static void *scalar_startstr_onlykey(
- void *closure, const void *handler_data, size_t size_hint) {
- upb_json_printer *p = closure;
- UPB_UNUSED(size_hint);
- CHK(putkey(closure, handler_data));
- return p;
-}
-
-/* Set up handlers for an Any submessage. */
-void printer_sethandlers_any(const void *closure, upb_handlers *h) {
- const upb_msgdef *md = upb_handlers_msgdef(h);
-
- const upb_fielddef* type_field = upb_msgdef_itof(md, UPB_ANY_TYPE);
- const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_ANY_VALUE);
-
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
- /* type_url's json name is "@type" */
- upb_handlerattr type_name_attr = UPB_HANDLERATTR_INIT;
- upb_handlerattr value_name_attr = UPB_HANDLERATTR_INIT;
- strpc *type_url_json_name = newstrpc_str(h, "@type");
- strpc *value_json_name = newstrpc_str(h, "value");
-
- type_name_attr.handler_data = type_url_json_name;
- value_name_attr.handler_data = value_json_name;
-
- /* Set up handlers. */
- upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
- upb_handlers_setendmsg(h, printer_endmsg, &empty_attr);
-
- upb_handlers_setstartstr(h, type_field, scalar_startstr, &type_name_attr);
- upb_handlers_setstring(h, type_field, scalar_str, &empty_attr);
- upb_handlers_setendstr(h, type_field, scalar_endstr, &empty_attr);
-
- /* This is not the full and correct JSON encoding for the Any value field. It
- * requires further processing by the wrapper code based on the type URL.
- */
- upb_handlers_setstartstr(h, value_field, scalar_startstr_onlykey,
- &value_name_attr);
-
- UPB_UNUSED(closure);
-}
-
-/* Set up handlers for a fieldmask submessage. */
-void printer_sethandlers_fieldmask(const void *closure, upb_handlers *h) {
- const upb_msgdef *md = upb_handlers_msgdef(h);
- const upb_fielddef* f = upb_msgdef_itof(md, 1);
-
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
- upb_handlers_setstartseq(h, f, startseq_fieldmask, &empty_attr);
- upb_handlers_setendseq(h, f, endseq_fieldmask, &empty_attr);
-
- upb_handlers_setstartmsg(h, printer_startmsg_fieldmask, &empty_attr);
- upb_handlers_setendmsg(h, printer_endmsg_fieldmask, &empty_attr);
-
- upb_handlers_setstartstr(h, f, repeated_startstr_fieldmask, &empty_attr);
- upb_handlers_setstring(h, f, repeated_str_fieldmask, &empty_attr);
-
- UPB_UNUSED(closure);
-}
-
-/* Set up handlers for a duration submessage. */
-void printer_sethandlers_duration(const void *closure, upb_handlers *h) {
- const upb_msgdef *md = upb_handlers_msgdef(h);
-
- const upb_fielddef* seconds_field =
- upb_msgdef_itof(md, UPB_DURATION_SECONDS);
- const upb_fielddef* nanos_field =
- upb_msgdef_itof(md, UPB_DURATION_NANOS);
-
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
- upb_handlers_setstartmsg(h, printer_startdurationmsg, &empty_attr);
- upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr);
- upb_handlers_setint32(h, nanos_field, putnanos, &empty_attr);
- upb_handlers_setendmsg(h, printer_enddurationmsg, &empty_attr);
-
- UPB_UNUSED(closure);
-}
-
-/* Set up handlers for a timestamp submessage. Instead of printing fields
- * separately, the json representation of timestamp follows RFC 3339 */
-void printer_sethandlers_timestamp(const void *closure, upb_handlers *h) {
- const upb_msgdef *md = upb_handlers_msgdef(h);
-
- const upb_fielddef* seconds_field =
- upb_msgdef_itof(md, UPB_TIMESTAMP_SECONDS);
- const upb_fielddef* nanos_field =
- upb_msgdef_itof(md, UPB_TIMESTAMP_NANOS);
-
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
- upb_handlers_setstartmsg(h, printer_starttimestampmsg, &empty_attr);
- upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr);
- upb_handlers_setint32(h, nanos_field, putnanos, &empty_attr);
- upb_handlers_setendmsg(h, printer_endtimestampmsg, &empty_attr);
-
- UPB_UNUSED(closure);
-}
-
-void printer_sethandlers_value(const void *closure, upb_handlers *h) {
- const upb_msgdef *md = upb_handlers_msgdef(h);
- upb_msg_field_iter i;
-
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
- upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);
- upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);
-
- upb_msg_field_begin(&i, md);
- for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
- const upb_fielddef *f = upb_msg_iter_field(&i);
-
- switch (upb_fielddef_type(f)) {
- case UPB_TYPE_ENUM:
- upb_handlers_setint32(h, f, putnull, &empty_attr);
- break;
- case UPB_TYPE_DOUBLE:
- upb_handlers_setdouble(h, f, putdouble, &empty_attr);
- break;
- case UPB_TYPE_STRING:
- upb_handlers_setstartstr(h, f, scalar_startstr_nokey, &empty_attr);
- upb_handlers_setstring(h, f, scalar_str, &empty_attr);
- upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr);
- break;
- case UPB_TYPE_BOOL:
- upb_handlers_setbool(h, f, putbool, &empty_attr);
- break;
- case UPB_TYPE_MESSAGE:
- break;
- default:
- UPB_ASSERT(false);
- break;
- }
- }
-
- UPB_UNUSED(closure);
-}
-
-#define WRAPPER_SETHANDLERS(wrapper, type, putmethod) \
-void printer_sethandlers_##wrapper(const void *closure, upb_handlers *h) { \
- const upb_msgdef *md = upb_handlers_msgdef(h); \
- const upb_fielddef* f = upb_msgdef_itof(md, 1); \
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT; \
- upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr); \
- upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr); \
- upb_handlers_set##type(h, f, putmethod, &empty_attr); \
- UPB_UNUSED(closure); \
-}
-
-WRAPPER_SETHANDLERS(doublevalue, double, putdouble)
-WRAPPER_SETHANDLERS(floatvalue, float, putfloat)
-WRAPPER_SETHANDLERS(int64value, int64, putint64_t)
-WRAPPER_SETHANDLERS(uint64value, uint64, putuint64_t)
-WRAPPER_SETHANDLERS(int32value, int32, putint32_t)
-WRAPPER_SETHANDLERS(uint32value, uint32, putuint32_t)
-WRAPPER_SETHANDLERS(boolvalue, bool, putbool)
-WRAPPER_SETHANDLERS(stringvalue, string, putstr_nokey)
-WRAPPER_SETHANDLERS(bytesvalue, string, putbytes)
-
-#undef WRAPPER_SETHANDLERS
-
-void printer_sethandlers_listvalue(const void *closure, upb_handlers *h) {
- const upb_msgdef *md = upb_handlers_msgdef(h);
- const upb_fielddef* f = upb_msgdef_itof(md, 1);
-
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
- upb_handlers_setstartseq(h, f, startseq_nokey, &empty_attr);
- upb_handlers_setendseq(h, f, endseq, &empty_attr);
-
- upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);
- upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);
-
- upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &empty_attr);
-
- UPB_UNUSED(closure);
-}
-
-void printer_sethandlers_structvalue(const void *closure, upb_handlers *h) {
- const upb_msgdef *md = upb_handlers_msgdef(h);
- const upb_fielddef* f = upb_msgdef_itof(md, 1);
-
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
- upb_handlers_setstartseq(h, f, startmap_nokey, &empty_attr);
- upb_handlers_setendseq(h, f, endmap, &empty_attr);
-
- upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);
- upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);
-
- upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &empty_attr);
-
- UPB_UNUSED(closure);
-}
-
-void printer_sethandlers(const void *closure, upb_handlers *h) {
- const upb_msgdef *md = upb_handlers_msgdef(h);
- bool is_mapentry = upb_msgdef_mapentry(md);
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
- upb_msg_field_iter i;
- const upb_json_printercache *cache = closure;
- const bool preserve_fieldnames = cache->preserve_fieldnames;
-
- if (is_mapentry) {
- /* mapentry messages are sufficiently different that we handle them
- * separately. */
- printer_sethandlers_mapentry(closure, preserve_fieldnames, h);
- return;
- }
-
- switch (upb_msgdef_wellknowntype(md)) {
- case UPB_WELLKNOWN_UNSPECIFIED:
- break;
- case UPB_WELLKNOWN_ANY:
- printer_sethandlers_any(closure, h);
- return;
- case UPB_WELLKNOWN_FIELDMASK:
- printer_sethandlers_fieldmask(closure, h);
- return;
- case UPB_WELLKNOWN_DURATION:
- printer_sethandlers_duration(closure, h);
- return;
- case UPB_WELLKNOWN_TIMESTAMP:
- printer_sethandlers_timestamp(closure, h);
- return;
- case UPB_WELLKNOWN_VALUE:
- printer_sethandlers_value(closure, h);
- return;
- case UPB_WELLKNOWN_LISTVALUE:
- printer_sethandlers_listvalue(closure, h);
- return;
- case UPB_WELLKNOWN_STRUCT:
- printer_sethandlers_structvalue(closure, h);
- return;
-#define WRAPPER(wellknowntype, name) \
- case wellknowntype: \
- printer_sethandlers_##name(closure, h); \
- return; \
-
- WRAPPER(UPB_WELLKNOWN_DOUBLEVALUE, doublevalue);
- WRAPPER(UPB_WELLKNOWN_FLOATVALUE, floatvalue);
- WRAPPER(UPB_WELLKNOWN_INT64VALUE, int64value);
- WRAPPER(UPB_WELLKNOWN_UINT64VALUE, uint64value);
- WRAPPER(UPB_WELLKNOWN_INT32VALUE, int32value);
- WRAPPER(UPB_WELLKNOWN_UINT32VALUE, uint32value);
- WRAPPER(UPB_WELLKNOWN_BOOLVALUE, boolvalue);
- WRAPPER(UPB_WELLKNOWN_STRINGVALUE, stringvalue);
- WRAPPER(UPB_WELLKNOWN_BYTESVALUE, bytesvalue);
-
-#undef WRAPPER
- }
-
- upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
- upb_handlers_setendmsg(h, printer_endmsg, &empty_attr);
-
-#define TYPE(type, name, ctype) \
- case type: \
- if (upb_fielddef_isseq(f)) { \
- upb_handlers_set##name(h, f, repeated_##ctype, &empty_attr); \
- } else { \
- upb_handlers_set##name(h, f, scalar_##ctype, &name_attr); \
- } \
- break;
-
- upb_msg_field_begin(&i, md);
- for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
- const upb_fielddef *f = upb_msg_iter_field(&i);
-
- upb_handlerattr name_attr = UPB_HANDLERATTR_INIT;
- name_attr.handler_data = newstrpc(h, f, preserve_fieldnames);
-
- if (upb_fielddef_ismap(f)) {
- upb_handlers_setstartseq(h, f, startmap, &name_attr);
- upb_handlers_setendseq(h, f, endmap, &name_attr);
- } else if (upb_fielddef_isseq(f)) {
- upb_handlers_setstartseq(h, f, startseq, &name_attr);
- upb_handlers_setendseq(h, f, endseq, &empty_attr);
- }
-
- switch (upb_fielddef_type(f)) {
- TYPE(UPB_TYPE_FLOAT, float, float);
- TYPE(UPB_TYPE_DOUBLE, double, double);
- TYPE(UPB_TYPE_BOOL, bool, bool);
- TYPE(UPB_TYPE_INT32, int32, int32_t);
- TYPE(UPB_TYPE_UINT32, uint32, uint32_t);
- TYPE(UPB_TYPE_INT64, int64, int64_t);
- TYPE(UPB_TYPE_UINT64, uint64, uint64_t);
- case UPB_TYPE_ENUM: {
- /* For now, we always emit symbolic names for enums. We may want an
- * option later to control this behavior, but we will wait for a real
- * need first. */
- upb_handlerattr enum_attr = UPB_HANDLERATTR_INIT;
- set_enum_hd(h, f, preserve_fieldnames, &enum_attr);
-
- if (upb_fielddef_isseq(f)) {
- upb_handlers_setint32(h, f, repeated_enum, &enum_attr);
- } else {
- upb_handlers_setint32(h, f, scalar_enum, &enum_attr);
- }
-
- break;
- }
- case UPB_TYPE_STRING:
- if (upb_fielddef_isseq(f)) {
- upb_handlers_setstartstr(h, f, repeated_startstr, &empty_attr);
- upb_handlers_setstring(h, f, repeated_str, &empty_attr);
- upb_handlers_setendstr(h, f, repeated_endstr, &empty_attr);
- } else {
- upb_handlers_setstartstr(h, f, scalar_startstr, &name_attr);
- upb_handlers_setstring(h, f, scalar_str, &empty_attr);
- upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr);
- }
- break;
- case UPB_TYPE_BYTES:
- /* XXX: this doesn't support strings that span buffers yet. The base64
- * encoder will need to be made resumable for this to work properly. */
- if (upb_fielddef_isseq(f)) {
- upb_handlers_setstring(h, f, repeated_bytes, &empty_attr);
- } else {
- upb_handlers_setstring(h, f, scalar_bytes, &name_attr);
- }
- break;
- case UPB_TYPE_MESSAGE:
- if (upb_fielddef_isseq(f)) {
- upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &name_attr);
- } else {
- upb_handlers_setstartsubmsg(h, f, scalar_startsubmsg, &name_attr);
- }
- break;
- }
- }
-
-#undef TYPE
-}
-
-static void json_printer_reset(upb_json_printer *p) {
- p->depth_ = 0;
-}
-
-
-/* Public API *****************************************************************/
-
-upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h,
- upb_bytessink output) {
- upb_json_printer *p = upb_arena_malloc(a, sizeof(upb_json_printer));
- if (!p) return NULL;
-
- p->output_ = output;
- json_printer_reset(p);
- upb_sink_reset(&p->input_, h, p);
- p->seconds = 0;
- p->nanos = 0;
-
- return p;
-}
-
-upb_sink upb_json_printer_input(upb_json_printer *p) {
- return p->input_;
-}
-
-upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames) {
- upb_json_printercache *cache = upb_gmalloc(sizeof(*cache));
- upb_handlercache *ret = upb_handlercache_new(printer_sethandlers, cache);
-
- cache->preserve_fieldnames = preserve_proto_fieldnames;
- upb_handlercache_addcleanup(ret, cache, upb_gfree);
-
- return ret;
-}
-/* See port_def.inc. This should #undef all macros #defined there. */
-
-#undef UPB_MAPTYPE_STRING
-#undef UPB_SIZE
-#undef UPB_PTR_AT
-#undef UPB_READ_ONEOF
-#undef UPB_WRITE_ONEOF
-#undef UPB_INLINE
-#undef UPB_ALIGN_UP
-#undef UPB_ALIGN_DOWN
-#undef UPB_ALIGN_MALLOC
-#undef UPB_ALIGN_OF
-#undef UPB_FORCEINLINE
-#undef UPB_NOINLINE
-#undef UPB_NORETURN
-#undef UPB_MAX
-#undef UPB_MIN
-#undef UPB_UNUSED
-#undef UPB_ASSUME
-#undef UPB_ASSERT
-#undef UPB_ASSERT_DEBUGVAR
-#undef UPB_UNREACHABLE
-#undef UPB_INFINITY
-#undef UPB_MSVC_VSNPRINTF
-#undef _upb_snprintf
-#undef _upb_vsnprintf
-#undef _upb_va_copy
diff --git a/php/ext/google/protobuf/upb.h b/php/ext/google/protobuf/upb.h
deleted file mode 100644
index 179e498777..0000000000
--- a/php/ext/google/protobuf/upb.h
+++ /dev/null
@@ -1,6796 +0,0 @@
-/* Amalgamated source file */
-
-// php.h intentionally defined NDEBUG. We have to define this macro in order to
-// be used together with php.h
-#ifndef NDEBUG
-#define NDEBUG
-#endif
-
-#include /*
-* This is where we define macros used across upb.
-*
-* All of these macros are undef'd in port_undef.inc to avoid leaking them to
-* users.
-*
-* The correct usage is:
-*
-* #include "upb/foobar.h"
-* #include "upb/baz.h"
-*
-* // MUST be last included header.
-* #include "upb/port_def.inc"
-*
-* // Code for this file.
-* // <...>
-*
-* // Can be omitted for .c files, required for .h.
-* #include "upb/port_undef.inc"
-*
-* This file is private and must not be included by users!
-*/
-#include
-#include
-
-#if UINTPTR_MAX == 0xffffffff
-#define UPB_SIZE(size32, size64) size32
-#else
-#define UPB_SIZE(size32, size64) size64
-#endif
-
-/* If we always read/write as a consistent type to each address, this shouldn't
- * violate aliasing.
- */
-#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs)))
-
-#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
- *UPB_PTR_AT(msg, case_offset, int) == case_val \
- ? *UPB_PTR_AT(msg, offset, fieldtype) \
- : default
-
-#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
- *UPB_PTR_AT(msg, case_offset, int) = case_val; \
- *UPB_PTR_AT(msg, offset, fieldtype) = value;
-
-#define UPB_MAPTYPE_STRING 0
-
-/* UPB_INLINE: inline if possible, emit standalone code if required. */
-#ifdef __cplusplus
-#define UPB_INLINE inline
-#elif defined (__GNUC__) || defined(__clang__)
-#define UPB_INLINE static __inline__
-#else
-#define UPB_INLINE static
-#endif
-
-#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align))
-#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align))
-#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16)
-#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member)
-
-/* Hints to the compiler about likely/unlikely branches. */
-#if defined (__GNUC__) || defined(__clang__)
-#define UPB_LIKELY(x) __builtin_expect((x),1)
-#define UPB_UNLIKELY(x) __builtin_expect((x),0)
-#else
-#define UPB_LIKELY(x) (x)
-#define UPB_UNLIKELY(x) (x)
-#endif
-
-/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler
- * doesn't provide these preprocessor symbols. */
-#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
-#define UPB_BIG_ENDIAN
-#endif
-
-/* Macros for function attributes on compilers that support them. */
-#ifdef __GNUC__
-#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
-#define UPB_NOINLINE __attribute__((noinline))
-#define UPB_NORETURN __attribute__((__noreturn__))
-#else /* !defined(__GNUC__) */
-#define UPB_FORCEINLINE
-#define UPB_NOINLINE
-#define UPB_NORETURN
-#endif
-
-#if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L
-/* C99/C++11 versions. */
-#include
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined(_MSC_VER)
-/* Microsoft C/C++ versions. */
-#include
-#include
-#if _MSC_VER < 1900
-int msvc_snprintf(char* s, size_t n, const char* format, ...);
-int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg);
-#define UPB_MSVC_VSNPRINTF
-#define _upb_snprintf msvc_snprintf
-#define _upb_vsnprintf msvc_vsnprintf
-#else
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#endif
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined __GNUC__
-/* A few hacky workarounds for functions not in C89.
- * For internal use only!
- * TODO(haberman): fix these by including our own implementations, or finding
- * another workaround.
- */
-#define _upb_snprintf __builtin_snprintf
-#define _upb_vsnprintf __builtin_vsnprintf
-#define _upb_va_copy(a, b) __va_copy(a, b)
-#else
-#error Need implementations of [v]snprintf and va_copy
-#endif
-
-#ifdef __cplusplus
-#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \
- (defined(_MSC_VER) && _MSC_VER >= 1900)
-/* C++11 is present */
-#else
-#error upb requires C++11 for C++ support
-#endif
-#endif
-
-#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
-#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
-
-#define UPB_UNUSED(var) (void)var
-
-/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
- */
-#ifdef NDEBUG
-#ifdef __GNUC__
-#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable()
-#else
-#define UPB_ASSUME(expr) do {} if (false && (expr))
-#endif
-#else
-#define UPB_ASSUME(expr) assert(expr)
-#endif
-
-/* UPB_ASSERT(): in release mode, we use the expression without letting it be
- * evaluated. This prevents "unused variable" warnings. */
-#ifdef NDEBUG
-#define UPB_ASSERT(expr) do {} while (false && (expr))
-#else
-#define UPB_ASSERT(expr) assert(expr)
-#endif
-
-/* UPB_ASSERT_DEBUGVAR(): assert that uses functions or variables that only
- * exist in debug mode. This turns into regular assert. */
-#define UPB_ASSERT_DEBUGVAR(expr) assert(expr)
-
-#if defined(__GNUC__) || defined(__clang__)
-#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
-#else
-#define UPB_UNREACHABLE() do { assert(0); } while(0)
-#endif
-
-/* UPB_INFINITY representing floating-point positive infinity. */
-#include
-#ifdef INFINITY
-#define UPB_INFINITY INFINITY
-#else
-#define UPB_INFINITY (1.0 / 0.0)
-#endif
-/*
-** upb_decode: parsing into a upb_msg using a upb_msglayout.
-*/
-
-#ifndef UPB_DECODE_H_
-#define UPB_DECODE_H_
-
-/*
-** Our memory representation for parsing tables and messages themselves.
-** Functions in this file are used by generated code and possibly reflection.
-**
-** The definitions in this file are internal to upb.
-**/
-
-#ifndef UPB_MSG_H_
-#define UPB_MSG_H_
-
-#include
-#include
-
-/*
-** upb_table
-**
-** This header is INTERNAL-ONLY! Its interfaces are not public or stable!
-** This file defines very fast int->upb_value (inttable) and string->upb_value
-** (strtable) hash tables.
-**
-** The table uses chained scatter with Brent's variation (inspired by the Lua
-** implementation of hash tables). The hash function for strings is Austin
-** Appleby's "MurmurHash."
-**
-** The inttable uses uintptr_t as its key, which guarantees it can be used to
-** store pointers or integers of at least 32 bits (upb isn't really useful on
-** systems where sizeof(void*) < 4).
-**
-** The table must be homogenous (all values of the same type). In debug
-** mode, we check this on insert and lookup.
-*/
-
-#ifndef UPB_TABLE_H_
-#define UPB_TABLE_H_
-
-#include
-#include
-/*
-** This file contains shared definitions that are widely used across upb.
-*/
-
-#ifndef UPB_H_
-#define UPB_H_
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* upb_status *****************************************************************/
-
-#define UPB_STATUS_MAX_MESSAGE 127
-
-typedef struct {
- bool ok;
- char msg[UPB_STATUS_MAX_MESSAGE]; /* Error message; NULL-terminated. */
-} upb_status;
-
-const char *upb_status_errmsg(const upb_status *status);
-bool upb_ok(const upb_status *status);
-
-/* These are no-op if |status| is NULL. */
-void upb_status_clear(upb_status *status);
-void upb_status_seterrmsg(upb_status *status, const char *msg);
-void upb_status_seterrf(upb_status *status, const char *fmt, ...);
-void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args);
-
-/** upb_strview ************************************************************/
-
-typedef struct {
- const char *data;
- size_t size;
-} upb_strview;
-
-UPB_INLINE upb_strview upb_strview_make(const char *data, size_t size) {
- upb_strview ret;
- ret.data = data;
- ret.size = size;
- return ret;
-}
-
-UPB_INLINE upb_strview upb_strview_makez(const char *data) {
- return upb_strview_make(data, strlen(data));
-}
-
-UPB_INLINE bool upb_strview_eql(upb_strview a, upb_strview b) {
- return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
-}
-
-#define UPB_STRVIEW_INIT(ptr, len) {ptr, len}
-
-#define UPB_STRVIEW_FORMAT "%.*s"
-#define UPB_STRVIEW_ARGS(view) (int)(view).size, (view).data
-
-/** upb_alloc *****************************************************************/
-
-/* A upb_alloc is a possibly-stateful allocator object.
- *
- * It could either be an arena allocator (which doesn't require individual
- * free() calls) or a regular malloc() (which does). The client must therefore
- * free memory unless it knows that the allocator is an arena allocator. */
-
-struct upb_alloc;
-typedef struct upb_alloc upb_alloc;
-
-/* A malloc()/free() function.
- * If "size" is 0 then the function acts like free(), otherwise it acts like
- * realloc(). Only "oldsize" bytes from a previous allocation are preserved. */
-typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize,
- size_t size);
-
-struct upb_alloc {
- upb_alloc_func *func;
-};
-
-UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) {
- UPB_ASSERT(alloc);
- return alloc->func(alloc, NULL, 0, size);
-}
-
-UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize,
- size_t size) {
- UPB_ASSERT(alloc);
- return alloc->func(alloc, ptr, oldsize, size);
-}
-
-UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) {
- assert(alloc);
- alloc->func(alloc, ptr, 0, 0);
-}
-
-/* The global allocator used by upb. Uses the standard malloc()/free(). */
-
-extern upb_alloc upb_alloc_global;
-
-/* Functions that hard-code the global malloc.
- *
- * We still get benefit because we can put custom logic into our global
- * allocator, like injecting out-of-memory faults in debug/testing builds. */
-
-UPB_INLINE void *upb_gmalloc(size_t size) {
- return upb_malloc(&upb_alloc_global, size);
-}
-
-UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) {
- return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
-}
-
-UPB_INLINE void upb_gfree(void *ptr) {
- upb_free(&upb_alloc_global, ptr);
-}
-
-/* upb_arena ******************************************************************/
-
-/* upb_arena is a specific allocator implementation that uses arena allocation.
- * The user provides an allocator that will be used to allocate the underlying
- * arena blocks. Arenas by nature do not require the individual allocations
- * to be freed. However the Arena does allow users to register cleanup
- * functions that will run when the arena is destroyed.
- *
- * A upb_arena is *not* thread-safe.
- *
- * You could write a thread-safe arena allocator that satisfies the
- * upb_alloc interface, but it would not be as efficient for the
- * single-threaded case. */
-
-typedef void upb_cleanup_func(void *ud);
-
-struct upb_arena;
-typedef struct upb_arena upb_arena;
-
-typedef struct {
- /* We implement the allocator interface.
- * This must be the first member of upb_arena!
- * TODO(haberman): remove once handlers are gone. */
- upb_alloc alloc;
-
- char *ptr, *end;
-} _upb_arena_head;
-
-/* Creates an arena from the given initial block (if any -- n may be 0).
- * Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this
- * is a fixed-size arena and cannot grow. */
-upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc);
-void upb_arena_free(upb_arena *a);
-bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func);
-void upb_arena_fuse(upb_arena *a, upb_arena *b);
-void *_upb_arena_slowmalloc(upb_arena *a, size_t size);
-
-UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; }
-
-UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) {
- _upb_arena_head *h = (_upb_arena_head*)a;
- void* ret;
- size = UPB_ALIGN_MALLOC(size);
-
- if (UPB_UNLIKELY((size_t)(h->end - h->ptr) < size)) {
- return _upb_arena_slowmalloc(a, size);
- }
-
- ret = h->ptr;
- h->ptr += size;
- return ret;
-}
-
-UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize,
- size_t size) {
- void *ret = upb_arena_malloc(a, size);
-
- if (ret && oldsize > 0) {
- memcpy(ret, ptr, oldsize);
- }
-
- return ret;
-}
-
-UPB_INLINE upb_arena *upb_arena_new(void) {
- return upb_arena_init(NULL, 0, &upb_alloc_global);
-}
-
-/* Constants ******************************************************************/
-
-/* Generic function type. */
-typedef void upb_func(void);
-
-/* A list of types as they are encoded on-the-wire. */
-typedef enum {
- UPB_WIRE_TYPE_VARINT = 0,
- UPB_WIRE_TYPE_64BIT = 1,
- UPB_WIRE_TYPE_DELIMITED = 2,
- UPB_WIRE_TYPE_START_GROUP = 3,
- UPB_WIRE_TYPE_END_GROUP = 4,
- UPB_WIRE_TYPE_32BIT = 5
-} upb_wiretype_t;
-
-/* The types a field can have. Note that this list is not identical to the
- * types defined in descriptor.proto, which gives INT32 and SINT32 separate
- * types (we distinguish the two with the "integer encoding" enum below). */
-typedef enum {
- UPB_TYPE_BOOL = 1,
- UPB_TYPE_FLOAT = 2,
- UPB_TYPE_INT32 = 3,
- UPB_TYPE_UINT32 = 4,
- UPB_TYPE_ENUM = 5, /* Enum values are int32. */
- UPB_TYPE_MESSAGE = 6,
- UPB_TYPE_DOUBLE = 7,
- UPB_TYPE_INT64 = 8,
- UPB_TYPE_UINT64 = 9,
- UPB_TYPE_STRING = 10,
- UPB_TYPE_BYTES = 11
-} upb_fieldtype_t;
-
-/* The repeated-ness of each field; this matches descriptor.proto. */
-typedef enum {
- UPB_LABEL_OPTIONAL = 1,
- UPB_LABEL_REQUIRED = 2,
- UPB_LABEL_REPEATED = 3
-} upb_label_t;
-
-/* Descriptor types, as defined in descriptor.proto. */
-typedef enum {
- /* Old (long) names. TODO(haberman): remove */
- UPB_DESCRIPTOR_TYPE_DOUBLE = 1,
- UPB_DESCRIPTOR_TYPE_FLOAT = 2,
- UPB_DESCRIPTOR_TYPE_INT64 = 3,
- UPB_DESCRIPTOR_TYPE_UINT64 = 4,
- UPB_DESCRIPTOR_TYPE_INT32 = 5,
- UPB_DESCRIPTOR_TYPE_FIXED64 = 6,
- UPB_DESCRIPTOR_TYPE_FIXED32 = 7,
- UPB_DESCRIPTOR_TYPE_BOOL = 8,
- UPB_DESCRIPTOR_TYPE_STRING = 9,
- UPB_DESCRIPTOR_TYPE_GROUP = 10,
- UPB_DESCRIPTOR_TYPE_MESSAGE = 11,
- UPB_DESCRIPTOR_TYPE_BYTES = 12,
- UPB_DESCRIPTOR_TYPE_UINT32 = 13,
- UPB_DESCRIPTOR_TYPE_ENUM = 14,
- UPB_DESCRIPTOR_TYPE_SFIXED32 = 15,
- UPB_DESCRIPTOR_TYPE_SFIXED64 = 16,
- UPB_DESCRIPTOR_TYPE_SINT32 = 17,
- UPB_DESCRIPTOR_TYPE_SINT64 = 18,
-
- UPB_DTYPE_DOUBLE = 1,
- UPB_DTYPE_FLOAT = 2,
- UPB_DTYPE_INT64 = 3,
- UPB_DTYPE_UINT64 = 4,
- UPB_DTYPE_INT32 = 5,
- UPB_DTYPE_FIXED64 = 6,
- UPB_DTYPE_FIXED32 = 7,
- UPB_DTYPE_BOOL = 8,
- UPB_DTYPE_STRING = 9,
- UPB_DTYPE_GROUP = 10,
- UPB_DTYPE_MESSAGE = 11,
- UPB_DTYPE_BYTES = 12,
- UPB_DTYPE_UINT32 = 13,
- UPB_DTYPE_ENUM = 14,
- UPB_DTYPE_SFIXED32 = 15,
- UPB_DTYPE_SFIXED64 = 16,
- UPB_DTYPE_SINT32 = 17,
- UPB_DTYPE_SINT64 = 18
-} upb_descriptortype_t;
-
-#define UPB_MAP_BEGIN -1
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* UPB_H_ */
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* upb_value ******************************************************************/
-
-/* A tagged union (stored untagged inside the table) so that we can check that
- * clients calling table accessors are correctly typed without having to have
- * an explosion of accessors. */
-typedef enum {
- UPB_CTYPE_INT32 = 1,
- UPB_CTYPE_INT64 = 2,
- UPB_CTYPE_UINT32 = 3,
- UPB_CTYPE_UINT64 = 4,
- UPB_CTYPE_BOOL = 5,
- UPB_CTYPE_CSTR = 6,
- UPB_CTYPE_PTR = 7,
- UPB_CTYPE_CONSTPTR = 8,
- UPB_CTYPE_FPTR = 9,
- UPB_CTYPE_FLOAT = 10,
- UPB_CTYPE_DOUBLE = 11
-} upb_ctype_t;
-
-typedef struct {
- uint64_t val;
-} upb_value;
-
-/* Like strdup(), which isn't always available since it's not ANSI C. */
-char *upb_strdup(const char *s, upb_alloc *a);
-/* Variant that works with a length-delimited rather than NULL-delimited string,
- * as supported by strtable. */
-char *upb_strdup2(const char *s, size_t len, upb_alloc *a);
-
-UPB_INLINE char *upb_gstrdup(const char *s) {
- return upb_strdup(s, &upb_alloc_global);
-}
-
-UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val) {
- v->val = val;
-}
-
-UPB_INLINE upb_value _upb_value_val(uint64_t val) {
- upb_value ret;
- _upb_value_setval(&ret, val);
- return ret;
-}
-
-/* For each value ctype, define the following set of functions:
- *
- * // Get/set an int32 from a upb_value.
- * int32_t upb_value_getint32(upb_value val);
- * void upb_value_setint32(upb_value *val, int32_t cval);
- *
- * // Construct a new upb_value from an int32.
- * upb_value upb_value_int32(int32_t val); */
-#define FUNCS(name, membername, type_t, converter, proto_type) \
- UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \
- val->val = (converter)cval; \
- } \
- UPB_INLINE upb_value upb_value_ ## name(type_t val) { \
- upb_value ret; \
- upb_value_set ## name(&ret, val); \
- return ret; \
- } \
- UPB_INLINE type_t upb_value_get ## name(upb_value val) { \
- return (type_t)(converter)val.val; \
- }
-
-FUNCS(int32, int32, int32_t, int32_t, UPB_CTYPE_INT32)
-FUNCS(int64, int64, int64_t, int64_t, UPB_CTYPE_INT64)
-FUNCS(uint32, uint32, uint32_t, uint32_t, UPB_CTYPE_UINT32)
-FUNCS(uint64, uint64, uint64_t, uint64_t, UPB_CTYPE_UINT64)
-FUNCS(bool, _bool, bool, bool, UPB_CTYPE_BOOL)
-FUNCS(cstr, cstr, char*, uintptr_t, UPB_CTYPE_CSTR)
-FUNCS(ptr, ptr, void*, uintptr_t, UPB_CTYPE_PTR)
-FUNCS(constptr, constptr, const void*, uintptr_t, UPB_CTYPE_CONSTPTR)
-FUNCS(fptr, fptr, upb_func*, uintptr_t, UPB_CTYPE_FPTR)
-
-#undef FUNCS
-
-UPB_INLINE void upb_value_setfloat(upb_value *val, float cval) {
- memcpy(&val->val, &cval, sizeof(cval));
-}
-
-UPB_INLINE void upb_value_setdouble(upb_value *val, double cval) {
- memcpy(&val->val, &cval, sizeof(cval));
-}
-
-UPB_INLINE upb_value upb_value_float(float cval) {
- upb_value ret;
- upb_value_setfloat(&ret, cval);
- return ret;
-}
-
-UPB_INLINE upb_value upb_value_double(double cval) {
- upb_value ret;
- upb_value_setdouble(&ret, cval);
- return ret;
-}
-
-#undef SET_TYPE
-
-
-/* upb_tabkey *****************************************************************/
-
-/* Either:
- * 1. an actual integer key, or
- * 2. a pointer to a string prefixed by its uint32_t length, owned by us.
- *
- * ...depending on whether this is a string table or an int table. We would
- * make this a union of those two types, but C89 doesn't support statically
- * initializing a non-first union member. */
-typedef uintptr_t upb_tabkey;
-
-UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) {
- char* mem = (char*)key;
- if (len) memcpy(len, mem, sizeof(*len));
- return mem + sizeof(*len);
-}
-
-
-/* upb_tabval *****************************************************************/
-
-typedef struct {
- uint64_t val;
-} upb_tabval;
-
-#define UPB_TABVALUE_EMPTY_INIT {-1}
-
-/* upb_table ******************************************************************/
-
-typedef struct _upb_tabent {
- upb_tabkey key;
- upb_tabval val;
-
- /* Internal chaining. This is const so we can create static initializers for
- * tables. We cast away const sometimes, but *only* when the containing
- * upb_table is known to be non-const. This requires a bit of care, but
- * the subtlety is confined to table.c. */
- const struct _upb_tabent *next;
-} upb_tabent;
-
-typedef struct {
- size_t count; /* Number of entries in the hash part. */
- size_t mask; /* Mask to turn hash value -> bucket. */
- uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */
-
- /* Hash table entries.
- * Making this const isn't entirely accurate; what we really want is for it to
- * have the same const-ness as the table it's inside. But there's no way to
- * declare that in C. So we have to make it const so that we can statically
- * initialize const hash tables. Then we cast away const when we have to.
- */
- const upb_tabent *entries;
-} upb_table;
-
-typedef struct {
- upb_table t;
-} upb_strtable;
-
-typedef struct {
- upb_table t; /* For entries that don't fit in the array part. */
- const upb_tabval *array; /* Array part of the table. See const note above. */
- size_t array_size; /* Array part size. */
- size_t array_count; /* Array part number of elements. */
-} upb_inttable;
-
-#define UPB_ARRAY_EMPTYENT -1
-
-UPB_INLINE size_t upb_table_size(const upb_table *t) {
- if (t->size_lg2 == 0)
- return 0;
- else
- return 1 << t->size_lg2;
-}
-
-/* Internal-only functions, in .h file only out of necessity. */
-UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) {
- return e->key == 0;
-}
-
-/* Used by some of the unit tests for generic hashing functionality. */
-uint32_t upb_murmur_hash2(const void * key, size_t len, uint32_t seed);
-
-UPB_INLINE uintptr_t upb_intkey(uintptr_t key) {
- return key;
-}
-
-UPB_INLINE uint32_t upb_inthash(uintptr_t key) {
- return (uint32_t)key;
-}
-
-static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) {
- return t->entries + (hash & t->mask);
-}
-
-UPB_INLINE bool upb_arrhas(upb_tabval key) {
- return key.val != (uint64_t)-1;
-}
-
-/* Initialize and uninitialize a table, respectively. If memory allocation
- * failed, false is returned that the table is uninitialized. */
-bool upb_inttable_init2(upb_inttable *table, upb_ctype_t ctype, upb_alloc *a);
-bool upb_strtable_init2(upb_strtable *table, upb_ctype_t ctype, upb_alloc *a);
-void upb_inttable_uninit2(upb_inttable *table, upb_alloc *a);
-void upb_strtable_uninit2(upb_strtable *table, upb_alloc *a);
-
-UPB_INLINE bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype) {
- return upb_inttable_init2(table, ctype, &upb_alloc_global);
-}
-
-UPB_INLINE bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype) {
- return upb_strtable_init2(table, ctype, &upb_alloc_global);
-}
-
-UPB_INLINE void upb_inttable_uninit(upb_inttable *table) {
- upb_inttable_uninit2(table, &upb_alloc_global);
-}
-
-UPB_INLINE void upb_strtable_uninit(upb_strtable *table) {
- upb_strtable_uninit2(table, &upb_alloc_global);
-}
-
-/* Returns the number of values in the table. */
-size_t upb_inttable_count(const upb_inttable *t);
-UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) {
- return t->t.count;
-}
-
-void upb_inttable_packedsize(const upb_inttable *t, size_t *size);
-void upb_strtable_packedsize(const upb_strtable *t, size_t *size);
-upb_inttable *upb_inttable_pack(const upb_inttable *t, void *p, size_t *ofs,
- size_t size);
-upb_strtable *upb_strtable_pack(const upb_strtable *t, void *p, size_t *ofs,
- size_t size);
-void upb_strtable_clear(upb_strtable *t);
-
-/* Inserts the given key into the hashtable with the given value. The key must
- * not already exist in the hash table. For string tables, the key must be
- * NULL-terminated, and the table will make an internal copy of the key.
- * Inttables must not insert a value of UINTPTR_MAX.
- *
- * If a table resize was required but memory allocation failed, false is
- * returned and the table is unchanged. */
-bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
- upb_alloc *a);
-bool upb_strtable_insert3(upb_strtable *t, const char *key, size_t len,
- upb_value val, upb_alloc *a);
-
-UPB_INLINE bool upb_inttable_insert(upb_inttable *t, uintptr_t key,
- upb_value val) {
- return upb_inttable_insert2(t, key, val, &upb_alloc_global);
-}
-
-UPB_INLINE bool upb_strtable_insert2(upb_strtable *t, const char *key,
- size_t len, upb_value val) {
- return upb_strtable_insert3(t, key, len, val, &upb_alloc_global);
-}
-
-/* For NULL-terminated strings. */
-UPB_INLINE bool upb_strtable_insert(upb_strtable *t, const char *key,
- upb_value val) {
- return upb_strtable_insert2(t, key, strlen(key), val);
-}
-
-/* Looks up key in this table, returning "true" if the key was found.
- * If v is non-NULL, copies the value for this key into *v. */
-bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v);
-bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
- upb_value *v);
-
-/* For NULL-terminated strings. */
-UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key,
- upb_value *v) {
- return upb_strtable_lookup2(t, key, strlen(key), v);
-}
-
-/* Removes an item from the table. Returns true if the remove was successful,
- * and stores the removed item in *val if non-NULL. */
-bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val);
-bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
- upb_value *val, upb_alloc *alloc);
-
-UPB_INLINE bool upb_strtable_remove2(upb_strtable *t, const char *key,
- size_t len, upb_value *val) {
- return upb_strtable_remove3(t, key, len, val, &upb_alloc_global);
-}
-
-/* For NULL-terminated strings. */
-UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key,
- upb_value *v) {
- return upb_strtable_remove2(t, key, strlen(key), v);
-}
-
-/* Updates an existing entry in an inttable. If the entry does not exist,
- * returns false and does nothing. Unlike insert/remove, this does not
- * invalidate iterators. */
-bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val);
-
-/* Handy routines for treating an inttable like a stack. May not be mixed with
- * other insert/remove calls. */
-bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a);
-upb_value upb_inttable_pop(upb_inttable *t);
-
-UPB_INLINE bool upb_inttable_push(upb_inttable *t, upb_value val) {
- return upb_inttable_push2(t, val, &upb_alloc_global);
-}
-
-/* Convenience routines for inttables with pointer keys. */
-bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
- upb_alloc *a);
-bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val);
-bool upb_inttable_lookupptr(
- const upb_inttable *t, const void *key, upb_value *val);
-
-UPB_INLINE bool upb_inttable_insertptr(upb_inttable *t, const void *key,
- upb_value val) {
- return upb_inttable_insertptr2(t, key, val, &upb_alloc_global);
-}
-
-/* Optimizes the table for the current set of entries, for both memory use and
- * lookup time. Client should call this after all entries have been inserted;
- * inserting more entries is legal, but will likely require a table resize. */
-void upb_inttable_compact2(upb_inttable *t, upb_alloc *a);
-
-UPB_INLINE void upb_inttable_compact(upb_inttable *t) {
- upb_inttable_compact2(t, &upb_alloc_global);
-}
-
-/* A special-case inlinable version of the lookup routine for 32-bit
- * integers. */
-UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key,
- upb_value *v) {
- *v = upb_value_int32(0); /* Silence compiler warnings. */
- if (key < t->array_size) {
- upb_tabval arrval = t->array[key];
- if (upb_arrhas(arrval)) {
- _upb_value_setval(v, arrval.val);
- return true;
- } else {
- return false;
- }
- } else {
- const upb_tabent *e;
- if (t->t.entries == NULL) return false;
- for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) {
- if ((uint32_t)e->key == key) {
- _upb_value_setval(v, e->val.val);
- return true;
- }
- if (e->next == NULL) return false;
- }
- }
-}
-
-/* Exposed for testing only. */
-bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a);
-
-/* Iterators ******************************************************************/
-
-/* Iterators for int and string tables. We are subject to some kind of unusual
- * design constraints:
- *
- * For high-level languages:
- * - we must be able to guarantee that we don't crash or corrupt memory even if
- * the program accesses an invalidated iterator.
- *
- * For C++11 range-based for:
- * - iterators must be copyable
- * - iterators must be comparable
- * - it must be possible to construct an "end" value.
- *
- * Iteration order is undefined.
- *
- * Modifying the table invalidates iterators. upb_{str,int}table_done() is
- * guaranteed to work even on an invalidated iterator, as long as the table it
- * is iterating over has not been freed. Calling next() or accessing data from
- * an invalidated iterator yields unspecified elements from the table, but it is
- * guaranteed not to crash and to return real table elements (except when done()
- * is true). */
-
-
-/* upb_strtable_iter **********************************************************/
-
-/* upb_strtable_iter i;
- * upb_strtable_begin(&i, t);
- * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
- * const char *key = upb_strtable_iter_key(&i);
- * const upb_value val = upb_strtable_iter_value(&i);
- * // ...
- * }
- */
-
-typedef struct {
- const upb_strtable *t;
- size_t index;
-} upb_strtable_iter;
-
-void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t);
-void upb_strtable_next(upb_strtable_iter *i);
-bool upb_strtable_done(const upb_strtable_iter *i);
-upb_strview upb_strtable_iter_key(const upb_strtable_iter *i);
-upb_value upb_strtable_iter_value(const upb_strtable_iter *i);
-void upb_strtable_iter_setdone(upb_strtable_iter *i);
-bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
- const upb_strtable_iter *i2);
-
-
-/* upb_inttable_iter **********************************************************/
-
-/* upb_inttable_iter i;
- * upb_inttable_begin(&i, t);
- * for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- * uintptr_t key = upb_inttable_iter_key(&i);
- * upb_value val = upb_inttable_iter_value(&i);
- * // ...
- * }
- */
-
-typedef struct {
- const upb_inttable *t;
- size_t index;
- bool array_part;
-} upb_inttable_iter;
-
-UPB_INLINE const upb_tabent *str_tabent(const upb_strtable_iter *i) {
- return &i->t->t.entries[i->index];
-}
-
-void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t);
-void upb_inttable_next(upb_inttable_iter *i);
-bool upb_inttable_done(const upb_inttable_iter *i);
-uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i);
-upb_value upb_inttable_iter_value(const upb_inttable_iter *i);
-void upb_inttable_iter_setdone(upb_inttable_iter *i);
-bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
- const upb_inttable_iter *i2);
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-#endif /* UPB_TABLE_H_ */
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs)
-
-typedef void upb_msg;
-
-/** upb_msglayout *************************************************************/
-
-/* upb_msglayout represents the memory layout of a given upb_msgdef. The
- * members are public so generated code can initialize them, but users MUST NOT
- * read or write any of its members. */
-
-/* These aren't real labels according to descriptor.proto, but in the table we
- * use these for map/packed fields instead of UPB_LABEL_REPEATED. */
-enum {
- _UPB_LABEL_MAP = 4,
- _UPB_LABEL_PACKED = 7 /* Low 3 bits are common with UPB_LABEL_REPEATED. */
-};
-
-typedef struct {
- uint32_t number;
- uint16_t offset;
- int16_t presence; /* If >0, hasbit_index. If <0, -oneof_index. */
- uint16_t submsg_index; /* undefined if descriptortype != MESSAGE or GROUP. */
- uint8_t descriptortype;
- uint8_t label;
-} upb_msglayout_field;
-
-typedef struct upb_msglayout {
- const struct upb_msglayout *const* submsgs;
- const upb_msglayout_field *fields;
- /* Must be aligned to sizeof(void*). Doesn't include internal members like
- * unknown fields, extension dict, pointer to msglayout, etc. */
- uint16_t size;
- uint16_t field_count;
- bool extendable;
-} upb_msglayout;
-
-/** upb_msg *******************************************************************/
-
-/* Internal members of a upb_msg. We can change this without breaking binary
- * compatibility. We put these before the user's data. The user's upb_msg*
- * points after the upb_msg_internal. */
-
-/* Used when a message is not extendable. */
-typedef struct {
- char *unknown;
- size_t unknown_len;
- size_t unknown_size;
-} upb_msg_internal;
-
-/* Used when a message is extendable. */
-typedef struct {
- upb_inttable *extdict;
- upb_msg_internal base;
-} upb_msg_internal_withext;
-
-/* Maps upb_fieldtype_t -> memory size. */
-extern char _upb_fieldtype_to_size[12];
-
-/* Creates a new messages with the given layout on the given arena. */
-upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a);
-
-/* Adds unknown data (serialized protobuf data) to the given message. The data
- * is copied into the message instance. */
-bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
- upb_arena *arena);
-
-/* Returns a reference to the message's unknown data. */
-const char *upb_msg_getunknown(const upb_msg *msg, size_t *len);
-
-UPB_INLINE bool _upb_has_field(const void *msg, size_t idx) {
- return (*PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0;
-}
-
-UPB_INLINE bool _upb_sethas(const void *msg, size_t idx) {
- return (*PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8));
-}
-
-UPB_INLINE bool _upb_clearhas(const void *msg, size_t idx) {
- return (*PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8)));
-}
-
-UPB_INLINE bool _upb_has_oneof_field(const void *msg, size_t case_ofs, int32_t num) {
- return *PTR_AT(msg, case_ofs, int32_t) == num;
-}
-
-UPB_INLINE bool _upb_has_submsg_nohasbit(const void *msg, size_t ofs) {
- return *PTR_AT(msg, ofs, const void*) != NULL;
-}
-
-UPB_INLINE bool _upb_isrepeated(const upb_msglayout_field *field) {
- return (field->label & 3) == UPB_LABEL_REPEATED;
-}
-
-/** upb_array *****************************************************************/
-
-/* Our internal representation for repeated fields. */
-typedef struct {
- uintptr_t data; /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */
- size_t len; /* Measured in elements. */
- size_t size; /* Measured in elements. */
-} upb_array;
-
-UPB_INLINE const void *_upb_array_constptr(const upb_array *arr) {
- return (void*)(arr->data & ~(uintptr_t)7);
-}
-
-UPB_INLINE void *_upb_array_ptr(upb_array *arr) {
- return (void*)_upb_array_constptr(arr);
-}
-
-/* Creates a new array on the given arena. */
-upb_array *_upb_array_new(upb_arena *a, upb_fieldtype_t type);
-
-/* Resizes the capacity of the array to be at least min_size. */
-bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena);
-
-/* Fallback functions for when the accessors require a resize. */
-void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
- upb_fieldtype_t type, upb_arena *arena);
-bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
- upb_fieldtype_t type, upb_arena *arena);
-
-UPB_INLINE const void *_upb_array_accessor(const void *msg, size_t ofs,
- size_t *size) {
- const upb_array *arr = *PTR_AT(msg, ofs, const upb_array*);
- if (arr) {
- if (size) *size = arr->len;
- return _upb_array_constptr(arr);
- } else {
- if (size) *size = 0;
- return NULL;
- }
-}
-
-UPB_INLINE void *_upb_array_mutable_accessor(void *msg, size_t ofs,
- size_t *size) {
- upb_array *arr = *PTR_AT(msg, ofs, upb_array*);
- if (arr) {
- if (size) *size = arr->len;
- return _upb_array_ptr(arr);
- } else {
- if (size) *size = 0;
- return NULL;
- }
-}
-
-UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size,
- upb_fieldtype_t type,
- upb_arena *arena) {
- upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array*);
- upb_array *arr = *arr_ptr;
- if (!arr || arr->size < size) {
- return _upb_array_resize_fallback(arr_ptr, size, type, arena);
- }
- arr->len = size;
- return _upb_array_ptr(arr);
-}
-
-
-UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs,
- size_t elem_size,
- upb_fieldtype_t type,
- const void *value,
- upb_arena *arena) {
- upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array*);
- upb_array *arr = *arr_ptr;
- void* ptr;
- if (!arr || arr->len == arr->size) {
- return _upb_array_append_fallback(arr_ptr, value, type, arena);
- }
- ptr = _upb_array_ptr(arr);
- memcpy(PTR_AT(ptr, arr->len * elem_size, char), value, elem_size);
- arr->len++;
- return true;
-}
-
-/** upb_map *******************************************************************/
-
-/* Right now we use strmaps for everything. We'll likely want to use
- * integer-specific maps for integer-keyed maps.*/
-typedef struct {
- /* Size of key and val, based on the map type. Strings are represented as '0'
- * because they must be handled specially. */
- char key_size;
- char val_size;
-
- upb_strtable table;
-} upb_map;
-
-/* Map entries aren't actually stored, they are only used during parsing. For
- * parsing, it helps a lot if all map entry messages have the same layout.
- * The compiler and def.c must ensure that all map entries have this layout. */
-typedef struct {
- upb_msg_internal internal;
- union {
- upb_strview str; /* For str/bytes. */
- upb_value val; /* For all other types. */
- } k;
- union {
- upb_strview str; /* For str/bytes. */
- upb_value val; /* For all other types. */
- } v;
-} upb_map_entry;
-
-/* Creates a new map on the given arena with this key/value type. */
-upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size);
-
-/* Converting between internal table representation and user values.
- *
- * _upb_map_tokey() and _upb_map_fromkey() are inverses.
- * _upb_map_tovalue() and _upb_map_fromvalue() are inverses.
- *
- * These functions account for the fact that strings are treated differently
- * from other types when stored in a map.
- */
-
-UPB_INLINE upb_strview _upb_map_tokey(const void *key, size_t size) {
- if (size == UPB_MAPTYPE_STRING) {
- return *(upb_strview*)key;
- } else {
- return upb_strview_make((const char*)key, size);
- }
-}
-
-UPB_INLINE void _upb_map_fromkey(upb_strview key, void* out, size_t size) {
- if (size == UPB_MAPTYPE_STRING) {
- memcpy(out, &key, sizeof(key));
- } else {
- memcpy(out, key.data, size);
- }
-}
-
-UPB_INLINE upb_value _upb_map_tovalue(const void *val, size_t size,
- upb_arena *a) {
- upb_value ret = {0};
- if (size == UPB_MAPTYPE_STRING) {
- upb_strview *strp = (upb_strview*)upb_arena_malloc(a, sizeof(*strp));
- *strp = *(upb_strview*)val;
- memcpy(&ret, &strp, sizeof(strp));
- } else {
- memcpy(&ret, val, size);
- }
- return ret;
-}
-
-UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) {
- if (size == UPB_MAPTYPE_STRING) {
- const upb_strview *strp = (const upb_strview*)upb_value_getptr(val);
- memcpy(out, strp, sizeof(upb_strview));
- } else {
- memcpy(out, &val, size);
- }
-}
-
-/* Map operations, shared by reflection and generated code. */
-
-UPB_INLINE size_t _upb_map_size(const upb_map *map) {
- return map->table.t.count;
-}
-
-UPB_INLINE bool _upb_map_get(const upb_map *map, const void *key,
- size_t key_size, void *val, size_t val_size) {
- upb_value tabval;
- upb_strview k = _upb_map_tokey(key, key_size);
- bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval);
- if (ret) {
- _upb_map_fromvalue(tabval, val, val_size);
- }
- return ret;
-}
-
-UPB_INLINE void* _upb_map_next(const upb_map *map, size_t *iter) {
- upb_strtable_iter it;
- it.t = &map->table;
- it.index = *iter;
- upb_strtable_next(&it);
- if (upb_strtable_done(&it)) return NULL;
- *iter = it.index;
- return (void*)str_tabent(&it);
-}
-
-UPB_INLINE bool _upb_map_set(upb_map *map, const void *key, size_t key_size,
- void *val, size_t val_size, upb_arena *arena) {
- upb_strview strkey = _upb_map_tokey(key, key_size);
- upb_value tabval = _upb_map_tovalue(val, val_size, arena);
- upb_alloc *a = upb_arena_alloc(arena);
-
- /* TODO(haberman): add overwrite operation to minimize number of lookups. */
- upb_strtable_remove3(&map->table, strkey.data, strkey.size, NULL, a);
- return upb_strtable_insert3(&map->table, strkey.data, strkey.size, tabval, a);
-}
-
-UPB_INLINE bool _upb_map_delete(upb_map *map, const void *key, size_t key_size) {
- upb_strview k = _upb_map_tokey(key, key_size);
- return upb_strtable_remove3(&map->table, k.data, k.size, NULL, NULL);
-}
-
-UPB_INLINE void _upb_map_clear(upb_map *map) {
- upb_strtable_clear(&map->table);
-}
-
-/* Message map operations, these get the map from the message first. */
-
-UPB_INLINE size_t _upb_msg_map_size(const upb_msg *msg, size_t ofs) {
- upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
- return map ? _upb_map_size(map) : 0;
-}
-
-UPB_INLINE bool _upb_msg_map_get(const upb_msg *msg, size_t ofs,
- const void *key, size_t key_size, void *val,
- size_t val_size) {
- upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
- if (!map) return false;
- return _upb_map_get(map, key, key_size, val, val_size);
-}
-
-UPB_INLINE void *_upb_msg_map_next(const upb_msg *msg, size_t ofs,
- size_t *iter) {
- upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
- if (!map) return NULL;
- return _upb_map_next(map, iter);
-}
-
-UPB_INLINE bool _upb_msg_map_set(upb_msg *msg, size_t ofs, const void *key,
- size_t key_size, void *val, size_t val_size,
- upb_arena *arena) {
- upb_map **map = PTR_AT(msg, ofs, upb_map *);
- if (!*map) {
- *map = _upb_map_new(arena, key_size, val_size);
- }
- return _upb_map_set(*map, key, key_size, val, val_size, arena);
-}
-
-UPB_INLINE bool _upb_msg_map_delete(upb_msg *msg, size_t ofs, const void *key,
- size_t key_size) {
- upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
- if (!map) return false;
- return _upb_map_delete(map, key, key_size);
-}
-
-UPB_INLINE void _upb_msg_map_clear(upb_msg *msg, size_t ofs) {
- upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
- if (!map) return;
- _upb_map_clear(map);
-}
-
-/* Accessing map key/value from a pointer, used by generated code only. */
-
-UPB_INLINE void _upb_msg_map_key(const void* msg, void* key, size_t size) {
- const upb_tabent *ent = (const upb_tabent*)msg;
- uint32_t u32len;
- upb_strview k;
- k.data = upb_tabstr(ent->key, &u32len);
- k.size = u32len;
- _upb_map_fromkey(k, key, size);
-}
-
-UPB_INLINE void _upb_msg_map_value(const void* msg, void* val, size_t size) {
- const upb_tabent *ent = (const upb_tabent*)msg;
- upb_value v;
- _upb_value_setval(&v, ent->val.val);
- _upb_map_fromvalue(v, val, size);
-}
-
-UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, size_t size) {
- upb_tabent *ent = (upb_tabent*)msg;
- /* This is like _upb_map_tovalue() except the entry already exists so we can
- * reuse the allocated upb_strview for string fields. */
- if (size == UPB_MAPTYPE_STRING) {
- upb_strview *strp = (upb_strview*)ent->val.val;
- memcpy(strp, val, sizeof(*strp));
- } else {
- memcpy(&ent->val.val, val, size);
- }
-}
-
-#undef PTR_AT
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-#endif /* UPB_MSG_H_ */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-bool upb_decode(const char *buf, size_t size, upb_msg *msg,
- const upb_msglayout *l, upb_arena *arena);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* UPB_DECODE_H_ */
-/*
-** upb_encode: parsing into a upb_msg using a upb_msglayout.
-*/
-
-#ifndef UPB_ENCODE_H_
-#define UPB_ENCODE_H_
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-char *upb_encode(const void *msg, const upb_msglayout *l, upb_arena *arena,
- size_t *size);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* UPB_ENCODE_H_ */
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- * google/protobuf/descriptor.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_
-#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_
-
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct google_protobuf_FileDescriptorSet;
-struct google_protobuf_FileDescriptorProto;
-struct google_protobuf_DescriptorProto;
-struct google_protobuf_DescriptorProto_ExtensionRange;
-struct google_protobuf_DescriptorProto_ReservedRange;
-struct google_protobuf_ExtensionRangeOptions;
-struct google_protobuf_FieldDescriptorProto;
-struct google_protobuf_OneofDescriptorProto;
-struct google_protobuf_EnumDescriptorProto;
-struct google_protobuf_EnumDescriptorProto_EnumReservedRange;
-struct google_protobuf_EnumValueDescriptorProto;
-struct google_protobuf_ServiceDescriptorProto;
-struct google_protobuf_MethodDescriptorProto;
-struct google_protobuf_FileOptions;
-struct google_protobuf_MessageOptions;
-struct google_protobuf_FieldOptions;
-struct google_protobuf_OneofOptions;
-struct google_protobuf_EnumOptions;
-struct google_protobuf_EnumValueOptions;
-struct google_protobuf_ServiceOptions;
-struct google_protobuf_MethodOptions;
-struct google_protobuf_UninterpretedOption;
-struct google_protobuf_UninterpretedOption_NamePart;
-struct google_protobuf_SourceCodeInfo;
-struct google_protobuf_SourceCodeInfo_Location;
-struct google_protobuf_GeneratedCodeInfo;
-struct google_protobuf_GeneratedCodeInfo_Annotation;
-typedef struct google_protobuf_FileDescriptorSet google_protobuf_FileDescriptorSet;
-typedef struct google_protobuf_FileDescriptorProto google_protobuf_FileDescriptorProto;
-typedef struct google_protobuf_DescriptorProto google_protobuf_DescriptorProto;
-typedef struct google_protobuf_DescriptorProto_ExtensionRange google_protobuf_DescriptorProto_ExtensionRange;
-typedef struct google_protobuf_DescriptorProto_ReservedRange google_protobuf_DescriptorProto_ReservedRange;
-typedef struct google_protobuf_ExtensionRangeOptions google_protobuf_ExtensionRangeOptions;
-typedef struct google_protobuf_FieldDescriptorProto google_protobuf_FieldDescriptorProto;
-typedef struct google_protobuf_OneofDescriptorProto google_protobuf_OneofDescriptorProto;
-typedef struct google_protobuf_EnumDescriptorProto google_protobuf_EnumDescriptorProto;
-typedef struct google_protobuf_EnumDescriptorProto_EnumReservedRange google_protobuf_EnumDescriptorProto_EnumReservedRange;
-typedef struct google_protobuf_EnumValueDescriptorProto google_protobuf_EnumValueDescriptorProto;
-typedef struct google_protobuf_ServiceDescriptorProto google_protobuf_ServiceDescriptorProto;
-typedef struct google_protobuf_MethodDescriptorProto google_protobuf_MethodDescriptorProto;
-typedef struct google_protobuf_FileOptions google_protobuf_FileOptions;
-typedef struct google_protobuf_MessageOptions google_protobuf_MessageOptions;
-typedef struct google_protobuf_FieldOptions google_protobuf_FieldOptions;
-typedef struct google_protobuf_OneofOptions google_protobuf_OneofOptions;
-typedef struct google_protobuf_EnumOptions google_protobuf_EnumOptions;
-typedef struct google_protobuf_EnumValueOptions google_protobuf_EnumValueOptions;
-typedef struct google_protobuf_ServiceOptions google_protobuf_ServiceOptions;
-typedef struct google_protobuf_MethodOptions google_protobuf_MethodOptions;
-typedef struct google_protobuf_UninterpretedOption google_protobuf_UninterpretedOption;
-typedef struct google_protobuf_UninterpretedOption_NamePart google_protobuf_UninterpretedOption_NamePart;
-typedef struct google_protobuf_SourceCodeInfo google_protobuf_SourceCodeInfo;
-typedef struct google_protobuf_SourceCodeInfo_Location google_protobuf_SourceCodeInfo_Location;
-typedef struct google_protobuf_GeneratedCodeInfo google_protobuf_GeneratedCodeInfo;
-typedef struct google_protobuf_GeneratedCodeInfo_Annotation google_protobuf_GeneratedCodeInfo_Annotation;
-extern const upb_msglayout google_protobuf_FileDescriptorSet_msginit;
-extern const upb_msglayout google_protobuf_FileDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_DescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit;
-extern const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit;
-extern const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit;
-extern const upb_msglayout google_protobuf_FieldDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_OneofDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_EnumDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit;
-extern const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_MethodDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_FileOptions_msginit;
-extern const upb_msglayout google_protobuf_MessageOptions_msginit;
-extern const upb_msglayout google_protobuf_FieldOptions_msginit;
-extern const upb_msglayout google_protobuf_OneofOptions_msginit;
-extern const upb_msglayout google_protobuf_EnumOptions_msginit;
-extern const upb_msglayout google_protobuf_EnumValueOptions_msginit;
-extern const upb_msglayout google_protobuf_ServiceOptions_msginit;
-extern const upb_msglayout google_protobuf_MethodOptions_msginit;
-extern const upb_msglayout google_protobuf_UninterpretedOption_msginit;
-extern const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit;
-extern const upb_msglayout google_protobuf_SourceCodeInfo_msginit;
-extern const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit;
-extern const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit;
-extern const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit;
-
-typedef enum {
- google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1,
- google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2,
- google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3
-} google_protobuf_FieldDescriptorProto_Label;
-
-typedef enum {
- google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1,
- google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2,
- google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3,
- google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4,
- google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5,
- google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6,
- google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7,
- google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8,
- google_protobuf_FieldDescriptorProto_TYPE_STRING = 9,
- google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10,
- google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11,
- google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12,
- google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13,
- google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14,
- google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15,
- google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16,
- google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17,
- google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18
-} google_protobuf_FieldDescriptorProto_Type;
-
-typedef enum {
- google_protobuf_FieldOptions_STRING = 0,
- google_protobuf_FieldOptions_CORD = 1,
- google_protobuf_FieldOptions_STRING_PIECE = 2
-} google_protobuf_FieldOptions_CType;
-
-typedef enum {
- google_protobuf_FieldOptions_JS_NORMAL = 0,
- google_protobuf_FieldOptions_JS_STRING = 1,
- google_protobuf_FieldOptions_JS_NUMBER = 2
-} google_protobuf_FieldOptions_JSType;
-
-typedef enum {
- google_protobuf_FileOptions_SPEED = 1,
- google_protobuf_FileOptions_CODE_SIZE = 2,
- google_protobuf_FileOptions_LITE_RUNTIME = 3
-} google_protobuf_FileOptions_OptimizeMode;
-
-typedef enum {
- google_protobuf_MethodOptions_IDEMPOTENCY_UNKNOWN = 0,
- google_protobuf_MethodOptions_NO_SIDE_EFFECTS = 1,
- google_protobuf_MethodOptions_IDEMPOTENT = 2
-} google_protobuf_MethodOptions_IdempotencyLevel;
-
-
-/* google.protobuf.FileDescriptorSet */
-
-UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_new(upb_arena *arena) {
- return (google_protobuf_FileDescriptorSet *)_upb_msg_new(&google_protobuf_FileDescriptorSet_msginit, arena);
-}
-UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize(const google_protobuf_FileDescriptorSet *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FileDescriptorSet_has_file(const google_protobuf_FileDescriptorSet *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet *msg, size_t *len) { return (const google_protobuf_FileDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_mutable_file(google_protobuf_FileDescriptorSet *msg, size_t *len) {
- return (google_protobuf_FileDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_resize_file(google_protobuf_FileDescriptorSet *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_FileDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorSet_add_file(google_protobuf_FileDescriptorSet *msg, upb_arena *arena) {
- struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-
-/* google.protobuf.FileDescriptorProto */
-
-UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_new(upb_arena *arena) {
- return (google_protobuf_FileDescriptorProto *)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize(const google_protobuf_FileDescriptorProto *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_FileDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
-UPB_INLINE upb_strview const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_message_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); }
-UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_enum_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(44, 88)); }
-UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_service(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(48, 96)); }
-UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_ServiceDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(48, 96), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_extension(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(52, 104)); }
-UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(52, 104), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_FileOptions*); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 64), const google_protobuf_SourceCodeInfo*); }
-UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(56, 112), len); }
-UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(60, 120), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); }
-
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
-}
-UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
- return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
-}
-UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
- return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto *msg, upb_strview val, upb_arena *arena) {
- return _upb_array_append_accessor(msg, UPB_SIZE(36, 72), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val,
- arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_mutable_message_type(google_protobuf_FileDescriptorProto *msg, size_t *len) {
- return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_resize_message_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescriptorProto_add_message_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(40, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_mutable_enum_type(google_protobuf_FileDescriptorProto *msg, size_t *len) {
- return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_resize_enum_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescriptorProto_add_enum_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(44, 88), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_mutable_service(google_protobuf_FileDescriptorProto *msg, size_t *len) {
- return (google_protobuf_ServiceDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 96), len);
-}
-UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_resize_service(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_ServiceDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(48, 96), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDescriptorProto_add_service(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(48, 96), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_mutable_extension(google_protobuf_FileDescriptorProto *msg, size_t *len) {
- return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 104), len);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_resize_extension(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(52, 104), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDescriptorProto_add_extension(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(52, 104), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) {
- _upb_sethas(msg, 4);
- *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_FileOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_FileOptions* sub = (struct google_protobuf_FileOptions*)google_protobuf_FileDescriptorProto_options(msg);
- if (sub == NULL) {
- sub = (struct google_protobuf_FileOptions*)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena);
- if (!sub) return NULL;
- google_protobuf_FileDescriptorProto_set_options(msg, sub);
- }
- return sub;
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) {
- _upb_sethas(msg, 5);
- *UPB_PTR_AT(msg, UPB_SIZE(32, 64), google_protobuf_SourceCodeInfo*) = value;
-}
-UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_SourceCodeInfo* sub = (struct google_protobuf_SourceCodeInfo*)google_protobuf_FileDescriptorProto_source_code_info(msg);
- if (sub == NULL) {
- sub = (struct google_protobuf_SourceCodeInfo*)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena);
- if (!sub) return NULL;
- google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub);
- }
- return sub;
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
- return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 112), len);
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
- return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(56, 112), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_FileDescriptorProto_add_public_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) {
- return _upb_array_append_accessor(msg, UPB_SIZE(56, 112), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
- arena);
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
- return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(60, 120), len);
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
- return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(60, 120), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) {
- return _upb_array_append_accessor(msg, UPB_SIZE(60, 120), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
- arena);
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 3);
- *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value;
-}
-
-/* google.protobuf.DescriptorProto */
-
-UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_new(upb_arena *arena) {
- return (google_protobuf_DescriptorProto *)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_DescriptorProto_serialize(const google_protobuf_DescriptorProto *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_DescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_field(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
-UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_nested_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); }
-UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_enum_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(24, 48)); }
-UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_extension_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 56)); }
-UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ExtensionRange* const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_extension(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(32, 64)); }
-UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(32, 64), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_MessageOptions*); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_oneof_decl(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(36, 72)); }
-UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_OneofDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_reserved_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); }
-UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
-UPB_INLINE upb_strview const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
-
-UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_field(google_protobuf_DescriptorProto *msg, size_t *len) {
- return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_field(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_field(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_mutable_nested_type(google_protobuf_DescriptorProto *msg, size_t *len) {
- return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_resize_nested_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_add_nested_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(20, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_mutable_enum_type(google_protobuf_DescriptorProto *msg, size_t *len) {
- return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_resize_enum_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_DescriptorProto_add_enum_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(24, 48), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_mutable_extension_range(google_protobuf_DescriptorProto *msg, size_t *len) {
- return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_resize_extension_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_add_extension_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(28, 56), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_extension(google_protobuf_DescriptorProto *msg, size_t *len) {
- return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 64), len);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_extension(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(32, 64), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_extension(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(32, 64), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_MessageOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProto_mutable_options(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_MessageOptions* sub = (struct google_protobuf_MessageOptions*)google_protobuf_DescriptorProto_options(msg);
- if (sub == NULL) {
- sub = (struct google_protobuf_MessageOptions*)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena);
- if (!sub) return NULL;
- google_protobuf_DescriptorProto_set_options(msg, sub);
- }
- return sub;
-}
-UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_mutable_oneof_decl(google_protobuf_DescriptorProto *msg, size_t *len) {
- return (google_protobuf_OneofDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
-}
-UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_resize_oneof_decl(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_OneofDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_DescriptorProto_add_oneof_decl(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(36, 72), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_mutable_reserved_range(google_protobuf_DescriptorProto *msg, size_t *len) {
- return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_resize_reserved_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_add_reserved_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(40, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE upb_strview* google_protobuf_DescriptorProto_mutable_reserved_name(google_protobuf_DescriptorProto *msg, size_t *len) {
- return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
-}
-UPB_INLINE upb_strview* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
- return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto *msg, upb_strview val, upb_arena *arena) {
- return _upb_array_append_accessor(msg, UPB_SIZE(44, 88), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val,
- arena);
-}
-
-/* google.protobuf.DescriptorProto.ExtensionRange */
-
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_new(upb_arena *arena) {
- return (google_protobuf_DescriptorProto_ExtensionRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize(const google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const google_protobuf_ExtensionRangeOptions*); }
-
-UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_start(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) {
- _upb_sethas(msg, 3);
- *UPB_PTR_AT(msg, UPB_SIZE(12, 16), google_protobuf_ExtensionRangeOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_mutable_options(google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena) {
- struct google_protobuf_ExtensionRangeOptions* sub = (struct google_protobuf_ExtensionRangeOptions*)google_protobuf_DescriptorProto_ExtensionRange_options(msg);
- if (sub == NULL) {
- sub = (struct google_protobuf_ExtensionRangeOptions*)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena);
- if (!sub) return NULL;
- google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub);
- }
- return sub;
-}
-
-/* google.protobuf.DescriptorProto.ReservedRange */
-
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_new(upb_arena *arena) {
- return (google_protobuf_DescriptorProto_ReservedRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize(const google_protobuf_DescriptorProto_ReservedRange *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-
-UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_start(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-
-/* google.protobuf.ExtensionRangeOptions */
-
-UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_new(upb_arena *arena) {
- return (google_protobuf_ExtensionRangeOptions *)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize(const google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t *len) {
- return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_resize_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ExtensionRangeOptions_add_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena) {
- struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-
-/* google.protobuf.FieldDescriptorProto */
-
-UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_new(upb_arena *arena) {
- return (google_protobuf_FieldDescriptorProto *)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_protobuf_FieldDescriptorProto *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 40), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 7); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 56), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), int32_t); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 8); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 72), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 9); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 88), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 11); }
-UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 120), const google_protobuf_FieldOptions*); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 28), int32_t); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 10); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 104), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), bool); }
-
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 6);
- *UPB_PTR_AT(msg, UPB_SIZE(36, 40), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 7);
- *UPB_PTR_AT(msg, UPB_SIZE(44, 56), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
- _upb_sethas(msg, 3);
- *UPB_PTR_AT(msg, UPB_SIZE(24, 24), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 8);
- *UPB_PTR_AT(msg, UPB_SIZE(52, 72), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 9);
- *UPB_PTR_AT(msg, UPB_SIZE(60, 88), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) {
- _upb_sethas(msg, 11);
- *UPB_PTR_AT(msg, UPB_SIZE(76, 120), google_protobuf_FieldOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg);
- if (sub == NULL) {
- sub = (struct google_protobuf_FieldOptions*)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena);
- if (!sub) return NULL;
- google_protobuf_FieldDescriptorProto_set_options(msg, sub);
- }
- return sub;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
- _upb_sethas(msg, 4);
- *UPB_PTR_AT(msg, UPB_SIZE(28, 28), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 10);
- *UPB_PTR_AT(msg, UPB_SIZE(68, 104), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) {
- _upb_sethas(msg, 5);
- *UPB_PTR_AT(msg, UPB_SIZE(32, 32), bool) = value;
-}
-
-/* google.protobuf.OneofDescriptorProto */
-
-UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_new(upb_arena *arena) {
- return (google_protobuf_OneofDescriptorProto *)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize(const google_protobuf_OneofDescriptorProto *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_OneofDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_OneofOptions*); }
-
-UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_OneofOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_mutable_options(google_protobuf_OneofDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_OneofOptions* sub = (struct google_protobuf_OneofOptions*)google_protobuf_OneofDescriptorProto_options(msg);
- if (sub == NULL) {
- sub = (struct google_protobuf_OneofOptions*)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena);
- if (!sub) return NULL;
- google_protobuf_OneofDescriptorProto_set_options(msg, sub);
- }
- return sub;
-}
-
-/* google.protobuf.EnumDescriptorProto */
-
-UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_new(upb_arena *arena) {
- return (google_protobuf_EnumDescriptorProto *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize(const google_protobuf_EnumDescriptorProto *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_EnumDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_value(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
-UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumValueDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_EnumOptions*); }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_reserved_range(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); }
-UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto_EnumReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
-UPB_INLINE upb_strview const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
-
-UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_mutable_value(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
- return (google_protobuf_EnumValueDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
-}
-UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_resize_value(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_EnumValueDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumDescriptorProto_add_value(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_EnumOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_mutable_options(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_EnumOptions* sub = (struct google_protobuf_EnumOptions*)google_protobuf_EnumDescriptorProto_options(msg);
- if (sub == NULL) {
- sub = (struct google_protobuf_EnumOptions*)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena);
- if (!sub) return NULL;
- google_protobuf_EnumDescriptorProto_set_options(msg, sub);
- }
- return sub;
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_mutable_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
- return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_resize_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_add_reserved_range(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(20, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_mutable_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
- return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
-}
-UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
- return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto *msg, upb_strview val, upb_arena *arena) {
- return _upb_array_append_accessor(msg, UPB_SIZE(24, 48), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val,
- arena);
-}
-
-/* google.protobuf.EnumDescriptorProto.EnumReservedRange */
-
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_new(upb_arena *arena) {
- return (google_protobuf_EnumDescriptorProto_EnumReservedRange *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-
-UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-
-/* google.protobuf.EnumValueDescriptorProto */
-
-UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_new(upb_arena *arena) {
- return (google_protobuf_EnumValueDescriptorProto *)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize(const google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const google_protobuf_EnumValueOptions*); }
-
-UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) {
- _upb_sethas(msg, 3);
- *UPB_PTR_AT(msg, UPB_SIZE(16, 24), google_protobuf_EnumValueOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_mutable_options(google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_EnumValueOptions* sub = (struct google_protobuf_EnumValueOptions*)google_protobuf_EnumValueDescriptorProto_options(msg);
- if (sub == NULL) {
- sub = (struct google_protobuf_EnumValueOptions*)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena);
- if (!sub) return NULL;
- google_protobuf_EnumValueDescriptorProto_set_options(msg, sub);
- }
- return sub;
-}
-
-/* google.protobuf.ServiceDescriptorProto */
-
-UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_new(upb_arena *arena) {
- return (google_protobuf_ServiceDescriptorProto *)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize(const google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_method(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
-UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto *msg, size_t *len) { return (const google_protobuf_MethodDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
-UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_ServiceOptions*); }
-
-UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_mutable_method(google_protobuf_ServiceDescriptorProto *msg, size_t *len) {
- return (google_protobuf_MethodDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
-}
-UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_resize_method(google_protobuf_ServiceDescriptorProto *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_MethodDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_ServiceDescriptorProto_add_method(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_ServiceOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_mutable_options(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_ServiceOptions* sub = (struct google_protobuf_ServiceOptions*)google_protobuf_ServiceDescriptorProto_options(msg);
- if (sub == NULL) {
- sub = (struct google_protobuf_ServiceOptions*)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena);
- if (!sub) return NULL;
- google_protobuf_ServiceDescriptorProto_set_options(msg, sub);
- }
- return sub;
-}
-
-/* google.protobuf.MethodDescriptorProto */
-
-UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_new(upb_arena *arena) {
- return (google_protobuf_MethodDescriptorProto *)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize(const google_protobuf_MethodDescriptorProto *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_MethodDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_MethodOptions*); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
-
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 3);
- *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 4);
- *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
- _upb_sethas(msg, 5);
- *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) {
- _upb_sethas(msg, 6);
- *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_MethodOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto *msg, upb_arena *arena) {
- struct google_protobuf_MethodOptions* sub = (struct google_protobuf_MethodOptions*)google_protobuf_MethodDescriptorProto_options(msg);
- if (sub == NULL) {
- sub = (struct google_protobuf_MethodOptions*)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena);
- if (!sub) return NULL;
- google_protobuf_MethodDescriptorProto_set_options(msg, sub);
- }
- return sub;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
-}
-
-/* google.protobuf.FileOptions */
-
-UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_new(upb_arena *arena) {
- return (google_protobuf_FileOptions *)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FileOptions_serialize(const google_protobuf_FileOptions *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_FileOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 11); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 32), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 12); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 48), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 13); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 64), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(17, 17), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(18, 18), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(19, 19), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 7); }
-UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(21, 21), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 8); }
-UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(22, 22), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 9); }
-UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(23, 23), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 14); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 80), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 15); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 96), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 16); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 112), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 17); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 128), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 18); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(84, 144), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 10); }
-UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 19); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(92, 160), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 20); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(100, 176), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_uninterpreted_option(const google_protobuf_FileOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(108, 192)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(108, 192), len); }
-
-UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_strview value) {
- _upb_sethas(msg, 11);
- *UPB_PTR_AT(msg, UPB_SIZE(28, 32), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_strview value) {
- _upb_sethas(msg, 12);
- *UPB_PTR_AT(msg, UPB_SIZE(36, 48), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_strview value) {
- _upb_sethas(msg, 13);
- *UPB_PTR_AT(msg, UPB_SIZE(44, 64), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) {
- _upb_sethas(msg, 3);
- *UPB_PTR_AT(msg, UPB_SIZE(17, 17), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) {
- _upb_sethas(msg, 4);
- *UPB_PTR_AT(msg, UPB_SIZE(18, 18), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) {
- _upb_sethas(msg, 5);
- *UPB_PTR_AT(msg, UPB_SIZE(19, 19), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) {
- _upb_sethas(msg, 6);
- *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) {
- _upb_sethas(msg, 7);
- *UPB_PTR_AT(msg, UPB_SIZE(21, 21), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) {
- _upb_sethas(msg, 8);
- *UPB_PTR_AT(msg, UPB_SIZE(22, 22), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) {
- _upb_sethas(msg, 9);
- *UPB_PTR_AT(msg, UPB_SIZE(23, 23), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
- _upb_sethas(msg, 14);
- *UPB_PTR_AT(msg, UPB_SIZE(52, 80), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
- _upb_sethas(msg, 15);
- *UPB_PTR_AT(msg, UPB_SIZE(60, 96), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
- _upb_sethas(msg, 16);
- *UPB_PTR_AT(msg, UPB_SIZE(68, 112), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
- _upb_sethas(msg, 17);
- *UPB_PTR_AT(msg, UPB_SIZE(76, 128), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
- _upb_sethas(msg, 18);
- *UPB_PTR_AT(msg, UPB_SIZE(84, 144), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) {
- _upb_sethas(msg, 10);
- *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
- _upb_sethas(msg, 19);
- *UPB_PTR_AT(msg, UPB_SIZE(92, 160), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_strview value) {
- _upb_sethas(msg, 20);
- *UPB_PTR_AT(msg, UPB_SIZE(100, 176), upb_strview) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mutable_uninterpreted_option(google_protobuf_FileOptions *msg, size_t *len) {
- return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(108, 192), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_resize_uninterpreted_option(google_protobuf_FileOptions *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(108, 192), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptions_add_uninterpreted_option(google_protobuf_FileOptions *msg, upb_arena *arena) {
- struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(108, 192), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-
-/* google.protobuf.MessageOptions */
-
-UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_new(upb_arena *arena) {
- return (google_protobuf_MessageOptions *)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_MessageOptions_serialize(const google_protobuf_MessageOptions *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_MessageOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_MessageOptions_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_uninterpreted_option(const google_protobuf_MessageOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 8)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(8, 8), len); }
-
-UPB_INLINE void google_protobuf_MessageOptions_set_message_set_wire_format(google_protobuf_MessageOptions *msg, bool value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
-}
-UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) {
- _upb_sethas(msg, 3);
- *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool) = value;
-}
-UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) {
- _upb_sethas(msg, 4);
- *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_mutable_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t *len) {
- return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_resize_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(8, 8), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOptions_add_uninterpreted_option(google_protobuf_MessageOptions *msg, upb_arena *arena) {
- struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(8, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-
-/* google.protobuf.FieldOptions */
-
-UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_new(upb_arena *arena) {
- return (google_protobuf_FieldOptions *)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FieldOptions_serialize(const google_protobuf_FieldOptions *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_FieldOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(25, 25), bool); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(26, 26), bool); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(27, 27), bool); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_uninterpreted_option(const google_protobuf_FieldOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 32)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(28, 32), len); }
-
-UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOptions *msg, int32_t value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) {
- _upb_sethas(msg, 3);
- *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) {
- _upb_sethas(msg, 4);
- *UPB_PTR_AT(msg, UPB_SIZE(25, 25), bool) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) {
- _upb_sethas(msg, 5);
- *UPB_PTR_AT(msg, UPB_SIZE(26, 26), bool) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) {
- _upb_sethas(msg, 6);
- *UPB_PTR_AT(msg, UPB_SIZE(27, 27), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t *len) {
- return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 32), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_resize_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 32), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOptions_add_uninterpreted_option(google_protobuf_FieldOptions *msg, upb_arena *arena) {
- struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(28, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-
-/* google.protobuf.OneofOptions */
-
-UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_new(upb_arena *arena) {
- return (google_protobuf_OneofOptions *)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_OneofOptions_serialize(const google_protobuf_OneofOptions *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_OneofOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_OneofOptions_has_uninterpreted_option(const google_protobuf_OneofOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mutable_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t *len) {
- return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_resize_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOptions_add_uninterpreted_option(google_protobuf_OneofOptions *msg, upb_arena *arena) {
- struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-
-/* google.protobuf.EnumOptions */
-
-UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_new(upb_arena *arena) {
- return (google_protobuf_EnumOptions *)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumOptions_serialize(const google_protobuf_EnumOptions *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_EnumOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
-UPB_INLINE bool google_protobuf_EnumOptions_has_uninterpreted_option(const google_protobuf_EnumOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
-
-UPB_INLINE void google_protobuf_EnumOptions_set_allow_alias(google_protobuf_EnumOptions *msg, bool value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mutable_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t *len) {
- return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_resize_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptions_add_uninterpreted_option(google_protobuf_EnumOptions *msg, upb_arena *arena) {
- struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-
-/* google.protobuf.EnumValueOptions */
-
-UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_new(upb_arena *arena) {
- return (google_protobuf_EnumValueOptions *)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumValueOptions_serialize(const google_protobuf_EnumValueOptions *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_EnumValueOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_EnumValueOptions_has_uninterpreted_option(const google_protobuf_EnumValueOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
-
-UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_EnumValueOptions *msg, bool value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t *len) {
- return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_resize_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValueOptions_add_uninterpreted_option(google_protobuf_EnumValueOptions *msg, upb_arena *arena) {
- struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-
-/* google.protobuf.ServiceOptions */
-
-UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_new(upb_arena *arena) {
- return (google_protobuf_ServiceOptions *)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_ServiceOptions_serialize(const google_protobuf_ServiceOptions *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_ServiceOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_ServiceOptions_has_uninterpreted_option(const google_protobuf_ServiceOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
-
-UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_ServiceOptions *msg, bool value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_mutable_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t *len) {
- return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_resize_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOptions_add_uninterpreted_option(google_protobuf_ServiceOptions *msg, upb_arena *arena) {
- struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-
-/* google.protobuf.MethodOptions */
-
-UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_new(upb_arena *arena) {
- return (google_protobuf_MethodOptions *)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_MethodOptions_serialize(const google_protobuf_MethodOptions *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_MethodOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); }
-UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_MethodOptions_has_uninterpreted_option(const google_protobuf_MethodOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 24)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(20, 24), len); }
-
-UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value;
-}
-UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t *len) {
- return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 24), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_resize_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 24), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOptions_add_uninterpreted_option(google_protobuf_MethodOptions *msg, upb_arena *arena) {
- struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(20, 24), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-
-/* google.protobuf.UninterpretedOption */
-
-UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_new(upb_arena *arena) {
- return (google_protobuf_UninterpretedOption *)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-}
-UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_UninterpretedOption_serialize(const google_protobuf_UninterpretedOption *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_name(const google_protobuf_UninterpretedOption *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(56, 80)); }
-UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg, size_t *len) { return (const google_protobuf_UninterpretedOption_NamePart* const*)_upb_array_accessor(msg, UPB_SIZE(56, 80), len); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview); }
-
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_mutable_name(google_protobuf_UninterpretedOption *msg, size_t *len) {
- return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 80), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_resize_name(google_protobuf_UninterpretedOption *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_resize_accessor(msg, UPB_SIZE(56, 80), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_add_name(google_protobuf_UninterpretedOption *msg, upb_arena *arena) {
- struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(56, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
- _upb_sethas(msg, 4);
- *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) {
- _upb_sethas(msg, 3);
- *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
- _upb_sethas(msg, 5);
- *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
- _upb_sethas(msg, 6);
- *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview) = value;
-}
-
-/* google.protobuf.UninterpretedOption.NamePart */
-
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_new(upb_arena *arena) {
- return (google_protobuf_UninterpretedOption_NamePart *)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
-}
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize(const google_protobuf_UninterpretedOption_NamePart *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-
-UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_strview value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-
-/* google.protobuf.SourceCodeInfo */
-
-UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_new(upb_arena *arena) {
- return (google_protobuf_SourceCodeInfo *)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena);
-}
-UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize(const google_protobuf_SourceCodeInfo *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_SourceCodeInfo_has_location(const google_protobuf_SourceCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo *msg, size_t *len) { return (const google_protobuf_SourceCodeInfo_Location* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_mutable_location(google_protobuf_SourceCodeInfo *msg, size_t *len) {
- return (google_protobuf_SourceCodeInfo_Location**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_resize_location(google_protobuf_SourceCodeInfo *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_SourceCodeInfo_Location**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_add_location(google_protobuf_SourceCodeInfo *msg, upb_arena *arena) {
- struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-
-/* google.protobuf.SourceCodeInfo.Location */
-
-UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_new(upb_arena *arena) {
- return (google_protobuf_SourceCodeInfo_Location *)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
-}
-UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize(const google_protobuf_SourceCodeInfo_Location *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, arena, len);
-}
-
-UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
-UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
-UPB_INLINE upb_strview const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
-
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_path(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
- return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
-}
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_path(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
- return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_path(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) {
- return _upb_array_append_accessor(msg, UPB_SIZE(20, 40), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
- arena);
-}
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_span(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
- return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
-}
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_span(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
- return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_span(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) {
- return _upb_array_append_accessor(msg, UPB_SIZE(24, 48), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
- arena);
-}
-UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
-}
-UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
- return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
-}
-UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
- return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview val, upb_arena *arena) {
- return _upb_array_append_accessor(msg, UPB_SIZE(28, 56), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val,
- arena);
-}
-
-/* google.protobuf.GeneratedCodeInfo */
-
-UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_new(upb_arena *arena) {
- return (google_protobuf_GeneratedCodeInfo *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_msginit, arena);
-}
-UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize(const google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_has_annotation(const google_protobuf_GeneratedCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo *msg, size_t *len) { return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_mutable_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t *len) {
- return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_resize_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t len, upb_arena *arena) {
- return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_add_annotation(google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena) {
- struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
- bool ok = _upb_array_append_accessor(
- msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
- if (!ok) return NULL;
- return sub;
-}
-
-/* google.protobuf.GeneratedCodeInfo.Annotation */
-
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_new(upb_arena *arena) {
- return (google_protobuf_GeneratedCodeInfo_Annotation *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
-}
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse(const char *buf, size_t size,
- upb_arena *arena) {
- google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena);
- return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize(const google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_arena *arena, size_t *len) {
- return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, len);
-}
-
-UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview); }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-
-UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) {
- return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 32), len);
-}
-UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_resize_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t len, upb_arena *arena) {
- return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 32), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t val, upb_arena *arena) {
- return _upb_array_append_accessor(msg, UPB_SIZE(20, 32), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
- arena);
-}
-UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_strview value) {
- _upb_sethas(msg, 3);
- *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
- _upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
- _upb_sethas(msg, 2);
- *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ */
-/*
-** Defs are upb's internal representation of the constructs that can appear
-** in a .proto file:
-**
-** - upb_msgdef: describes a "message" construct.
-** - upb_fielddef: describes a message field.
-** - upb_filedef: describes a .proto file and its defs.
-** - upb_enumdef: describes an enum.
-** - upb_oneofdef: describes a oneof.
-**
-** TODO: definitions of services.
-*/
-
-#ifndef UPB_DEF_H_
-#define UPB_DEF_H_
-
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-struct upb_enumdef;
-typedef struct upb_enumdef upb_enumdef;
-struct upb_fielddef;
-typedef struct upb_fielddef upb_fielddef;
-struct upb_filedef;
-typedef struct upb_filedef upb_filedef;
-struct upb_msgdef;
-typedef struct upb_msgdef upb_msgdef;
-struct upb_oneofdef;
-typedef struct upb_oneofdef upb_oneofdef;
-struct upb_symtab;
-typedef struct upb_symtab upb_symtab;
-
-typedef enum {
- UPB_SYNTAX_PROTO2 = 2,
- UPB_SYNTAX_PROTO3 = 3
-} upb_syntax_t;
-
-/* All the different kind of well known type messages. For simplicity of check,
- * number wrappers and string wrappers are grouped together. Make sure the
- * order and merber of these groups are not changed.
- */
-typedef enum {
- UPB_WELLKNOWN_UNSPECIFIED,
- UPB_WELLKNOWN_ANY,
- UPB_WELLKNOWN_FIELDMASK,
- UPB_WELLKNOWN_DURATION,
- UPB_WELLKNOWN_TIMESTAMP,
- /* number wrappers */
- UPB_WELLKNOWN_DOUBLEVALUE,
- UPB_WELLKNOWN_FLOATVALUE,
- UPB_WELLKNOWN_INT64VALUE,
- UPB_WELLKNOWN_UINT64VALUE,
- UPB_WELLKNOWN_INT32VALUE,
- UPB_WELLKNOWN_UINT32VALUE,
- /* string wrappers */
- UPB_WELLKNOWN_STRINGVALUE,
- UPB_WELLKNOWN_BYTESVALUE,
- UPB_WELLKNOWN_BOOLVALUE,
- UPB_WELLKNOWN_VALUE,
- UPB_WELLKNOWN_LISTVALUE,
- UPB_WELLKNOWN_STRUCT
-} upb_wellknowntype_t;
-
-/* upb_fielddef ***************************************************************/
-
-/* Maximum field number allowed for FieldDefs. This is an inherent limit of the
- * protobuf wire format. */
-#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
-
-const char *upb_fielddef_fullname(const upb_fielddef *f);
-upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f);
-upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f);
-upb_label_t upb_fielddef_label(const upb_fielddef *f);
-uint32_t upb_fielddef_number(const upb_fielddef *f);
-const char *upb_fielddef_name(const upb_fielddef *f);
-const char *upb_fielddef_jsonname(const upb_fielddef *f);
-bool upb_fielddef_isextension(const upb_fielddef *f);
-bool upb_fielddef_lazy(const upb_fielddef *f);
-bool upb_fielddef_packed(const upb_fielddef *f);
-const upb_filedef *upb_fielddef_file(const upb_fielddef *f);
-const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f);
-const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f);
-const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f);
-uint32_t upb_fielddef_index(const upb_fielddef *f);
-bool upb_fielddef_issubmsg(const upb_fielddef *f);
-bool upb_fielddef_isstring(const upb_fielddef *f);
-bool upb_fielddef_isseq(const upb_fielddef *f);
-bool upb_fielddef_isprimitive(const upb_fielddef *f);
-bool upb_fielddef_ismap(const upb_fielddef *f);
-int64_t upb_fielddef_defaultint64(const upb_fielddef *f);
-int32_t upb_fielddef_defaultint32(const upb_fielddef *f);
-uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f);
-uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f);
-bool upb_fielddef_defaultbool(const upb_fielddef *f);
-float upb_fielddef_defaultfloat(const upb_fielddef *f);
-double upb_fielddef_defaultdouble(const upb_fielddef *f);
-const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len);
-bool upb_fielddef_hassubdef(const upb_fielddef *f);
-bool upb_fielddef_haspresence(const upb_fielddef *f);
-const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f);
-const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f);
-const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f);
-
-/* Internal only. */
-uint32_t upb_fielddef_selectorbase(const upb_fielddef *f);
-
-/* upb_oneofdef ***************************************************************/
-
-typedef upb_inttable_iter upb_oneof_iter;
-
-const char *upb_oneofdef_name(const upb_oneofdef *o);
-const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o);
-int upb_oneofdef_numfields(const upb_oneofdef *o);
-uint32_t upb_oneofdef_index(const upb_oneofdef *o);
-bool upb_oneofdef_issynthetic(const upb_oneofdef *o);
-
-/* Oneof lookups:
- * - ntof: look up a field by name.
- * - ntofz: look up a field by name (as a null-terminated string).
- * - itof: look up a field by number. */
-const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
- const char *name, size_t length);
-UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o,
- const char *name) {
- return upb_oneofdef_ntof(o, name, strlen(name));
-}
-const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num);
-
-/* upb_oneof_iter i;
- * for(upb_oneof_begin(&i, e); !upb_oneof_done(&i); upb_oneof_next(&i)) {
- * // ...
- * }
- */
-void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o);
-void upb_oneof_next(upb_oneof_iter *iter);
-bool upb_oneof_done(upb_oneof_iter *iter);
-upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter);
-void upb_oneof_iter_setdone(upb_oneof_iter *iter);
-bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1,
- const upb_oneof_iter *iter2);
-
-/* upb_msgdef *****************************************************************/
-
-typedef upb_inttable_iter upb_msg_field_iter;
-typedef upb_strtable_iter upb_msg_oneof_iter;
-
-/* Well-known field tag numbers for map-entry messages. */
-#define UPB_MAPENTRY_KEY 1
-#define UPB_MAPENTRY_VALUE 2
-
-/* Well-known field tag numbers for Any messages. */
-#define UPB_ANY_TYPE 1
-#define UPB_ANY_VALUE 2
-
-/* Well-known field tag numbers for timestamp messages. */
-#define UPB_DURATION_SECONDS 1
-#define UPB_DURATION_NANOS 2
-
-/* Well-known field tag numbers for duration messages. */
-#define UPB_TIMESTAMP_SECONDS 1
-#define UPB_TIMESTAMP_NANOS 2
-
-const char *upb_msgdef_fullname(const upb_msgdef *m);
-const upb_filedef *upb_msgdef_file(const upb_msgdef *m);
-const char *upb_msgdef_name(const upb_msgdef *m);
-int upb_msgdef_numfields(const upb_msgdef *m);
-int upb_msgdef_numoneofs(const upb_msgdef *m);
-int upb_msgdef_numrealoneofs(const upb_msgdef *m);
-upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m);
-bool upb_msgdef_mapentry(const upb_msgdef *m);
-upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m);
-bool upb_msgdef_isnumberwrapper(const upb_msgdef *m);
-const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i);
-const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
- size_t len);
-const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
- size_t len);
-const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m);
-const upb_fielddef *_upb_msgdef_field(const upb_msgdef *m, int i);
-
-UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m,
- const char *name) {
- return upb_msgdef_ntoo(m, name, strlen(name));
-}
-
-UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m,
- const char *name) {
- return upb_msgdef_ntof(m, name, strlen(name));
-}
-
-/* Internal-only. */
-size_t upb_msgdef_selectorcount(const upb_msgdef *m);
-uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m);
-
-/* Lookup of either field or oneof by name. Returns whether either was found.
- * If the return is true, then the found def will be set, and the non-found
- * one set to NULL. */
-bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
- const upb_fielddef **f, const upb_oneofdef **o);
-
-UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name,
- const upb_fielddef **f,
- const upb_oneofdef **o) {
- return upb_msgdef_lookupname(m, name, strlen(name), f, o);
-}
-
-/* Returns a field by either JSON name or regular proto name. */
-const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m,
- const char *name, size_t len);
-
-/* Iteration over fields and oneofs. For example:
- *
- * upb_msg_field_iter i;
- * for(upb_msg_field_begin(&i, m);
- * !upb_msg_field_done(&i);
- * upb_msg_field_next(&i)) {
- * upb_fielddef *f = upb_msg_iter_field(&i);
- * // ...
- * }
- *
- * For C we don't have separate iterators for const and non-const.
- * It is the caller's responsibility to cast the upb_fielddef* to
- * const if the upb_msgdef* is const. */
-void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m);
-void upb_msg_field_next(upb_msg_field_iter *iter);
-bool upb_msg_field_done(const upb_msg_field_iter *iter);
-upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter);
-void upb_msg_field_iter_setdone(upb_msg_field_iter *iter);
-bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
- const upb_msg_field_iter * iter2);
-
-/* Similar to above, we also support iterating through the oneofs in a
- * msgdef. */
-void upb_msg_oneof_begin(upb_msg_oneof_iter * iter, const upb_msgdef *m);
-void upb_msg_oneof_next(upb_msg_oneof_iter * iter);
-bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter);
-const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter);
-void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter);
-bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
- const upb_msg_oneof_iter *iter2);
-
-/* upb_enumdef ****************************************************************/
-
-typedef upb_strtable_iter upb_enum_iter;
-
-const char *upb_enumdef_fullname(const upb_enumdef *e);
-const char *upb_enumdef_name(const upb_enumdef *e);
-const upb_filedef *upb_enumdef_file(const upb_enumdef *e);
-int32_t upb_enumdef_default(const upb_enumdef *e);
-int upb_enumdef_numvals(const upb_enumdef *e);
-
-/* Enum lookups:
- * - ntoi: look up a name with specified length.
- * - ntoiz: look up a name provided as a null-terminated string.
- * - iton: look up an integer, returning the name as a null-terminated
- * string. */
-bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len,
- int32_t *num);
-UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e,
- const char *name, int32_t *num) {
- return upb_enumdef_ntoi(e, name, strlen(name), num);
-}
-const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num);
-
-/* upb_enum_iter i;
- * for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) {
- * // ...
- * }
- */
-void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e);
-void upb_enum_next(upb_enum_iter *iter);
-bool upb_enum_done(upb_enum_iter *iter);
-const char *upb_enum_iter_name(upb_enum_iter *iter);
-int32_t upb_enum_iter_number(upb_enum_iter *iter);
-
-/* upb_filedef ****************************************************************/
-
-const char *upb_filedef_name(const upb_filedef *f);
-const char *upb_filedef_package(const upb_filedef *f);
-const char *upb_filedef_phpprefix(const upb_filedef *f);
-const char *upb_filedef_phpnamespace(const upb_filedef *f);
-upb_syntax_t upb_filedef_syntax(const upb_filedef *f);
-int upb_filedef_depcount(const upb_filedef *f);
-int upb_filedef_msgcount(const upb_filedef *f);
-int upb_filedef_enumcount(const upb_filedef *f);
-const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i);
-const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i);
-const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i);
-
-/* upb_symtab *****************************************************************/
-
-upb_symtab *upb_symtab_new(void);
-void upb_symtab_free(upb_symtab* s);
-const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym);
-const upb_msgdef *upb_symtab_lookupmsg2(
- const upb_symtab *s, const char *sym, size_t len);
-const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym);
-const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name);
-const upb_filedef *upb_symtab_lookupfile2(
- const upb_symtab *s, const char *name, size_t len);
-int upb_symtab_filecount(const upb_symtab *s);
-const upb_filedef *upb_symtab_addfile(
- upb_symtab *s, const google_protobuf_FileDescriptorProto *file,
- upb_status *status);
-
-/* For generated code only: loads a generated descriptor. */
-typedef struct upb_def_init {
- struct upb_def_init **deps; /* Dependencies of this file. */
- const upb_msglayout **layouts; /* Pre-order layouts of all messages. */
- const char *filename;
- upb_strview descriptor; /* Serialized descriptor. */
-} upb_def_init;
-
-bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init);
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* __cplusplus */
-
-#endif /* UPB_DEF_H_ */
-
-#ifndef UPB_REFLECTION_H_
-#define UPB_REFLECTION_H_
-
-
-
-typedef union {
- bool bool_val;
- float float_val;
- double double_val;
- int32_t int32_val;
- int64_t int64_val;
- uint32_t uint32_val;
- uint64_t uint64_val;
- const upb_map* map_val;
- const upb_msg* msg_val;
- const upb_array* array_val;
- upb_strview str_val;
-} upb_msgval;
-
-typedef union {
- upb_map* map;
- upb_msg* msg;
- upb_array* array;
-} upb_mutmsgval;
-
-/** upb_msg *******************************************************************/
-
-/* Creates a new message of the given type in the given arena. */
-upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a);
-
-/* Returns the value associated with this field. */
-upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f);
-
-/* Returns a mutable pointer to a map, array, or submessage value. If the given
- * arena is non-NULL this will construct a new object if it was not previously
- * present. May not be called for primitive fields. */
-upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, upb_arena *a);
-
-/* May only be called for fields where upb_fielddef_haspresence(f) == true. */
-bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f);
-
-/* Returns whether any field is set in the oneof. */
-bool upb_msg_hasoneof(const upb_msg *msg, const upb_oneofdef *o);
-
-/* Sets the given field to the given value. For a msg/array/map/string, the
- * value must be in the same arena. */
-void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
- upb_arena *a);
-
-/* Clears any field presence and sets the value back to its default. */
-void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f);
-
-/* Iterate over present fields.
- *
- * size_t iter = UPB_MSG_BEGIN;
- * const upb_fielddef *f;
- * upb_msgval val;
- * while (upb_msg_next(msg, m, ext_pool, &f, &val, &iter)) {
- * process_field(f, val);
- * }
- *
- * If ext_pool is NULL, no extensions will be returned. If the given symtab
- * returns extensions that don't match what is in this message, those extensions
- * will be skipped.
- */
-
-#define UPB_MSG_BEGIN -1
-bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
- const upb_symtab *ext_pool, const upb_fielddef **f,
- upb_msgval *val, size_t *iter);
-
-/* Adds unknown data (serialized protobuf data) to the given message. The data
- * is copied into the message instance. */
-void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
- upb_arena *arena);
-
-/* Returns a reference to the message's unknown data. */
-const char *upb_msg_getunknown(const upb_msg *msg, size_t *len);
-
-/** upb_array *****************************************************************/
-
-/* Creates a new array on the given arena that holds elements of this type. */
-upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type);
-
-/* Returns the size of the array. */
-size_t upb_array_size(const upb_array *arr);
-
-/* Returns the given element, which must be within the array's current size. */
-upb_msgval upb_array_get(const upb_array *arr, size_t i);
-
-/* Sets the given element, which must be within the array's current size. */
-void upb_array_set(upb_array *arr, size_t i, upb_msgval val);
-
-/* Appends an element to the array. Returns false on allocation failure. */
-bool upb_array_append(upb_array *array, upb_msgval val, upb_arena *arena);
-
-/* Changes the size of a vector. New elements are initialized to empty/0.
- * Returns false on allocation failure. */
-bool upb_array_resize(upb_array *array, size_t size, upb_arena *arena);
-
-/** upb_map *******************************************************************/
-
-/* Creates a new map on the given arena with the given key/value size. */
-upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type,
- upb_fieldtype_t value_type);
-
-/* Returns the number of entries in the map. */
-size_t upb_map_size(const upb_map *map);
-
-/* Stores a value for the given key into |*val| (or the zero value if the key is
- * not present). Returns whether the key was present. The |val| pointer may be
- * NULL, in which case the function tests whether the given key is present. */
-bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val);
-
-/* Removes all entries in the map. */
-void upb_map_clear(upb_map *map);
-
-/* Sets the given key to the given value. Returns true if this was a new key in
- * the map, or false if an existing key was replaced. */
-bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
- upb_arena *arena);
-
-/* Deletes this key from the table. Returns true if the key was present. */
-bool upb_map_delete(upb_map *map, upb_msgval key);
-
-/* Map iteration:
- *
- * size_t iter = UPB_MAP_BEGIN;
- * while (upb_mapiter_next(map, &iter)) {
- * upb_msgval key = upb_mapiter_key(map, iter);
- * upb_msgval val = upb_mapiter_value(map, iter);
- *
- * // If mutating is desired.
- * upb_mapiter_setvalue(map, iter, value2);
- * }
- */
-
-/* Advances to the next entry. Returns false if no more entries are present. */
-bool upb_mapiter_next(const upb_map *map, size_t *iter);
-
-/* Returns the key and value for this entry of the map. */
-upb_msgval upb_mapiter_key(const upb_map *map, size_t iter);
-upb_msgval upb_mapiter_value(const upb_map *map, size_t iter);
-
-/* Sets the value for this entry. The iterator must not be done, and the
- * iterator must not have been initialized const. */
-void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value);
-
-
-#endif /* UPB_REFLECTION_H_ */
-/*
-** upb::Handlers (upb_handlers)
-**
-** A upb_handlers is like a virtual table for a upb_msgdef. Each field of the
-** message can have associated functions that will be called when we are
-** parsing or visiting a stream of data. This is similar to how handlers work
-** in SAX (the Simple API for XML).
-**
-** The handlers have no idea where the data is coming from, so a single set of
-** handlers could be used with two completely different data sources (for
-** example, a parser and a visitor over in-memory objects). This decoupling is
-** the most important feature of upb, because it allows parsers and serializers
-** to be highly reusable.
-**
-** This is a mixed C/C++ interface that offers a full API to both languages.
-** See the top-level README for more information.
-*/
-
-#ifndef UPB_HANDLERS_H
-#define UPB_HANDLERS_H
-
-
-
-#ifdef __cplusplus
-namespace upb {
-class HandlersPtr;
-class HandlerCache;
-template class Handler;
-template struct CanonicalType;
-} /* namespace upb */
-#endif
-
-
-/* The maximum depth that the handler graph can have. This is a resource limit
- * for the C stack since we sometimes need to recursively traverse the graph.
- * Cycles are ok; the traversal will stop when it detects a cycle, but we must
- * hit the cycle before the maximum depth is reached.
- *
- * If having a single static limit is too inflexible, we can add another variant
- * of Handlers::Freeze that allows specifying this as a parameter. */
-#define UPB_MAX_HANDLER_DEPTH 64
-
-/* All the different types of handlers that can be registered.
- * Only needed for the advanced functions in upb::Handlers. */
-typedef enum {
- UPB_HANDLER_INT32,
- UPB_HANDLER_INT64,
- UPB_HANDLER_UINT32,
- UPB_HANDLER_UINT64,
- UPB_HANDLER_FLOAT,
- UPB_HANDLER_DOUBLE,
- UPB_HANDLER_BOOL,
- UPB_HANDLER_STARTSTR,
- UPB_HANDLER_STRING,
- UPB_HANDLER_ENDSTR,
- UPB_HANDLER_STARTSUBMSG,
- UPB_HANDLER_ENDSUBMSG,
- UPB_HANDLER_STARTSEQ,
- UPB_HANDLER_ENDSEQ
-} upb_handlertype_t;
-
-#define UPB_HANDLER_MAX (UPB_HANDLER_ENDSEQ+1)
-
-#define UPB_BREAK NULL
-
-/* A convenient definition for when no closure is needed. */
-extern char _upb_noclosure;
-#define UPB_NO_CLOSURE &_upb_noclosure
-
-/* A selector refers to a specific field handler in the Handlers object
- * (for example: the STARTSUBMSG handler for field "field15"). */
-typedef int32_t upb_selector_t;
-
-/* Static selectors for upb::Handlers. */
-#define UPB_STARTMSG_SELECTOR 0
-#define UPB_ENDMSG_SELECTOR 1
-#define UPB_UNKNOWN_SELECTOR 2
-#define UPB_STATIC_SELECTOR_COUNT 3 /* Warning: also in upb/def.c. */
-
-/* Static selectors for upb::BytesHandler. */
-#define UPB_STARTSTR_SELECTOR 0
-#define UPB_STRING_SELECTOR 1
-#define UPB_ENDSTR_SELECTOR 2
-
-#ifdef __cplusplus
-template const void *UniquePtrForType() {
- static const char ch = 0;
- return &ch;
-}
-#endif
-
-/* upb_handlers ************************************************************/
-
-/* Handler attributes, to be registered with the handler itself. */
-typedef struct {
- const void *handler_data;
- const void *closure_type;
- const void *return_closure_type;
- bool alwaysok;
-} upb_handlerattr;
-
-#define UPB_HANDLERATTR_INIT {NULL, NULL, NULL, false}
-
-/* Bufhandle, data passed along with a buffer to indicate its provenance. */
-typedef struct {
- /* The beginning of the buffer. This may be different than the pointer
- * passed to a StringBuf handler because the handler may receive data
- * that is from the middle or end of a larger buffer. */
- const char *buf;
-
- /* The offset within the attached object where this buffer begins. Only
- * meaningful if there is an attached object. */
- size_t objofs;
-
- /* The attached object (if any) and a pointer representing its type. */
- const void *obj;
- const void *objtype;
-
-#ifdef __cplusplus
- template
- void SetAttachedObject(const T* _obj) {
- obj = _obj;
- objtype = UniquePtrForType();
- }
-
- template
- const T *GetAttachedObject() const {
- return objtype == UniquePtrForType() ? static_cast(obj)
- : NULL;
- }
-#endif
-} upb_bufhandle;
-
-#define UPB_BUFHANDLE_INIT {NULL, 0, NULL, NULL}
-
-/* Handler function typedefs. */
-typedef void upb_handlerfree(void *d);
-typedef bool upb_unknown_handlerfunc(void *c, const void *hd, const char *buf,
- size_t n);
-typedef bool upb_startmsg_handlerfunc(void *c, const void*);
-typedef bool upb_endmsg_handlerfunc(void *c, const void *, upb_status *status);
-typedef void* upb_startfield_handlerfunc(void *c, const void *hd);
-typedef bool upb_endfield_handlerfunc(void *c, const void *hd);
-typedef bool upb_int32_handlerfunc(void *c, const void *hd, int32_t val);
-typedef bool upb_int64_handlerfunc(void *c, const void *hd, int64_t val);
-typedef bool upb_uint32_handlerfunc(void *c, const void *hd, uint32_t val);
-typedef bool upb_uint64_handlerfunc(void *c, const void *hd, uint64_t val);
-typedef bool upb_float_handlerfunc(void *c, const void *hd, float val);
-typedef bool upb_double_handlerfunc(void *c, const void *hd, double val);
-typedef bool upb_bool_handlerfunc(void *c, const void *hd, bool val);
-typedef void *upb_startstr_handlerfunc(void *c, const void *hd,
- size_t size_hint);
-typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf,
- size_t n, const upb_bufhandle* handle);
-
-struct upb_handlers;
-typedef struct upb_handlers upb_handlers;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Mutating accessors. */
-const upb_status *upb_handlers_status(upb_handlers *h);
-void upb_handlers_clearerr(upb_handlers *h);
-const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h);
-bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *hfree);
-bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setint32(upb_handlers *h, const upb_fielddef *f,
- upb_int32_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setint64(upb_handlers *h, const upb_fielddef *f,
- upb_int64_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setuint32(upb_handlers *h, const upb_fielddef *f,
- upb_uint32_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setuint64(upb_handlers *h, const upb_fielddef *f,
- upb_uint64_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setfloat(upb_handlers *h, const upb_fielddef *f,
- upb_float_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setdouble(upb_handlers *h, const upb_fielddef *f,
- upb_double_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setbool(upb_handlers *h, const upb_fielddef *f,
- upb_bool_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setstartstr(upb_handlers *h, const upb_fielddef *f,
- upb_startstr_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setstring(upb_handlers *h, const upb_fielddef *f,
- upb_string_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setendstr(upb_handlers *h, const upb_fielddef *f,
- upb_endfield_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setstartseq(upb_handlers *h, const upb_fielddef *f,
- upb_startfield_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setstartsubmsg(upb_handlers *h, const upb_fielddef *f,
- upb_startfield_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setendsubmsg(upb_handlers *h, const upb_fielddef *f,
- upb_endfield_handlerfunc *func,
- const upb_handlerattr *attr);
-bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f,
- upb_endfield_handlerfunc *func,
- const upb_handlerattr *attr);
-
-/* Read-only accessors. */
-const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
- const upb_fielddef *f);
-const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
- upb_selector_t sel);
-upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s,
- const void **handler_data);
-bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t s,
- upb_handlerattr *attr);
-
-/* "Static" methods */
-upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f);
-bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
- upb_selector_t *s);
-UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) {
- return start + 1;
-}
-
-#ifdef __cplusplus
-} /* extern "C" */
-
-namespace upb {
-typedef upb_handlers Handlers;
-}
-
-/* Convenience macros for creating a Handler object that is wrapped with a
- * type-safe wrapper function that converts the "void*" parameters/returns
- * of the underlying C API into nice C++ function.
- *
- * Sample usage:
- * void OnValue1(MyClosure* c, const MyHandlerData* d, int32_t val) {
- * // do stuff ...
- * }
- *
- * // Handler that doesn't need any data bound to it.
- * void OnValue2(MyClosure* c, int32_t val) {
- * // do stuff ...
- * }
- *
- * // Handler that returns bool so it can return failure if necessary.
- * bool OnValue3(MyClosure* c, int32_t val) {
- * // do stuff ...
- * return ok;
- * }
- *
- * // Member function handler.
- * class MyClosure {
- * public:
- * void OnValue(int32_t val) {
- * // do stuff ...
- * }
- * };
- *
- * // Takes ownership of the MyHandlerData.
- * handlers->SetInt32Handler(f1, UpbBind(OnValue1, new MyHandlerData(...)));
- * handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue2));
- * handlers->SetInt32Handler(f1, UpbMakeHandler(OnValue3));
- * handlers->SetInt32Handler(f2, UpbMakeHandler(&MyClosure::OnValue));
- */
-
-/* In C++11, the "template" disambiguator can appear even outside templates,
- * so all calls can safely use this pair of macros. */
-
-#define UpbMakeHandler(f) upb::MatchFunc(f).template GetFunc()
-
-/* We have to be careful to only evaluate "d" once. */
-#define UpbBind(f, d) upb::MatchFunc(f).template GetFunc((d))
-
-/* Handler: a struct that contains the (handler, data, deleter) tuple that is
- * used to register all handlers. Users can Make() these directly but it's
- * more convenient to use the UpbMakeHandler/UpbBind macros above. */
-template class upb::Handler {
- public:
- /* The underlying, handler function signature that upb uses internally. */
- typedef T FuncPtr;
-
- /* Intentionally implicit. */
- template Handler(F func);
- ~Handler() { UPB_ASSERT(registered_); }
-
- void AddCleanup(upb_handlers* h) const;
- FuncPtr handler() const { return handler_; }
- const upb_handlerattr& attr() const { return attr_; }
-
- private:
- Handler(const Handler&) = delete;
- Handler& operator=(const Handler&) = delete;
-
- FuncPtr handler_;
- mutable upb_handlerattr attr_;
- mutable bool registered_;
- void *cleanup_data_;
- upb_handlerfree *cleanup_func_;
-};
-
-/* A upb::Handlers object represents the set of handlers associated with a
- * message in the graph of messages. You can think of it as a big virtual
- * table with functions corresponding to all the events that can fire while
- * parsing or visiting a message of a specific type.
- *
- * Any handlers that are not set behave as if they had successfully consumed
- * the value. Any unset Start* handlers will propagate their closure to the
- * inner frame.
- *
- * The easiest way to create the *Handler objects needed by the Set* methods is
- * with the UpbBind() and UpbMakeHandler() macros; see below. */
-class upb::HandlersPtr {
- public:
- HandlersPtr(upb_handlers* ptr) : ptr_(ptr) {}
-
- upb_handlers* ptr() const { return ptr_; }
-
- typedef upb_selector_t Selector;
- typedef upb_handlertype_t Type;
-
- typedef Handler StartFieldHandler;
- typedef Handler EndFieldHandler;
- typedef Handler StartMessageHandler;
- typedef Handler
- EndMessageHandler;
- typedef Handler StartStringHandler;
- typedef Handler
- StringHandler;
-
- template struct ValueHandler {
- typedef Handler H;
- };
-
- typedef ValueHandler::H Int32Handler;
- typedef ValueHandler::H Int64Handler;
- typedef ValueHandler::H UInt32Handler;
- typedef ValueHandler::H UInt64Handler;
- typedef ValueHandler::H FloatHandler;
- typedef ValueHandler::H DoubleHandler;
- typedef ValueHandler::H BoolHandler;
-
- /* Any function pointer can be converted to this and converted back to its
- * correct type. */
- typedef void GenericFunction();
-
- typedef void HandlersCallback(const void *closure, upb_handlers *h);
-
- /* Returns the msgdef associated with this handlers object. */
- MessageDefPtr message_def() const {
- return MessageDefPtr(upb_handlers_msgdef(ptr()));
- }
-
- /* Adds the given pointer and function to the list of cleanup functions that
- * will be run when these handlers are freed. If this pointer has previously
- * been registered, the function returns false and does nothing. */
- bool AddCleanup(void *ptr, upb_handlerfree *cleanup) {
- return upb_handlers_addcleanup(ptr_, ptr, cleanup);
- }
-
- /* Sets the startmsg handler for the message, which is defined as follows:
- *
- * bool startmsg(MyType* closure) {
- * // Called when the message begins. Returns true if processing should
- * // continue.
- * return true;
- * }
- */
- bool SetStartMessageHandler(const StartMessageHandler &h) {
- h.AddCleanup(ptr());
- return upb_handlers_setstartmsg(ptr(), h.handler(), &h.attr());
- }
-
- /* Sets the endmsg handler for the message, which is defined as follows:
- *
- * bool endmsg(MyType* closure, upb_status *status) {
- * // Called when processing of this message ends, whether in success or
- * // failure. "status" indicates the final status of processing, and
- * // can also be modified in-place to update the final status.
- * }
- */
- bool SetEndMessageHandler(const EndMessageHandler& h) {
- h.AddCleanup(ptr());
- return upb_handlers_setendmsg(ptr(), h.handler(), &h.attr());
- }
-
- /* Sets the value handler for the given field, which is defined as follows
- * (this is for an int32 field; other field types will pass their native
- * C/C++ type for "val"):
- *
- * bool OnValue(MyClosure* c, const MyHandlerData* d, int32_t val) {
- * // Called when the field's value is encountered. "d" contains
- * // whatever data was bound to this field when it was registered.
- * // Returns true if processing should continue.
- * return true;
- * }
- *
- * handers->SetInt32Handler(f, UpbBind(OnValue, new MyHandlerData(...)));
- *
- * The value type must exactly match f->type().
- * For example, a handler that takes an int32_t parameter may only be used for
- * fields of type UPB_TYPE_INT32 and UPB_TYPE_ENUM.
- *
- * Returns false if the handler failed to register; in this case the cleanup
- * handler (if any) will be called immediately.
- */
- bool SetInt32Handler(FieldDefPtr f, const Int32Handler &h) {
- h.AddCleanup(ptr());
- return upb_handlers_setint32(ptr(), f.ptr(), h.handler(), &h.attr());
- }
-
- bool SetInt64Handler (FieldDefPtr f, const Int64Handler& h) {
- h.AddCleanup(ptr());
- return upb_handlers_setint64(ptr(), f.ptr(), h.handler(), &h.attr());
- }
-
- bool SetUInt32Handler(FieldDefPtr f, const UInt32Handler& h) {
- h.AddCleanup(ptr());
- return upb_handlers_setuint32(ptr(), f.ptr(), h.handler(), &h.attr());
- }
-
- bool SetUInt64Handler(FieldDefPtr f, const UInt64Handler& h) {
- h.AddCleanup(ptr());
- return upb_handlers_setuint64(ptr(), f.ptr(), h.handler(), &h.attr());
- }
-
- bool SetFloatHandler (FieldDefPtr f, const FloatHandler& h) {
- h.AddCleanup(ptr());
- return upb_handlers_setfloat(ptr(), f.ptr(), h.handler(), &h.attr());
- }
-
- bool SetDoubleHandler(FieldDefPtr f, const DoubleHandler& h) {
- h.AddCleanup(ptr());
- return upb_handlers_setdouble(ptr(), f.ptr(), h.handler(), &h.attr());
- }
-
- bool SetBoolHandler(FieldDefPtr f, const BoolHandler &h) {
- h.AddCleanup(ptr());
- return upb_handlers_setbool(ptr(), f.ptr(), h.handler(), &h.attr());
- }
-
- /* Like the previous, but templated on the type on the value (ie. int32).
- * This is mostly useful to call from other templates. To call this you must
- * specify the template parameter explicitly, ie:
- * h->SetValueHandler(f, UpbBind(MyHandler, MyData)); */
- template
- bool SetValueHandler(
- FieldDefPtr f,
- const typename ValueHandler::Type>::H &handler);
-
- /* Sets handlers for a string field, which are defined as follows:
- *
- * MySubClosure* startstr(MyClosure* c, const MyHandlerData* d,
- * size_t size_hint) {
- * // Called when a string value begins. The return value indicates the
- * // closure for the string. "size_hint" indicates the size of the
- * // string if it is known, however if the string is length-delimited
- * // and the end-of-string is not available size_hint will be zero.
- * // This case is indistinguishable from the case where the size is
- * // known to be zero.
- * //
- * // TODO(haberman): is it important to distinguish these cases?
- * // If we had ssize_t as a type we could make -1 "unknown", but
- * // ssize_t is POSIX (not ANSI) and therefore less portable.
- * // In practice I suspect it won't be important to distinguish.
- * return closure;
- * }
- *
- * size_t str(MyClosure* closure, const MyHandlerData* d,
- * const char *str, size_t len) {
- * // Called for each buffer of string data; the multiple physical buffers
- * // are all part of the same logical string. The return value indicates
- * // how many bytes were consumed. If this number is less than "len",
- * // this will also indicate that processing should be halted for now,
- * // like returning false or UPB_BREAK from any other callback. If
- * // number is greater than "len", the excess bytes will be skipped over
- * // and not passed to the callback.
- * return len;
- * }
- *
- * bool endstr(MyClosure* c, const MyHandlerData* d) {
- * // Called when a string value ends. Return value indicates whether
- * // processing should continue.
- * return true;
- * }
- */
- bool SetStartStringHandler(FieldDefPtr f, const StartStringHandler &h) {
- h.AddCleanup(ptr());
- return upb_handlers_setstartstr(ptr(), f.ptr(), h.handler(), &h.attr());
- }
-
- bool SetStringHandler(FieldDefPtr f, const StringHandler& h) {
- h.AddCleanup(ptr());
- return upb_handlers_setstring(ptr(), f.ptr(), h.handler(), &h.attr());
- }
-
- bool SetEndStringHandler(FieldDefPtr f, const EndFieldHandler& h) {
- h.AddCleanup(ptr());
- return upb_handlers_setendstr(ptr(), f.ptr(), h.handler(), &h.attr());
- }
-
- /* Sets the startseq handler, which is defined as follows:
- *
- * MySubClosure *startseq(MyClosure* c, const MyHandlerData* d) {
- * // Called when a sequence (repeated field) begins. The returned
- * // pointer indicates the closure for the sequence (or UPB_BREAK
- * // to interrupt processing).
- * return closure;
- * }
- *
- * h->SetStartSequenceHandler(f, UpbBind(startseq, new MyHandlerData(...)));
- *
- * Returns "false" if "f" does not belong to this message or is not a
- * repeated field.
- */
- bool SetStartSequenceHandler(FieldDefPtr f, const StartFieldHandler &h) {
- h.AddCleanup(ptr());
- return upb_handlers_setstartseq(ptr(), f.ptr(), h.handler(), &h.attr());
- }
-
- /* Sets the startsubmsg handler for the given field, which is defined as
- * follows:
- *
- * MySubClosure* startsubmsg(MyClosure* c, const MyHandlerData* d) {
- * // Called when a submessage begins. The returned pointer indicates the
- * // closure for the sequence (or UPB_BREAK to interrupt processing).
- * return closure;
- * }
- *
- * h->SetStartSubMessageHandler(f, UpbBind(startsubmsg,
- * new MyHandlerData(...)));
- *
- * Returns "false" if "f" does not belong to this message or is not a
- * submessage/group field.
- */
- bool SetStartSubMessageHandler(FieldDefPtr f, const StartFieldHandler& h) {
- h.AddCleanup(ptr());
- return upb_handlers_setstartsubmsg(ptr(), f.ptr(), h.handler(), &h.attr());
- }
-
- /* Sets the endsubmsg handler for the given field, which is defined as
- * follows:
- *
- * bool endsubmsg(MyClosure* c, const MyHandlerData* d) {
- * // Called when a submessage ends. Returns true to continue processing.
- * return true;
- * }
- *
- * Returns "false" if "f" does not belong to this message or is not a
- * submessage/group field.
- */
- bool SetEndSubMessageHandler(FieldDefPtr f, const EndFieldHandler &h) {
- h.AddCleanup(ptr());
- return upb_handlers_setendsubmsg(ptr(), f.ptr(), h.handler(), &h.attr());
- }
-
- /* Starts the endsubseq handler for the given field, which is defined as
- * follows:
- *
- * bool endseq(MyClosure* c, const MyHandlerData* d) {
- * // Called when a sequence ends. Returns true continue processing.
- * return true;
- * }
- *
- * Returns "false" if "f" does not belong to this message or is not a
- * repeated field.
- */
- bool SetEndSequenceHandler(FieldDefPtr f, const EndFieldHandler &h) {
- h.AddCleanup(ptr());
- return upb_handlers_setendseq(ptr(), f.ptr(), h.handler(), &h.attr());
- }
-
- private:
- upb_handlers* ptr_;
-};
-
-#endif /* __cplusplus */
-
-/* upb_handlercache ***********************************************************/
-
-/* A upb_handlercache lazily builds and caches upb_handlers. You pass it a
- * function (with optional closure) that can build handlers for a given
- * message on-demand, and the cache maintains a map of msgdef->handlers. */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct upb_handlercache;
-typedef struct upb_handlercache upb_handlercache;
-
-typedef void upb_handlers_callback(const void *closure, upb_handlers *h);
-
-upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback,
- const void *closure);
-void upb_handlercache_free(upb_handlercache *cache);
-const upb_handlers *upb_handlercache_get(upb_handlercache *cache,
- const upb_msgdef *md);
-bool upb_handlercache_addcleanup(upb_handlercache *h, void *p,
- upb_handlerfree *hfree);
-
-#ifdef __cplusplus
-} /* extern "C" */
-
-class upb::HandlerCache {
- public:
- HandlerCache(upb_handlers_callback *callback, const void *closure)
- : ptr_(upb_handlercache_new(callback, closure), upb_handlercache_free) {}
- HandlerCache(HandlerCache&&) = default;
- HandlerCache& operator=(HandlerCache&&) = default;
- HandlerCache(upb_handlercache* c) : ptr_(c, upb_handlercache_free) {}
-
- upb_handlercache* ptr() { return ptr_.get(); }
-
- const upb_handlers *Get(MessageDefPtr md) {
- return upb_handlercache_get(ptr_.get(), md.ptr());
- }
-
- private:
- std::unique_ptr ptr_;
-};
-
-#endif /* __cplusplus */
-
-/* upb_byteshandler ***********************************************************/
-
-typedef struct {
- upb_func *func;
-
- /* It is wasteful to include the entire attributes here:
- *
- * * Some of the information is redundant (like storing the closure type
- * separately for each handler that must match).
- * * Some of the info is only needed prior to freeze() (like closure types).
- * * alignment padding wastes a lot of space for alwaysok_.
- *
- * If/when the size and locality of handlers is an issue, we can optimize this
- * not to store the entire attr like this. We do not expose the table's
- * layout to allow this optimization in the future. */
- upb_handlerattr attr;
-} upb_handlers_tabent;
-
-#define UPB_TABENT_INIT {NULL, UPB_HANDLERATTR_INIT}
-
-typedef struct {
- upb_handlers_tabent table[3];
-} upb_byteshandler;
-
-#define UPB_BYTESHANDLER_INIT \
- { \
- { UPB_TABENT_INIT, UPB_TABENT_INIT, UPB_TABENT_INIT } \
- }
-
-UPB_INLINE void upb_byteshandler_init(upb_byteshandler *handler) {
- upb_byteshandler init = UPB_BYTESHANDLER_INIT;
- *handler = init;
-}
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Caller must ensure that "d" outlives the handlers. */
-bool upb_byteshandler_setstartstr(upb_byteshandler *h,
- upb_startstr_handlerfunc *func, void *d);
-bool upb_byteshandler_setstring(upb_byteshandler *h,
- upb_string_handlerfunc *func, void *d);
-bool upb_byteshandler_setendstr(upb_byteshandler *h,
- upb_endfield_handlerfunc *func, void *d);
-
-#ifdef __cplusplus
-} /* extern "C" */
-
-namespace upb {
-typedef upb_byteshandler BytesHandler;
-}
-#endif
-
-/** Message handlers ******************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* These are the handlers used internally by upb_msgfactory_getmergehandlers().
- * They write scalar data to a known offset from the message pointer.
- *
- * These would be trivial for anyone to implement themselves, but it's better
- * to use these because some JITs will recognize and specialize these instead
- * of actually calling the function. */
-
-/* Sets a handler for the given primitive field that will write the data at the
- * given offset. If hasbit > 0, also sets a hasbit at the given bit offset
- * (addressing each byte low to high). */
-bool upb_msg_setscalarhandler(upb_handlers *h,
- const upb_fielddef *f,
- size_t offset,
- int32_t hasbit);
-
-/* If the given handler is a msghandlers_primitive field, returns true and sets
- * *type, *offset and *hasbit. Otherwise returns false. */
-bool upb_msg_getscalarhandlerdata(const upb_handlers *h,
- upb_selector_t s,
- upb_fieldtype_t *type,
- size_t *offset,
- int32_t *hasbit);
-
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-/*
-** Inline definitions for handlers.h, which are particularly long and a bit
-** tricky.
-*/
-
-#ifndef UPB_HANDLERS_INL_H_
-#define UPB_HANDLERS_INL_H_
-
-#include
-#include
-
-
-#ifdef __cplusplus
-
-/* Type detection and typedefs for integer types.
- * For platforms where there are multiple 32-bit or 64-bit types, we need to be
- * able to enumerate them so we can properly create overloads for all variants.
- *
- * If any platform existed where there were three integer types with the same
- * size, this would have to become more complicated. For example, short, int,
- * and long could all be 32-bits. Even more diabolically, short, int, long,
- * and long long could all be 64 bits and still be standard-compliant.
- * However, few platforms are this strange, and it's unlikely that upb will be
- * used on the strangest ones. */
-
-/* Can't count on stdint.h limits like INT32_MAX, because in C++ these are
- * only defined when __STDC_LIMIT_MACROS are defined before the *first* include
- * of stdint.h. We can't guarantee that someone else didn't include these first
- * without defining __STDC_LIMIT_MACROS. */
-#define UPB_INT32_MAX 0x7fffffffLL
-#define UPB_INT32_MIN (-UPB_INT32_MAX - 1)
-#define UPB_INT64_MAX 0x7fffffffffffffffLL
-#define UPB_INT64_MIN (-UPB_INT64_MAX - 1)
-
-#if INT_MAX == UPB_INT32_MAX && INT_MIN == UPB_INT32_MIN
-#define UPB_INT_IS_32BITS 1
-#endif
-
-#if LONG_MAX == UPB_INT32_MAX && LONG_MIN == UPB_INT32_MIN
-#define UPB_LONG_IS_32BITS 1
-#endif
-
-#if LONG_MAX == UPB_INT64_MAX && LONG_MIN == UPB_INT64_MIN
-#define UPB_LONG_IS_64BITS 1
-#endif
-
-#if LLONG_MAX == UPB_INT64_MAX && LLONG_MIN == UPB_INT64_MIN
-#define UPB_LLONG_IS_64BITS 1
-#endif
-
-/* We use macros instead of typedefs so we can undefine them later and avoid
- * leaking them outside this header file. */
-#if UPB_INT_IS_32BITS
-#define UPB_INT32_T int
-#define UPB_UINT32_T unsigned int
-
-#if UPB_LONG_IS_32BITS
-#define UPB_TWO_32BIT_TYPES 1
-#define UPB_INT32ALT_T long
-#define UPB_UINT32ALT_T unsigned long
-#endif /* UPB_LONG_IS_32BITS */
-
-#elif UPB_LONG_IS_32BITS /* && !UPB_INT_IS_32BITS */
-#define UPB_INT32_T long
-#define UPB_UINT32_T unsigned long
-#endif /* UPB_INT_IS_32BITS */
-
-
-#if UPB_LONG_IS_64BITS
-#define UPB_INT64_T long
-#define UPB_UINT64_T unsigned long
-
-#if UPB_LLONG_IS_64BITS
-#define UPB_TWO_64BIT_TYPES 1
-#define UPB_INT64ALT_T long long
-#define UPB_UINT64ALT_T unsigned long long
-#endif /* UPB_LLONG_IS_64BITS */
-
-#elif UPB_LLONG_IS_64BITS /* && !UPB_LONG_IS_64BITS */
-#define UPB_INT64_T long long
-#define UPB_UINT64_T unsigned long long
-#endif /* UPB_LONG_IS_64BITS */
-
-#undef UPB_INT32_MAX
-#undef UPB_INT32_MIN
-#undef UPB_INT64_MAX
-#undef UPB_INT64_MIN
-#undef UPB_INT_IS_32BITS
-#undef UPB_LONG_IS_32BITS
-#undef UPB_LONG_IS_64BITS
-#undef UPB_LLONG_IS_64BITS
-
-
-namespace upb {
-
-typedef void CleanupFunc(void *ptr);
-
-/* Template to remove "const" from "const T*" and just return "T*".
- *
- * We define a nonsense default because otherwise it will fail to instantiate as
- * a function parameter type even in cases where we don't expect any caller to
- * actually match the overload. */
-class CouldntRemoveConst {};
-template struct remove_constptr { typedef CouldntRemoveConst type; };
-template struct remove_constptr { typedef T *type; };
-
-/* Template that we use below to remove a template specialization from
- * consideration if it matches a specific type. */
-template struct disable_if_same { typedef void Type; };
-template struct disable_if_same {};
-
-template void DeletePointer(void *p) { delete static_cast(p); }
-
-template
-struct FirstUnlessVoidOrBool {
- typedef T1 value;
-};
-
-template
-struct FirstUnlessVoidOrBool {
- typedef T2 value;
-};
-
-template
-struct FirstUnlessVoidOrBool {
- typedef T2 value;
-};
-
-template
-struct is_same {
- static bool value;
-};
-
-template
-struct is_same {
- static bool value;
-};
-
-template
-bool is_same::value = false;
-
-template
-bool is_same::value = true;
-
-/* FuncInfo *******************************************************************/
-
-/* Info about the user's original, pre-wrapped function. */
-template
-struct FuncInfo {
- /* The type of the closure that the function takes (its first param). */
- typedef C Closure;
-
- /* The return type. */
- typedef R Return;
-};
-
-/* Func ***********************************************************************/
-
-/* Func1, Func2, Func3: Template classes representing a function and its
- * signature.
- *
- * Since the function is a template parameter, calling the function can be
- * inlined at compile-time and does not require a function pointer at runtime.
- * These functions are not bound to a handler data so have no data or cleanup
- * handler. */
-struct UnboundFunc {
- CleanupFunc *GetCleanup() { return nullptr; }
- void *GetData() { return nullptr; }
-};
-
-template
-struct Func1 : public UnboundFunc {
- typedef R Return;
- typedef I FuncInfo;
- static R Call(P1 p1) { return F(p1); }
-};
-
-template
-struct Func2 : public UnboundFunc {
- typedef R Return;
- typedef I FuncInfo;
- static R Call(P1 p1, P2 p2) { return F(p1, p2); }
-};
-
-template
-struct Func3 : public UnboundFunc {
- typedef R Return;
- typedef I FuncInfo;
- static R Call(P1 p1, P2 p2, P3 p3) { return F(p1, p2, p3); }
-};
-
-template
-struct Func4 : public UnboundFunc {
- typedef R Return;
- typedef I FuncInfo;
- static R Call(P1 p1, P2 p2, P3 p3, P4 p4) { return F(p1, p2, p3, p4); }
-};
-
-template
-struct Func5 : public UnboundFunc {
- typedef R Return;
- typedef I FuncInfo;
- static R Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
- return F(p1, p2, p3, p4, p5);
- }
-};
-
-/* BoundFunc ******************************************************************/
-
-/* BoundFunc2, BoundFunc3: Like Func2/Func3 except also contains a value that
- * shall be bound to the function's second parameter.
- *
- * Note that the second parameter is a const pointer, but our stored bound value
- * is non-const so we can free it when the handlers are destroyed. */
-template
-struct BoundFunc {
- typedef typename remove_constptr::type MutableP2;
- explicit BoundFunc(MutableP2 data_) : data(data_) {}
- CleanupFunc *GetCleanup() { return &DeletePointer; }
- MutableP2 GetData() { return data; }
- MutableP2 data;
-};
-
-template
-struct BoundFunc2 : public BoundFunc {
- typedef BoundFunc Base;
- typedef I FuncInfo;
- explicit BoundFunc2(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-template
-struct BoundFunc3 : public BoundFunc {
- typedef BoundFunc Base;
- typedef I FuncInfo;
- explicit BoundFunc3(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-template
-struct BoundFunc4 : public BoundFunc {
- typedef BoundFunc Base;
- typedef I FuncInfo;
- explicit BoundFunc4(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-template
-struct BoundFunc5 : public BoundFunc {
- typedef BoundFunc Base;
- typedef I FuncInfo;
- explicit BoundFunc5(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-/* FuncSig ********************************************************************/
-
-/* FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function
- * *signature*, but without a specific function attached.
- *
- * These classes contain member functions that can be invoked with a
- * specific function to return a Func/BoundFunc class. */
-template
-struct FuncSig1 {
- template
- Func1 > GetFunc() {
- return Func1 >();
- }
-};
-
-template
-struct FuncSig2 {
- template
- Func2 > GetFunc() {
- return Func2 >();
- }
-
- template
- BoundFunc2 > GetFunc(
- typename remove_constptr::type param2) {
- return BoundFunc2 >(param2);
- }
-};
-
-template
-struct FuncSig3 {
- template
- Func3 > GetFunc() {
- return Func3 >();
- }
-
- template
- BoundFunc3 > GetFunc(
- typename remove_constptr::type param2) {
- return BoundFunc3 >(param2);
- }
-};
-
-template
-struct FuncSig4 {
- template
- Func4 > GetFunc() {
- return Func4 >();
- }
-
- template
- BoundFunc4 > GetFunc(
- typename remove_constptr::type param2) {
- return BoundFunc4