From 80b1d62bfcea65c59e2160da71dad84b1bd19cef Mon Sep 17 00:00:00 2001 From: "kenton@google.com" Date: Wed, 29 Jul 2009 01:13:20 +0000 Subject: Submit recent changes from internal branch, including "lite mode" for C++ and Java. See CHANGES.txt for more details. --- CHANGES.txt | 26 +- Makefile.am | 7 + generate_descriptor_proto.sh | 6 +- java/pom.xml | 3 + .../java/com/google/protobuf/AbstractMessage.java | 681 +++++--- .../com/google/protobuf/AbstractMessageLite.java | 321 ++++ .../main/java/com/google/protobuf/ByteString.java | 76 +- .../java/com/google/protobuf/CodedInputStream.java | 224 ++- .../com/google/protobuf/CodedOutputStream.java | 424 ++--- .../main/java/com/google/protobuf/Descriptors.java | 558 ++++--- .../java/com/google/protobuf/DynamicMessage.java | 81 +- .../com/google/protobuf/ExtensionRegistry.java | 80 +- .../com/google/protobuf/ExtensionRegistryLite.java | 169 ++ .../main/java/com/google/protobuf/FieldSet.java | 910 +++++----- .../java/com/google/protobuf/GeneratedMessage.java | 532 +++--- .../com/google/protobuf/GeneratedMessageLite.java | 539 ++++++ .../main/java/com/google/protobuf/Internal.java | 194 +++ .../protobuf/InvalidProtocolBufferException.java | 4 +- .../src/main/java/com/google/protobuf/Message.java | 247 +-- .../main/java/com/google/protobuf/MessageLite.java | 331 ++++ .../com/google/protobuf/ProtocolMessageEnum.java | 2 +- .../src/main/java/com/google/protobuf/RpcUtil.java | 13 +- .../java/com/google/protobuf/ServiceException.java | 6 +- .../main/java/com/google/protobuf/TextFormat.java | 296 ++-- .../protobuf/UninitializedMessageException.java | 85 +- .../java/com/google/protobuf/UnknownFieldSet.java | 389 +++-- .../main/java/com/google/protobuf/WireFormat.java | 94 +- .../java/com/google/protobuf/DescriptorsTest.java | 30 + .../com/google/protobuf/DynamicMessageTest.java | 12 + .../com/google/protobuf/GeneratedMessageTest.java | 89 + .../test/java/com/google/protobuf/LiteTest.java | 114 ++ .../test/java/com/google/protobuf/TestUtil.java | 1031 +++++++++++- .../java/com/google/protobuf/TextFormatTest.java | 25 +- .../java/com/google/protobuf/WireFormatTest.java | 65 + python/google/protobuf/internal/containers.py | 8 +- python/google/protobuf/internal/decoder.py | 4 +- python/google/protobuf/internal/decoder_test.py | 18 +- python/google/protobuf/internal/encoder.py | 6 +- python/google/protobuf/internal/encoder_test.py | 12 +- python/google/protobuf/internal/message_test.py | 53 + python/google/protobuf/internal/reflection_test.py | 88 +- python/google/protobuf/internal/test_util.py | 198 ++- .../google/protobuf/internal/text_format_test.py | 281 +++- python/google/protobuf/internal/type_checkers.py | 6 +- python/google/protobuf/internal/wire_format.py | 2 + python/google/protobuf/message.py | 3 +- python/google/protobuf/reflection.py | 66 +- python/google/protobuf/service.py | 5 +- python/google/protobuf/text_format.py | 527 +++++- src/Makefile.am | 37 +- src/google/protobuf/compiler/code_generator.cc | 22 + src/google/protobuf/compiler/code_generator.h | 11 + src/google/protobuf/compiler/cpp/cpp_enum.cc | 79 +- src/google/protobuf/compiler/cpp/cpp_enum.h | 4 + src/google/protobuf/compiler/cpp/cpp_enum_field.cc | 107 +- src/google/protobuf/compiler/cpp/cpp_extension.cc | 1 + src/google/protobuf/compiler/cpp/cpp_field.cc | 19 + src/google/protobuf/compiler/cpp/cpp_field.h | 10 + src/google/protobuf/compiler/cpp/cpp_file.cc | 315 ++-- src/google/protobuf/compiler/cpp/cpp_generator.cc | 29 +- src/google/protobuf/compiler/cpp/cpp_helpers.cc | 13 +- src/google/protobuf/compiler/cpp/cpp_helpers.h | 29 + src/google/protobuf/compiler/cpp/cpp_message.cc | 523 +++--- src/google/protobuf/compiler/cpp/cpp_message.h | 9 +- .../protobuf/compiler/cpp/cpp_message_field.cc | 67 +- .../protobuf/compiler/cpp/cpp_primitive_field.cc | 111 +- src/google/protobuf/compiler/cpp/cpp_service.cc | 2 +- .../protobuf/compiler/cpp/cpp_string_field.cc | 129 +- src/google/protobuf/compiler/cpp/cpp_unittest.cc | 64 +- src/google/protobuf/compiler/java/java_enum.cc | 148 +- .../protobuf/compiler/java/java_enum_field.cc | 43 +- .../protobuf/compiler/java/java_extension.cc | 99 +- src/google/protobuf/compiler/java/java_file.cc | 43 +- src/google/protobuf/compiler/java/java_file.h | 2 + .../protobuf/compiler/java/java_generator.cc | 28 +- src/google/protobuf/compiler/java/java_helpers.cc | 67 + src/google/protobuf/compiler/java/java_helpers.h | 30 + src/google/protobuf/compiler/java/java_message.cc | 478 ++++-- .../protobuf/compiler/java/java_primitive_field.cc | 103 +- src/google/protobuf/compiler/parser.cc | 2 +- src/google/protobuf/descriptor.cc | 80 +- src/google/protobuf/descriptor.pb.cc | 1739 ++++++++++++-------- src/google/protobuf/descriptor.pb.h | 197 ++- src/google/protobuf/descriptor.proto | 11 +- src/google/protobuf/descriptor_unittest.cc | 145 ++ src/google/protobuf/dynamic_message.cc | 84 +- src/google/protobuf/extension_set.cc | 730 ++++---- src/google/protobuf/extension_set.h | 144 +- src/google/protobuf/extension_set_heavy.cc | 218 +++ .../protobuf/generated_message_reflection.cc | 301 +++- src/google/protobuf/generated_message_reflection.h | 22 +- src/google/protobuf/generated_message_util.cc | 44 + src/google/protobuf/generated_message_util.h | 65 + src/google/protobuf/io/coded_stream.cc | 96 +- src/google/protobuf/io/coded_stream.h | 46 + src/google/protobuf/io/gzip_stream.cc | 7 +- src/google/protobuf/io/gzip_stream.h | 6 +- src/google/protobuf/io/tokenizer.cc | 2 +- src/google/protobuf/io/tokenizer_unittest.cc | 1 + src/google/protobuf/io/zero_copy_stream_impl.cc | 345 ---- src/google/protobuf/io/zero_copy_stream_impl.h | 280 +--- .../protobuf/io/zero_copy_stream_impl_lite.cc | 393 +++++ .../protobuf/io/zero_copy_stream_impl_lite.h | 338 ++++ .../protobuf/io/zero_copy_stream_unittest.cc | 1 + src/google/protobuf/lite_unittest.cc | 112 ++ src/google/protobuf/message.cc | 188 +-- src/google/protobuf/message.h | 205 +-- src/google/protobuf/message_lite.cc | 282 ++++ src/google/protobuf/message_lite.h | 237 +++ src/google/protobuf/message_unittest.cc | 30 - src/google/protobuf/repeated_field.cc | 49 +- src/google/protobuf/repeated_field.h | 687 ++++---- src/google/protobuf/stubs/common.h | 32 +- src/google/protobuf/test_util.cc | 12 +- src/google/protobuf/test_util.h | 3 +- src/google/protobuf/test_util_lite.cc | 1502 +++++++++++++++++ src/google/protobuf/test_util_lite.h | 101 ++ src/google/protobuf/text_format.cc | 64 +- src/google/protobuf/text_format.h | 12 + src/google/protobuf/text_format_unittest.cc | 120 +- src/google/protobuf/unittest_custom_options.proto | 2 + src/google/protobuf/unittest_import_lite.proto | 49 + src/google/protobuf/unittest_lite.proto | 312 ++++ .../protobuf/unittest_lite_imports_nonlite.proto | 43 + src/google/protobuf/wire_format.cc | 306 ++-- src/google/protobuf/wire_format.h | 436 +---- src/google/protobuf/wire_format_inl.h | 687 -------- src/google/protobuf/wire_format_lite.cc | 193 +++ src/google/protobuf/wire_format_lite.h | 558 +++++++ src/google/protobuf/wire_format_lite_inl.h | 657 ++++++++ src/google/protobuf/wire_format_unittest.cc | 63 +- 131 files changed, 16616 insertions(+), 7186 deletions(-) create mode 100644 java/src/main/java/com/google/protobuf/AbstractMessageLite.java create mode 100644 java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java create mode 100644 java/src/main/java/com/google/protobuf/GeneratedMessageLite.java create mode 100644 java/src/main/java/com/google/protobuf/Internal.java create mode 100644 java/src/main/java/com/google/protobuf/MessageLite.java create mode 100644 java/src/test/java/com/google/protobuf/LiteTest.java create mode 100755 python/google/protobuf/internal/message_test.py create mode 100644 src/google/protobuf/extension_set_heavy.cc create mode 100644 src/google/protobuf/generated_message_util.cc create mode 100644 src/google/protobuf/generated_message_util.h create mode 100644 src/google/protobuf/io/zero_copy_stream_impl_lite.cc create mode 100644 src/google/protobuf/io/zero_copy_stream_impl_lite.h create mode 100644 src/google/protobuf/lite_unittest.cc create mode 100644 src/google/protobuf/message_lite.cc create mode 100644 src/google/protobuf/message_lite.h create mode 100644 src/google/protobuf/test_util_lite.cc create mode 100644 src/google/protobuf/test_util_lite.h create mode 100644 src/google/protobuf/unittest_import_lite.proto create mode 100644 src/google/protobuf/unittest_lite.proto create mode 100644 src/google/protobuf/unittest_lite_imports_nonlite.proto delete mode 100644 src/google/protobuf/wire_format_inl.h create mode 100644 src/google/protobuf/wire_format_lite.cc create mode 100644 src/google/protobuf/wire_format_lite.h create mode 100644 src/google/protobuf/wire_format_lite_inl.h diff --git a/CHANGES.txt b/CHANGES.txt index 4f870c31..c7e5bc9b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,9 @@ -????-??-?? version 2.1.1: +????-??-?? version 2.2.0: C++ + * Lite mode: The "optimize_for = LITE_RUNTIME" option causes the compiler + to generate code which only depends libprotobuf-lite, which is much smaller + than libprotobuf but lacks descriptors, reflection, and some other features. * Fixed bug where Message.Swap(Message) was only implemented for optimize_for_speed. Swap now properly implemented in both modes (Issue 91). @@ -10,6 +13,27 @@ * Floating-point literals in generated code that are intended to be single-precision now explicitly have 'f' suffix to avoid pedantic warnings produced by some compilers. + * The [deprecated=true] option now causes the C++ code generator to generate + a GCC-style deprecation annotation (no-op on other compilers). + * google::protobuf::GetEnumDescriptor() returns the + EnumDescriptor for that type -- useful for templates which cannot call + SomeGeneratedEnumType_descriptor(). + * Various optimizations and obscure bug fixes. + + Java + * Lite mode: The "optimize_for = LITE_RUNTIME" option causes the compiler + to generate code which only depends libprotobuf-lite, which is much smaller + than libprotobuf but lacks descriptors, reflection, and some other features. + * Put Builder objects on a freelist after build() is called, so they may be + reused later. + * Lots of style cleanups. + + Python + * Fixed endianness bug with floats and doubles. + * Text format parsing support. + * Fix bug with parsing packed repeated fields in embedded messages. + * Ability to initialize fields by passing keyword args to constructor. + * Support iterators in extend and __setslice__ for containers. 2009-05-13 version 2.1.0: diff --git a/Makefile.am b/Makefile.am index c6412d89..d3ed37ca 100644 --- a/Makefile.am +++ b/Makefile.am @@ -62,6 +62,7 @@ EXTRA_DIST = \ examples/add_person.py \ examples/list_people.py \ java/src/main/java/com/google/protobuf/AbstractMessage.java \ + java/src/main/java/com/google/protobuf/AbstractMessageLite.java \ java/src/main/java/com/google/protobuf/BlockingRpcChannel.java \ java/src/main/java/com/google/protobuf/BlockingService.java \ java/src/main/java/com/google/protobuf/ByteString.java \ @@ -70,10 +71,14 @@ EXTRA_DIST = \ java/src/main/java/com/google/protobuf/Descriptors.java \ java/src/main/java/com/google/protobuf/DynamicMessage.java \ java/src/main/java/com/google/protobuf/ExtensionRegistry.java \ + java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java \ java/src/main/java/com/google/protobuf/FieldSet.java \ java/src/main/java/com/google/protobuf/GeneratedMessage.java \ + java/src/main/java/com/google/protobuf/GeneratedMessageLite.java \ + java/src/main/java/com/google/protobuf/Internal.java \ java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \ java/src/main/java/com/google/protobuf/Message.java \ + java/src/main/java/com/google/protobuf/MessageLite.java \ java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java \ java/src/main/java/com/google/protobuf/RpcCallback.java \ java/src/main/java/com/google/protobuf/RpcChannel.java \ @@ -91,6 +96,7 @@ EXTRA_DIST = \ java/src/test/java/com/google/protobuf/DescriptorsTest.java \ java/src/test/java/com/google/protobuf/DynamicMessageTest.java \ java/src/test/java/com/google/protobuf/GeneratedMessageTest.java \ + java/src/test/java/com/google/protobuf/LiteTest.java \ java/src/test/java/com/google/protobuf/MessageTest.java \ java/src/test/java/com/google/protobuf/ServiceTest.java \ java/src/test/java/com/google/protobuf/TestUtil.java \ @@ -110,6 +116,7 @@ EXTRA_DIST = \ python/google/protobuf/internal/input_stream.py \ python/google/protobuf/internal/input_stream_test.py \ python/google/protobuf/internal/message_listener.py \ + python/google/protobuf/internal/message_test.py \ python/google/protobuf/internal/more_extensions.proto \ python/google/protobuf/internal/more_messages.proto \ python/google/protobuf/internal/output_stream.py \ diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh index 548b2e8f..69dd7dae 100755 --- a/generate_descriptor_proto.sh +++ b/generate_descriptor_proto.sh @@ -5,6 +5,10 @@ # itself, they cannot be generated automatically by a make rule. "make check" # will fail if these files do not match what the protocol compiler would # generate. +# +# HINT: Flags passed to generate_descriptor_proto.sh will be passed directly +# to make when building protoc. This is particularly useful for passing +# -j4 to run 4 jobs simultaneously. if test ! -e src/google/protobuf/stubs/common.h; then cat >&2 << __EOF__ @@ -23,5 +27,5 @@ __EOF__ fi cd src -make protoc && ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:. google/protobuf/descriptor.proto +make $@ protoc && ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:. google/protobuf/descriptor.proto cd .. diff --git a/java/pom.xml b/java/pom.xml index 12787a4b..bf5d206f 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -124,6 +124,9 @@ value="../src/google/protobuf/unittest_optimize_for.proto" /> + + + target/generated-test-sources diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java index 53175cdd..e5bdefe3 100644 --- a/java/src/main/java/com/google/protobuf/AbstractMessage.java +++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java @@ -30,12 +30,12 @@ package com.google.protobuf; +import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; -import java.io.FilterInputStream; import java.io.InputStream; import java.io.IOException; -import java.io.OutputStream; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -45,11 +45,12 @@ import java.util.Map; * * @author kenton@google.com Kenton Varda */ -public abstract class AbstractMessage implements Message { +public abstract class AbstractMessage extends AbstractMessageLite + implements Message { @SuppressWarnings("unchecked") public boolean isInitialized() { // Check that all required fields are present. - for (FieldDescriptor field : getDescriptorForType().getFields()) { + for (final FieldDescriptor field : getDescriptorForType().getFields()) { if (field.isRequired()) { if (!hasField(field)) { return false; @@ -58,11 +59,12 @@ public abstract class AbstractMessage implements Message { } // Check that embedded messages are initialized. - for (Map.Entry entry : getAllFields().entrySet()) { - FieldDescriptor field = entry.getKey(); + for (final Map.Entry entry : + getAllFields().entrySet()) { + final FieldDescriptor field = entry.getKey(); if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { if (field.isRepeated()) { - for (Message element : (List) entry.getValue()) { + for (final Message element : (List) entry.getValue()) { if (!element.isInitialized()) { return false; } @@ -83,117 +85,59 @@ public abstract class AbstractMessage implements Message { return TextFormat.printToString(this); } - public void writeTo(CodedOutputStream output) throws IOException { - for (Map.Entry entry : getAllFields().entrySet()) { - FieldDescriptor field = entry.getKey(); - if (field.isRepeated()) { - List valueList = (List) entry.getValue(); - if (field.getOptions().getPacked()) { - - output.writeTag(field.getNumber(), - WireFormat.WIRETYPE_LENGTH_DELIMITED); - int dataSize = 0; - for (Object element : valueList) { - dataSize += CodedOutputStream.computeFieldSizeNoTag( - field.getType(), element); - } - output.writeRawVarint32(dataSize); - - for (Object element : valueList) { - output.writeFieldNoTag(field.getType(), element); - } - } else { - for (Object element : valueList) { - output.writeField(field.getType(), field.getNumber(), element); - } - } + public void writeTo(final CodedOutputStream output) throws IOException { + final boolean isMessageSet = + getDescriptorForType().getOptions().getMessageSetWireFormat(); + + for (final Map.Entry entry : + getAllFields().entrySet()) { + final FieldDescriptor field = entry.getKey(); + final Object value = entry.getValue(); + if (isMessageSet && field.isExtension() && + field.getType() == FieldDescriptor.Type.MESSAGE && + !field.isRepeated()) { + output.writeMessageSetExtension(field.getNumber(), (Message) value); } else { - output.writeField(field.getType(), field.getNumber(), entry.getValue()); + FieldSet.writeField(field, value, output); } } - UnknownFieldSet unknownFields = getUnknownFields(); - if (getDescriptorForType().getOptions().getMessageSetWireFormat()) { + final UnknownFieldSet unknownFields = getUnknownFields(); + if (isMessageSet) { unknownFields.writeAsMessageSetTo(output); } else { unknownFields.writeTo(output); } } - public ByteString toByteString() { - try { - ByteString.CodedBuilder out = - ByteString.newCodedBuilder(getSerializedSize()); - writeTo(out.getCodedOutput()); - return out.build(); - } catch (IOException e) { - throw new RuntimeException( - "Serializing to a ByteString threw an IOException (should " + - "never happen).", e); - } - } - - public byte[] toByteArray() { - try { - byte[] result = new byte[getSerializedSize()]; - CodedOutputStream output = CodedOutputStream.newInstance(result); - writeTo(output); - output.checkNoSpaceLeft(); - return result; - } catch (IOException e) { - throw new RuntimeException( - "Serializing to a byte array threw an IOException " + - "(should never happen).", e); - } - } - - public void writeTo(OutputStream output) throws IOException { - CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); - writeTo(codedOutput); - codedOutput.flush(); - } - - public void writeDelimitedTo(OutputStream output) throws IOException { - CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); - codedOutput.writeRawVarint32(getSerializedSize()); - writeTo(codedOutput); - codedOutput.flush(); - } - private int memoizedSize = -1; public int getSerializedSize() { int size = memoizedSize; - if (size != -1) return size; + if (size != -1) { + return size; + } size = 0; - for (Map.Entry entry : getAllFields().entrySet()) { - FieldDescriptor field = entry.getKey(); - if (field.isRepeated()) { - List valueList = (List) entry.getValue(); - if (field.getOptions().getPacked()) { - int dataSize = 0; - for (Object element : valueList) { - dataSize += CodedOutputStream.computeFieldSizeNoTag( - field.getType(), element); - } - size += dataSize; - size += CodedOutputStream.computeTagSize(field.getNumber()); - size += CodedOutputStream.computeRawVarint32Size(dataSize); - } else { - for (Object element : valueList) { - size += CodedOutputStream.computeFieldSize( - field.getType(), field.getNumber(), element); - } - } + final boolean isMessageSet = + getDescriptorForType().getOptions().getMessageSetWireFormat(); + + for (final Map.Entry entry : + getAllFields().entrySet()) { + final FieldDescriptor field = entry.getKey(); + final Object value = entry.getValue(); + if (isMessageSet && field.isExtension() && + field.getType() == FieldDescriptor.Type.MESSAGE && + !field.isRepeated()) { + size += CodedOutputStream.computeMessageSetExtensionSize( + field.getNumber(), (Message) value); } else { - size += CodedOutputStream.computeFieldSize( - field.getType(), field.getNumber(), entry.getValue()); + size += FieldSet.computeFieldSize(field, value); } } - UnknownFieldSet unknownFields = getUnknownFields(); - if (getDescriptorForType().getOptions().getMessageSetWireFormat()) { + final UnknownFieldSet unknownFields = getUnknownFields(); + if (isMessageSet) { size += unknownFields.getSerializedSizeAsMessageSet(); } else { size += unknownFields.getSerializedSize(); @@ -204,14 +148,14 @@ public abstract class AbstractMessage implements Message { } @Override - public boolean equals(Object other) { + public boolean equals(final Object other) { if (other == this) { return true; } if (!(other instanceof Message)) { return false; } - Message otherMessage = (Message) other; + final Message otherMessage = (Message) other; if (getDescriptorForType() != otherMessage.getDescriptorForType()) { return false; } @@ -237,20 +181,21 @@ public abstract class AbstractMessage implements Message { */ @SuppressWarnings("unchecked") public static abstract class Builder + extends AbstractMessageLite.Builder implements Message.Builder { // The compiler produces an error if this is not declared explicitly. @Override public abstract BuilderType clone(); public BuilderType clear() { - for (Map.Entry entry : + for (final Map.Entry entry : getAllFields().entrySet()) { clearField(entry.getKey()); } return (BuilderType) this; } - public BuilderType mergeFrom(Message other) { + public BuilderType mergeFrom(final Message other) { if (other.getDescriptorForType() != getDescriptorForType()) { throw new IllegalArgumentException( "mergeFrom(Message) can only merge messages of the same type."); @@ -265,15 +210,15 @@ public abstract class AbstractMessage implements Message { // TODO(kenton): Provide a function somewhere called makeDeepCopy() // which allows people to make secure deep copies of messages. - for (Map.Entry entry : + for (final Map.Entry entry : other.getAllFields().entrySet()) { - FieldDescriptor field = entry.getKey(); + final FieldDescriptor field = entry.getKey(); if (field.isRepeated()) { - for (Object element : (List)entry.getValue()) { + for (final Object element : (List)entry.getValue()) { addRepeatedField(field, element); } } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - Message existingValue = (Message)getField(field); + final Message existingValue = (Message)getField(field); if (existingValue == existingValue.getDefaultInstanceForType()) { setField(field, entry.getValue()); } else { @@ -288,24 +233,288 @@ public abstract class AbstractMessage implements Message { } } + mergeUnknownFields(other.getUnknownFields()); + return (BuilderType) this; } - public BuilderType mergeFrom(CodedInputStream input) throws IOException { + @Override + public BuilderType mergeFrom(final CodedInputStream input) + throws IOException { return mergeFrom(input, ExtensionRegistry.getEmptyRegistry()); } - public BuilderType mergeFrom(CodedInputStream input, - ExtensionRegistry extensionRegistry) - throws IOException { - UnknownFieldSet.Builder unknownFields = + @Override + public BuilderType mergeFrom( + final CodedInputStream input, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + final UnknownFieldSet.Builder unknownFields = UnknownFieldSet.newBuilder(getUnknownFields()); - FieldSet.mergeFrom(input, unknownFields, extensionRegistry, this); + while (true) { + final int tag = input.readTag(); + if (tag == 0) { + break; + } + + if (!mergeFieldFrom(input, unknownFields, extensionRegistry, + this, tag)) { + // end group tag + break; + } + } setUnknownFields(unknownFields.build()); return (BuilderType) this; } - public BuilderType mergeUnknownFields(UnknownFieldSet unknownFields) { + /** + * Like {@link #mergeFrom(CodedInputStream, UnknownFieldSet.Builder, + * ExtensionRegistryLite, Message.Builder)}, but parses a single field. + * Package-private because it is used by GeneratedMessage.ExtendableMessage. + * @param tag The tag, which should have already been read. + * @return {@code true} unless the tag is an end-group tag. + */ + @SuppressWarnings("unchecked") + static boolean mergeFieldFrom( + final CodedInputStream input, + final UnknownFieldSet.Builder unknownFields, + final ExtensionRegistryLite extensionRegistry, + final Message.Builder builder, + final int tag) throws IOException { + final Descriptor type = builder.getDescriptorForType(); + + if (type.getOptions().getMessageSetWireFormat() && + tag == WireFormat.MESSAGE_SET_ITEM_TAG) { + mergeMessageSetExtensionFromCodedStream( + input, unknownFields, extensionRegistry, builder); + return true; + } + + final int wireType = WireFormat.getTagWireType(tag); + final int fieldNumber = WireFormat.getTagFieldNumber(tag); + + final FieldDescriptor field; + Message defaultInstance = null; + + if (type.isExtensionNumber(fieldNumber)) { + // extensionRegistry may be either ExtensionRegistry or + // ExtensionRegistryLite. Since the type we are parsing is a full + // message, only a full ExtensionRegistry could possibly contain + // extensions of it. Otherwise we will treat the registry as if it + // were empty. + if (extensionRegistry instanceof ExtensionRegistry) { + final ExtensionRegistry.ExtensionInfo extension = + ((ExtensionRegistry) extensionRegistry) + .findExtensionByNumber(type, fieldNumber); + if (extension == null) { + field = null; + } else { + field = extension.descriptor; + defaultInstance = extension.defaultInstance; + } + } else { + field = null; + } + } else { + field = type.findFieldByNumber(fieldNumber); + } + + if (field == null || wireType != + FieldSet.getWireFormatForFieldType( + field.getLiteType(), + field.getOptions().getPacked())) { + // Unknown field or wrong wire type. Skip. + return unknownFields.mergeFieldFrom(tag, input); + } + + if (field.getOptions().getPacked()) { + final int length = input.readRawVarint32(); + final int limit = input.pushLimit(length); + if (field.getLiteType() == WireFormat.FieldType.ENUM) { + while (input.getBytesUntilLimit() > 0) { + final int rawValue = input.readEnum(); + final Object value = field.getEnumType().findValueByNumber(rawValue); + if (value == null) { + // If the number isn't recognized as a valid value for this + // enum, drop it (don't even add it to unknownFields). + return true; + } + builder.addRepeatedField(field, value); + } + } else { + while (input.getBytesUntilLimit() > 0) { + final Object value = + FieldSet.readPrimitiveField(input, field.getLiteType()); + builder.addRepeatedField(field, value); + } + } + input.popLimit(limit); + } else { + final Object value; + switch (field.getType()) { + case GROUP: { + final Message.Builder subBuilder; + if (defaultInstance != null) { + subBuilder = defaultInstance.newBuilderForType(); + } else { + subBuilder = builder.newBuilderForField(field); + } + if (!field.isRepeated()) { + subBuilder.mergeFrom((Message) builder.getField(field)); + } + input.readGroup(field.getNumber(), subBuilder, extensionRegistry); + value = subBuilder.build(); + break; + } + case MESSAGE: { + final Message.Builder subBuilder; + if (defaultInstance != null) { + subBuilder = defaultInstance.newBuilderForType(); + } else { + subBuilder = builder.newBuilderForField(field); + } + if (!field.isRepeated()) { + subBuilder.mergeFrom((Message) builder.getField(field)); + } + input.readMessage(subBuilder, extensionRegistry); + value = subBuilder.build(); + break; + } + case ENUM: + final int rawValue = input.readEnum(); + value = field.getEnumType().findValueByNumber(rawValue); + // If the number isn't recognized as a valid value for this enum, + // drop it. + if (value == null) { + unknownFields.mergeVarintField(fieldNumber, rawValue); + return true; + } + break; + default: + value = FieldSet.readPrimitiveField(input, field.getLiteType()); + break; + } + + if (field.isRepeated()) { + builder.addRepeatedField(field, value); + } else { + builder.setField(field, value); + } + } + + return true; + } + + /** Called by {@code #mergeFieldFrom()} to parse a MessageSet extension. */ + private static void mergeMessageSetExtensionFromCodedStream( + final CodedInputStream input, + final UnknownFieldSet.Builder unknownFields, + final ExtensionRegistryLite extensionRegistry, + final Message.Builder builder) throws IOException { + final Descriptor type = builder.getDescriptorForType(); + + // The wire format for MessageSet is: + // message MessageSet { + // repeated group Item = 1 { + // required int32 typeId = 2; + // required bytes message = 3; + // } + // } + // "typeId" is the extension's field number. The extension can only be + // a message type, where "message" contains the encoded bytes of that + // message. + // + // In practice, we will probably never see a MessageSet item in which + // the message appears before the type ID, or where either field does not + // appear exactly once. However, in theory such cases are valid, so we + // should be prepared to accept them. + + int typeId = 0; + ByteString rawBytes = null; // If we encounter "message" before "typeId" + Message.Builder subBuilder = null; + FieldDescriptor field = null; + + while (true) { + final int tag = input.readTag(); + if (tag == 0) { + break; + } + + if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) { + typeId = input.readUInt32(); + // Zero is not a valid type ID. + if (typeId != 0) { + final ExtensionRegistry.ExtensionInfo extension; + + // extensionRegistry may be either ExtensionRegistry or + // ExtensionRegistryLite. Since the type we are parsing is a full + // message, only a full ExtensionRegistry could possibly contain + // extensions of it. Otherwise we will treat the registry as if it + // were empty. + if (extensionRegistry instanceof ExtensionRegistry) { + extension = ((ExtensionRegistry) extensionRegistry) + .findExtensionByNumber(type, typeId); + } else { + extension = null; + } + + if (extension != null) { + field = extension.descriptor; + subBuilder = extension.defaultInstance.newBuilderForType(); + final Message originalMessage = (Message)builder.getField(field); + if (originalMessage != null) { + subBuilder.mergeFrom(originalMessage); + } + if (rawBytes != null) { + // We already encountered the message. Parse it now. + subBuilder.mergeFrom( + CodedInputStream.newInstance(rawBytes.newInput())); + rawBytes = null; + } + } else { + // Unknown extension number. If we already saw data, put it + // in rawBytes. + if (rawBytes != null) { + unknownFields.mergeField(typeId, + UnknownFieldSet.Field.newBuilder() + .addLengthDelimited(rawBytes) + .build()); + rawBytes = null; + } + } + } + } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) { + if (typeId == 0) { + // We haven't seen a type ID yet, so we have to store the raw bytes + // for now. + rawBytes = input.readBytes(); + } else if (subBuilder == null) { + // We don't know how to parse this. Ignore it. + unknownFields.mergeField(typeId, + UnknownFieldSet.Field.newBuilder() + .addLengthDelimited(input.readBytes()) + .build()); + } else { + // We already know the type, so we can parse directly from the input + // with no copying. Hooray! + input.readMessage(subBuilder, extensionRegistry); + } + } else { + // Unknown tag. Skip it. + if (!input.skipField(tag)) { + break; // end of group + } + } + } + + input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG); + + if (subBuilder != null) { + builder.setField(field, subBuilder.build()); + } + } + + public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) { setUnknownFields( UnknownFieldSet.newBuilder(getUnknownFields()) .mergeFrom(unknownFields) @@ -313,145 +522,169 @@ public abstract class AbstractMessage implements Message { return (BuilderType) this; } - public BuilderType mergeFrom(ByteString data) - throws InvalidProtocolBufferException { - try { - CodedInputStream input = data.newCodedInput(); - mergeFrom(input); - input.checkLastTagWas(0); - return (BuilderType) this; - } catch (InvalidProtocolBufferException e) { - throw e; - } catch (IOException e) { - throw new RuntimeException( - "Reading from a ByteString threw an IOException (should " + - "never happen).", e); + /** + * Construct an UninitializedMessageException reporting missing fields in + * the given message. + */ + protected static UninitializedMessageException + newUninitializedMessageException(Message message) { + return new UninitializedMessageException(findMissingFields(message)); + } + + /** + * Populates {@code this.missingFields} with the full "path" of each + * missing required field in the given message. + */ + private static List findMissingFields(final Message message) { + final List results = new ArrayList(); + findMissingFields(message, "", results); + return results; + } + + /** Recursive helper implementing {@link #findMissingFields(Message)}. */ + private static void findMissingFields(final Message message, + final String prefix, + final List results) { + for (final FieldDescriptor field : + message.getDescriptorForType().getFields()) { + if (field.isRequired() && !message.hasField(field)) { + results.add(prefix + field.getName()); + } + } + + for (final Map.Entry entry : + message.getAllFields().entrySet()) { + final FieldDescriptor field = entry.getKey(); + final Object value = entry.getValue(); + + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + if (field.isRepeated()) { + int i = 0; + for (final Object element : (List) value) { + findMissingFields((Message) element, + subMessagePrefix(prefix, field, i++), + results); + } + } else { + if (message.hasField(field)) { + findMissingFields((Message) value, + subMessagePrefix(prefix, field, -1), + results); + } + } + } } } - public BuilderType mergeFrom(ByteString data, - ExtensionRegistry extensionRegistry) - throws InvalidProtocolBufferException { - try { - CodedInputStream input = data.newCodedInput(); - mergeFrom(input, extensionRegistry); - input.checkLastTagWas(0); - return (BuilderType) this; - } catch (InvalidProtocolBufferException e) { - throw e; - } catch (IOException e) { - throw new RuntimeException( - "Reading from a ByteString threw an IOException (should " + - "never happen).", e); + private static String subMessagePrefix(final String prefix, + final FieldDescriptor field, + final int index) { + final StringBuilder result = new StringBuilder(prefix); + if (field.isExtension()) { + result.append('(') + .append(field.getFullName()) + .append(')'); + } else { + result.append(field.getName()); } + if (index != -1) { + result.append('[') + .append(index) + .append(']'); + } + result.append('.'); + return result.toString(); } - public BuilderType mergeFrom(byte[] data) + // =============================================================== + // The following definitions seem to be required in order to make javac + // not produce weird errors like: + // + // java/com/google/protobuf/DynamicMessage.java:203: types + // com.google.protobuf.AbstractMessage.Builder< + // com.google.protobuf.DynamicMessage.Builder> and + // com.google.protobuf.AbstractMessage.Builder< + // com.google.protobuf.DynamicMessage.Builder> are incompatible; both + // define mergeFrom(com.google.protobuf.ByteString), but with unrelated + // return types. + // + // Strangely, these lines are only needed if javac is invoked separately + // on AbstractMessage.java and AbstractMessageLite.java. If javac is + // invoked on both simultaneously, it works. (Or maybe the important + // point is whether or not DynamicMessage.java is compiled together with + // AbstractMessageLite.java -- not sure.) I suspect this is a compiler + // bug. + + @Override + public BuilderType mergeFrom(final ByteString data) throws InvalidProtocolBufferException { - return mergeFrom(data, 0, data.length); + return super.mergeFrom(data); } - public BuilderType mergeFrom(byte[] data, int off, int len) + @Override + public BuilderType mergeFrom( + final ByteString data, + final ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { - try { - CodedInputStream input = CodedInputStream.newInstance(data, off, len); - mergeFrom(input); - input.checkLastTagWas(0); - return (BuilderType) this; - } catch (InvalidProtocolBufferException e) { - throw e; - } catch (IOException e) { - throw new RuntimeException( - "Reading from a byte array threw an IOException (should " + - "never happen).", e); - } + return super.mergeFrom(data, extensionRegistry); } - public BuilderType mergeFrom( - byte[] data, - ExtensionRegistry extensionRegistry) + @Override + public BuilderType mergeFrom(final byte[] data) throws InvalidProtocolBufferException { - return mergeFrom(data, 0, data.length, extensionRegistry); + return super.mergeFrom(data); } + @Override public BuilderType mergeFrom( - byte[] data, int off, int len, - ExtensionRegistry extensionRegistry) + final byte[] data, final int off, final int len) throws InvalidProtocolBufferException { - try { - CodedInputStream input = CodedInputStream.newInstance(data, off, len); - mergeFrom(input, extensionRegistry); - input.checkLastTagWas(0); - return (BuilderType) this; - } catch (InvalidProtocolBufferException e) { - throw e; - } catch (IOException e) { - throw new RuntimeException( - "Reading from a byte array threw an IOException (should " + - "never happen).", e); - } + return super.mergeFrom(data, off, len); } - public BuilderType mergeFrom(InputStream input) throws IOException { - CodedInputStream codedInput = CodedInputStream.newInstance(input); - mergeFrom(codedInput); - codedInput.checkLastTagWas(0); - return (BuilderType) this; + @Override + public BuilderType mergeFrom( + final byte[] data, + final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return super.mergeFrom(data, extensionRegistry); } - public BuilderType mergeFrom(InputStream input, - ExtensionRegistry extensionRegistry) - throws IOException { - CodedInputStream codedInput = CodedInputStream.newInstance(input); - mergeFrom(codedInput, extensionRegistry); - codedInput.checkLastTagWas(0); - return (BuilderType) this; + @Override + public BuilderType mergeFrom( + final byte[] data, final int off, final int len, + final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return super.mergeFrom(data, off, len, extensionRegistry); } - public BuilderType mergeDelimitedFrom(InputStream input, - ExtensionRegistry extensionRegistry) - throws IOException { - final int size = CodedInputStream.readRawVarint32(input); - - // A stream which will not read more than |size| bytes. - InputStream limitedInput = new FilterInputStream(input) { - int limit = size; - - @Override - public int available() throws IOException { - return Math.min(super.available(), limit); - } - - @Override - public int read() throws IOException { - if (limit <= 0) return -1; - int result = super.read(); - if (result >= 0) --limit; - return result; - } + @Override + public BuilderType mergeFrom(final InputStream input) + throws IOException { + return super.mergeFrom(input); + } - @Override - public int read(byte[] b, int off, int len) throws IOException { - if (limit <= 0) return -1; - len = Math.min(len, limit); - int result = super.read(b, off, len); - if (result >= 0) limit -= result; - return result; - } + @Override + public BuilderType mergeFrom( + final InputStream input, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + return super.mergeFrom(input, extensionRegistry); + } - @Override - public long skip(long n) throws IOException { - long result = super.skip(Math.min(n, limit)); - if (result >= 0) limit -= result; - return result; - } - }; - return mergeFrom(limitedInput, extensionRegistry); + @Override + public BuilderType mergeDelimitedFrom(final InputStream input) + throws IOException { + return super.mergeDelimitedFrom(input); } - public BuilderType mergeDelimitedFrom(InputStream input) + @Override + public BuilderType mergeDelimitedFrom( + final InputStream input, + final ExtensionRegistryLite extensionRegistry) throws IOException { - return mergeDelimitedFrom(input, ExtensionRegistry.getEmptyRegistry()); + return super.mergeDelimitedFrom(input, extensionRegistry); } + } } diff --git a/java/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java new file mode 100644 index 00000000..489577df --- /dev/null +++ b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java @@ -0,0 +1,321 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.io.FilterInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Collection; + +/** + * A partial implementation of the {@link MessageLite} interface which + * implements as many methods of that interface as possible in terms of other + * methods. + * + * @author kenton@google.com Kenton Varda + */ +public abstract class AbstractMessageLite implements MessageLite { + public ByteString toByteString() { + try { + final ByteString.CodedBuilder out = + ByteString.newCodedBuilder(getSerializedSize()); + writeTo(out.getCodedOutput()); + return out.build(); + } catch (IOException e) { + throw new RuntimeException( + "Serializing to a ByteString threw an IOException (should " + + "never happen).", e); + } + } + + public byte[] toByteArray() { + try { + final byte[] result = new byte[getSerializedSize()]; + final CodedOutputStream output = CodedOutputStream.newInstance(result); + writeTo(output); + output.checkNoSpaceLeft(); + return result; + } catch (IOException e) { + throw new RuntimeException( + "Serializing to a byte array threw an IOException " + + "(should never happen).", e); + } + } + + public void writeTo(final OutputStream output) throws IOException { + final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); + writeTo(codedOutput); + codedOutput.flush(); + } + + public void writeDelimitedTo(final OutputStream output) throws IOException { + final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); + codedOutput.writeRawVarint32(getSerializedSize()); + writeTo(codedOutput); + codedOutput.flush(); + } + + /** + * A partial implementation of the {@link Message.Builder} interface which + * implements as many methods of that interface as possible in terms of + * other methods. + */ + @SuppressWarnings("unchecked") + public static abstract class Builder + implements MessageLite.Builder { + // The compiler produces an error if this is not declared explicitly. + @Override + public abstract BuilderType clone(); + + public BuilderType mergeFrom(final CodedInputStream input) + throws IOException { + // TODO(kenton): Don't use null here. Currently we have to because + // using ExtensionRegistry.getEmptyRegistry() would imply a dependency + // on ExtensionRegistry. However, AbstractMessage overrides this with + // a correct implementation, and lite messages don't yet support + // extensions, so it ends up not mattering for now. It will matter + // once lite messages support extensions. + return mergeFrom(input, null); + } + + // Re-defined here for return type covariance. + public abstract BuilderType mergeFrom( + final CodedInputStream input, + final ExtensionRegistryLite extensionRegistry) + throws IOException; + + public BuilderType mergeFrom(final ByteString data) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = data.newCodedInput(); + mergeFrom(input); + input.checkLastTagWas(0); + return (BuilderType) this; + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "Reading from a ByteString threw an IOException (should " + + "never happen).", e); + } + } + + public BuilderType mergeFrom( + final ByteString data, + final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = data.newCodedInput(); + mergeFrom(input, extensionRegistry); + input.checkLastTagWas(0); + return (BuilderType) this; + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "Reading from a ByteString threw an IOException (should " + + "never happen).", e); + } + } + + public BuilderType mergeFrom(final byte[] data) + throws InvalidProtocolBufferException { + return mergeFrom(data, 0, data.length); + } + + public BuilderType mergeFrom(final byte[] data, final int off, + final int len) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = + CodedInputStream.newInstance(data, off, len); + mergeFrom(input); + input.checkLastTagWas(0); + return (BuilderType) this; + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "Reading from a byte array threw an IOException (should " + + "never happen).", e); + } + } + + public BuilderType mergeFrom( + final byte[] data, + final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return mergeFrom(data, 0, data.length, extensionRegistry); + } + + public BuilderType mergeFrom( + final byte[] data, final int off, final int len, + final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = + CodedInputStream.newInstance(data, off, len); + mergeFrom(input, extensionRegistry); + input.checkLastTagWas(0); + return (BuilderType) this; + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "Reading from a byte array threw an IOException (should " + + "never happen).", e); + } + } + + public BuilderType mergeFrom(final InputStream input) throws IOException { + final CodedInputStream codedInput = CodedInputStream.newInstance(input); + mergeFrom(codedInput); + codedInput.checkLastTagWas(0); + return (BuilderType) this; + } + + public BuilderType mergeFrom( + final InputStream input, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + final CodedInputStream codedInput = CodedInputStream.newInstance(input); + mergeFrom(codedInput, extensionRegistry); + codedInput.checkLastTagWas(0); + return (BuilderType) this; + } + + /** + * An InputStream implementations which reads from some other InputStream + * but is limited to a particular number of bytes. Used by + * mergeDelimitedFrom(). This is intentionally package-private so that + * UnknownFieldSet can share it. + */ + static final class LimitedInputStream extends FilterInputStream { + private int limit; + + LimitedInputStream(InputStream in, int limit) { + super(in); + this.limit = limit; + } + + @Override + public int available() throws IOException { + return Math.min(super.available(), limit); + } + + @Override + public int read() throws IOException { + if (limit <= 0) { + return -1; + } + final int result = super.read(); + if (result >= 0) { + --limit; + } + return result; + } + + @Override + public int read(final byte[] b, final int off, int len) + throws IOException { + if (limit <= 0) { + return -1; + } + len = Math.min(len, limit); + final int result = super.read(b, off, len); + if (result >= 0) { + limit -= result; + } + return result; + } + + @Override + public long skip(final long n) throws IOException { + final long result = super.skip(Math.min(n, limit)); + if (result >= 0) { + limit -= result; + } + return result; + } + } + + public BuilderType mergeDelimitedFrom( + final InputStream input, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + final int size = CodedInputStream.readRawVarint32(input); + final InputStream limitedInput = new LimitedInputStream(input, size); + return mergeFrom(limitedInput, extensionRegistry); + } + + public BuilderType mergeDelimitedFrom(final InputStream input) + throws IOException { + final int size = CodedInputStream.readRawVarint32(input); + final InputStream limitedInput = new LimitedInputStream(input, size); + return mergeFrom(limitedInput); + } + + /** + * Construct an UninitializedMessageException reporting missing fields in + * the given message. + */ + protected static UninitializedMessageException + newUninitializedMessageException(MessageLite message) { + return new UninitializedMessageException(message); + } + + /** + * Adds the {@code values} to the {@code list}. This is a helper method + * used by generated code. Users should ignore it. + * + * @throws NullPointerException if any of the elements of {@code values} is + * null. + */ + protected static void addAll(final Iterable values, + final Collection list) { + for (final T value : values) { + if (value == null) { + throw new NullPointerException(); + } + } + if (values instanceof Collection) { + @SuppressWarnings("unsafe") final + Collection collection = (Collection) values; + list.addAll(collection); + } else { + for (final T value : values) { + list.add(value); + } + } + } + } +} diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java index f376e7a1..c83c335c 100644 --- a/java/src/main/java/com/google/protobuf/ByteString.java +++ b/java/src/main/java/com/google/protobuf/ByteString.java @@ -46,7 +46,7 @@ import java.nio.ByteBuffer; public final class ByteString { private final byte[] bytes; - private ByteString(byte[] bytes) { + private ByteString(final byte[] bytes) { this.bytes = bytes; } @@ -55,7 +55,7 @@ public final class ByteString { * * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size */ - public byte byteAt(int index) { + public byte byteAt(final int index) { return bytes[index]; } @@ -63,14 +63,14 @@ public final class ByteString { * Gets the number of bytes. */ public int size() { - return this.bytes.length; + return bytes.length; } /** * Returns {@code true} if the size is {@code 0}, {@code false} otherwise. */ public boolean isEmpty() { - return this.bytes.length == 0; + return bytes.length == 0; } // ================================================================= @@ -84,8 +84,9 @@ public final class ByteString { /** * Copies the given bytes into a {@code ByteString}. */ - public static ByteString copyFrom(byte[] bytes, int offset, int size) { - byte[] copy = new byte[size]; + public static ByteString copyFrom(final byte[] bytes, final int offset, + final int size) { + final byte[] copy = new byte[size]; System.arraycopy(bytes, offset, copy, 0, size); return new ByteString(copy); } @@ -93,7 +94,7 @@ public final class ByteString { /** * Copies the given bytes into a {@code ByteString}. */ - public static ByteString copyFrom(byte[] bytes) { + public static ByteString copyFrom(final byte[] bytes) { return copyFrom(bytes, 0, bytes.length); } @@ -101,7 +102,7 @@ public final class ByteString { * Encodes {@code text} into a sequence of bytes using the named charset * and returns the result as a {@code ByteString}. */ - public static ByteString copyFrom(String text, String charsetName) + public static ByteString copyFrom(final String text, final String charsetName) throws UnsupportedEncodingException { return new ByteString(text.getBytes(charsetName)); } @@ -110,7 +111,7 @@ public final class ByteString { * Encodes {@code text} into a sequence of UTF-8 bytes and returns the * result as a {@code ByteString}. */ - public static ByteString copyFromUtf8(String text) { + public static ByteString copyFromUtf8(final String text) { try { return new ByteString(text.getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { @@ -127,7 +128,7 @@ public final class ByteString { * @param target buffer to copy into * @param offset in the target buffer */ - public void copyTo(byte[] target, int offset) { + public void copyTo(final byte[] target, final int offset) { System.arraycopy(bytes, 0, target, offset, bytes.length); } @@ -139,8 +140,9 @@ public final class ByteString { * @param targetOffset offset within the target buffer * @param size number of bytes to copy */ - public void copyTo(byte[] target, int sourceOffset, int targetOffset, - int size) { + public void copyTo(final byte[] target, final int sourceOffset, + final int targetOffset, + final int size) { System.arraycopy(bytes, sourceOffset, target, targetOffset, size); } @@ -148,9 +150,9 @@ public final class ByteString { * Copies bytes to a {@code byte[]}. */ public byte[] toByteArray() { - int size = this.bytes.length; - byte[] copy = new byte[size]; - System.arraycopy(this.bytes, 0, copy, 0, size); + final int size = bytes.length; + final byte[] copy = new byte[size]; + System.arraycopy(bytes, 0, copy, 0, size); return copy; } @@ -159,7 +161,7 @@ public final class ByteString { * same backing byte array. */ public ByteBuffer asReadOnlyByteBuffer() { - ByteBuffer byteBuffer = ByteBuffer.wrap(this.bytes); + final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); return byteBuffer.asReadOnlyBuffer(); } @@ -167,9 +169,9 @@ public final class ByteString { * Constructs a new {@code String} by decoding the bytes using the * specified charset. */ - public String toString(String charsetName) + public String toString(final String charsetName) throws UnsupportedEncodingException { - return new String(this.bytes, charsetName); + return new String(bytes, charsetName); } /** @@ -177,7 +179,7 @@ public final class ByteString { */ public String toStringUtf8() { try { - return new String(this.bytes, "UTF-8"); + return new String(bytes, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException("UTF-8 not supported?", e); } @@ -187,7 +189,7 @@ public final class ByteString { // equals() and hashCode() @Override - public boolean equals(Object o) { + public boolean equals(final Object o) { if (o == this) { return true; } @@ -196,16 +198,16 @@ public final class ByteString { return false; } - ByteString other = (ByteString) o; - int size = this.bytes.length; + final ByteString other = (ByteString) o; + final int size = bytes.length; if (size != other.bytes.length) { return false; } - byte[] bytes = this.bytes; - byte[] otherBytes = other.bytes; + final byte[] thisBytes = bytes; + final byte[] otherBytes = other.bytes; for (int i = 0; i < size; i++) { - if (bytes[i] != otherBytes[i]) { + if (thisBytes[i] != otherBytes[i]) { return false; } } @@ -213,25 +215,25 @@ public final class ByteString { return true; } - volatile int hash = 0; + private volatile int hash = 0; @Override public int hashCode() { - int h = this.hash; + int h = hash; if (h == 0) { - byte[] bytes = this.bytes; - int size = this.bytes.length; + final byte[] thisBytes = bytes; + final int size = bytes.length; h = size; for (int i = 0; i < size; i++) { - h = h * 31 + bytes[i]; + h = h * 31 + thisBytes[i]; } if (h == 0) { h = 1; } - this.hash = h; + hash = h; } return h; @@ -264,7 +266,7 @@ public final class ByteString { /** * Creates a new {@link Output} with the given initial capacity. */ - public static Output newOutput(int initialCapacity) { + public static Output newOutput(final int initialCapacity) { return new Output(new ByteArrayOutputStream(initialCapacity)); } @@ -285,7 +287,7 @@ public final class ByteString { /** * Constructs a new output with the given initial capacity. */ - private Output(ByteArrayOutputStream bout) { + private Output(final ByteArrayOutputStream bout) { super(bout); this.bout = bout; } @@ -294,14 +296,14 @@ public final class ByteString { * Creates a {@code ByteString} instance from this {@code Output}. */ public ByteString toByteString() { - byte[] byteArray = bout.toByteArray(); + final byte[] byteArray = bout.toByteArray(); return new ByteString(byteArray); } } /** * Constructs a new ByteString builder, which allows you to efficiently - * construct a {@code ByteString} by writing to a {@link CodedOutputSteam}. + * construct a {@code ByteString} by writing to a {@link CodedOutputStream}. * Using this is much more efficient than calling {@code newOutput()} and * wrapping that in a {@code CodedOutputStream}. * @@ -312,7 +314,7 @@ public final class ByteString { * @param size The target byte size of the {@code ByteString}. You must * write exactly this many bytes before building the result. */ - static CodedBuilder newCodedBuilder(int size) { + static CodedBuilder newCodedBuilder(final int size) { return new CodedBuilder(size); } @@ -321,7 +323,7 @@ public final class ByteString { private final CodedOutputStream output; private final byte[] buffer; - private CodedBuilder(int size) { + private CodedBuilder(final int size) { buffer = new byte[size]; output = CodedOutputStream.newInstance(buffer); } diff --git a/java/src/main/java/com/google/protobuf/CodedInputStream.java b/java/src/main/java/com/google/protobuf/CodedInputStream.java index b6be2e87..9125957d 100644 --- a/java/src/main/java/com/google/protobuf/CodedInputStream.java +++ b/java/src/main/java/com/google/protobuf/CodedInputStream.java @@ -51,21 +51,22 @@ public final class CodedInputStream { /** * Create a new CodedInputStream wrapping the given InputStream. */ - public static CodedInputStream newInstance(InputStream input) { + public static CodedInputStream newInstance(final InputStream input) { return new CodedInputStream(input); } /** * Create a new CodedInputStream wrapping the given byte array. */ - public static CodedInputStream newInstance(byte[] buf) { + public static CodedInputStream newInstance(final byte[] buf) { return newInstance(buf, 0, buf.length); } /** * Create a new CodedInputStream wrapping the given byte array slice. */ - public static CodedInputStream newInstance(byte[] buf, int off, int len) { + public static CodedInputStream newInstance(final byte[] buf, final int off, + final int len) { return new CodedInputStream(buf, off, len); } @@ -98,7 +99,8 @@ public final class CodedInputStream { * @throws InvalidProtocolBufferException {@code value} does not match the * last tag. */ - public void checkLastTagWas(int value) throws InvalidProtocolBufferException { + public void checkLastTagWas(final int value) + throws InvalidProtocolBufferException { if (lastTag != value) { throw InvalidProtocolBufferException.invalidEndTag(); } @@ -110,7 +112,7 @@ public final class CodedInputStream { * @return {@code false} if the tag is an endgroup tag, in which case * nothing is skipped. Otherwise, returns {@code true}. */ - public boolean skipField(int tag) throws IOException { + public boolean skipField(final int tag) throws IOException { switch (WireFormat.getTagWireType(tag)) { case WireFormat.WIRETYPE_VARINT: readInt32(); @@ -143,8 +145,10 @@ public final class CodedInputStream { */ public void skipMessage() throws IOException { while (true) { - int tag = readTag(); - if (tag == 0 || !skipField(tag)) return; + final int tag = readTag(); + if (tag == 0 || !skipField(tag)) { + return; + } } } @@ -192,11 +196,11 @@ public final class CodedInputStream { /** Read a {@code string} field value from the stream. */ public String readString() throws IOException { - int size = readRawVarint32(); + final int size = readRawVarint32(); if (size <= (bufferSize - bufferPos) && size > 0) { // Fast path: We already have the bytes in a contiguous buffer, so // just copy directly from it. - String result = new String(buffer, bufferPos, size, "UTF-8"); + final String result = new String(buffer, bufferPos, size, "UTF-8"); bufferPos += size; return result; } else { @@ -206,8 +210,9 @@ public final class CodedInputStream { } /** Read a {@code group} field value from the stream. */ - public void readGroup(int fieldNumber, Message.Builder builder, - ExtensionRegistry extensionRegistry) + public void readGroup(final int fieldNumber, + final MessageLite.Builder builder, + final ExtensionRegistryLite extensionRegistry) throws IOException { if (recursionDepth >= recursionLimit) { throw InvalidProtocolBufferException.recursionLimitExceeded(); @@ -222,28 +227,31 @@ public final class CodedInputStream { /** * Reads a {@code group} field value from the stream and merges it into the * given {@link UnknownFieldSet}. + * + * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so + * you can just call {@link #readGroup}. */ - public void readUnknownGroup(int fieldNumber, UnknownFieldSet.Builder builder) + @Deprecated + public void readUnknownGroup(final int fieldNumber, + final MessageLite.Builder builder) throws IOException { - if (recursionDepth >= recursionLimit) { - throw InvalidProtocolBufferException.recursionLimitExceeded(); - } - ++recursionDepth; - builder.mergeFrom(this); - checkLastTagWas( - WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); - --recursionDepth; + // We know that UnknownFieldSet will ignore any ExtensionRegistry so it + // is safe to pass null here. (We can't call + // ExtensionRegistry.getEmptyRegistry() because that would make this + // class depend on ExtensionRegistry, which is not part of the lite + // library.) + readGroup(fieldNumber, builder, null); } /** Read an embedded message field value from the stream. */ - public void readMessage(Message.Builder builder, - ExtensionRegistry extensionRegistry) + public void readMessage(final MessageLite.Builder builder, + final ExtensionRegistryLite extensionRegistry) throws IOException { - int length = readRawVarint32(); + final int length = readRawVarint32(); if (recursionDepth >= recursionLimit) { throw InvalidProtocolBufferException.recursionLimitExceeded(); } - int oldLimit = pushLimit(length); + final int oldLimit = pushLimit(length); ++recursionDepth; builder.mergeFrom(this, extensionRegistry); checkLastTagWas(0); @@ -253,11 +261,11 @@ public final class CodedInputStream { /** Read a {@code bytes} field value from the stream. */ public ByteString readBytes() throws IOException { - int size = readRawVarint32(); - if (size < bufferSize - bufferPos && size > 0) { + final int size = readRawVarint32(); + if (size <= (bufferSize - bufferPos) && size > 0) { // Fast path: We already have the bytes in a contiguous buffer, so // just copy directly from it. - ByteString result = ByteString.copyFrom(buffer, bufferPos, size); + final ByteString result = ByteString.copyFrom(buffer, bufferPos, size); bufferPos += size; return result; } else { @@ -299,52 +307,6 @@ public final class CodedInputStream { return decodeZigZag64(readRawVarint64()); } - /** - * Read a field of any primitive type. Enums, groups, and embedded - * messages are not handled by this method. - * - * @param type Declared type of the field. - * @return An object representing the field's value, of the exact - * type which would be returned by - * {@link Message#getField(Descriptors.FieldDescriptor)} for - * this field. - */ - public Object readPrimitiveField( - Descriptors.FieldDescriptor.Type type) throws IOException { - switch (type) { - case DOUBLE : return readDouble (); - case FLOAT : return readFloat (); - case INT64 : return readInt64 (); - case UINT64 : return readUInt64 (); - case INT32 : return readInt32 (); - case FIXED64 : return readFixed64 (); - case FIXED32 : return readFixed32 (); - case BOOL : return readBool (); - case STRING : return readString (); - case BYTES : return readBytes (); - case UINT32 : return readUInt32 (); - case SFIXED32: return readSFixed32(); - case SFIXED64: return readSFixed64(); - case SINT32 : return readSInt32 (); - case SINT64 : return readSInt64 (); - - case GROUP: - throw new IllegalArgumentException( - "readPrimitiveField() cannot handle nested groups."); - case MESSAGE: - throw new IllegalArgumentException( - "readPrimitiveField() cannot handle embedded messages."); - case ENUM: - // We don't hanlde enums because we don't know what to do if the - // value is not recognized. - throw new IllegalArgumentException( - "readPrimitiveField() cannot handle enums."); - } - - throw new RuntimeException( - "There is no way to get here, but the compiler thinks otherwise."); - } - // ================================================================= /** @@ -373,7 +335,9 @@ public final class CodedInputStream { if (tmp < 0) { // Discard upper 32 bits. for (int i = 0; i < 5; i++) { - if (readRawByte() >= 0) return result; + if (readRawByte() >= 0) { + return result; + } } throw InvalidProtocolBufferException.malformedVarint(); } @@ -390,11 +354,11 @@ public final class CodedInputStream { * then you would probably end up reading past the end of the varint since * CodedInputStream buffers its input. */ - static int readRawVarint32(InputStream input) throws IOException { + static int readRawVarint32(final InputStream input) throws IOException { int result = 0; int offset = 0; for (; offset < 32; offset += 7) { - int b = input.read(); + final int b = input.read(); if (b == -1) { throw InvalidProtocolBufferException.truncatedMessage(); } @@ -405,7 +369,7 @@ public final class CodedInputStream { } // Keep reading up to 64 bits. for (; offset < 64; offset += 7) { - int b = input.read(); + final int b = input.read(); if (b == -1) { throw InvalidProtocolBufferException.truncatedMessage(); } @@ -421,9 +385,11 @@ public final class CodedInputStream { int shift = 0; long result = 0; while (shift < 64) { - byte b = readRawByte(); + final byte b = readRawByte(); result |= (long)(b & 0x7F) << shift; - if ((b & 0x80) == 0) return result; + if ((b & 0x80) == 0) { + return result; + } shift += 7; } throw InvalidProtocolBufferException.malformedVarint(); @@ -431,10 +397,10 @@ public final class CodedInputStream { /** Read a 32-bit little-endian integer from the stream. */ public int readRawLittleEndian32() throws IOException { - byte b1 = readRawByte(); - byte b2 = readRawByte(); - byte b3 = readRawByte(); - byte b4 = readRawByte(); + final byte b1 = readRawByte(); + final byte b2 = readRawByte(); + final byte b3 = readRawByte(); + final byte b4 = readRawByte(); return (((int)b1 & 0xff) ) | (((int)b2 & 0xff) << 8) | (((int)b3 & 0xff) << 16) | @@ -443,14 +409,14 @@ public final class CodedInputStream { /** Read a 64-bit little-endian integer from the stream. */ public long readRawLittleEndian64() throws IOException { - byte b1 = readRawByte(); - byte b2 = readRawByte(); - byte b3 = readRawByte(); - byte b4 = readRawByte(); - byte b5 = readRawByte(); - byte b6 = readRawByte(); - byte b7 = readRawByte(); - byte b8 = readRawByte(); + final byte b1 = readRawByte(); + final byte b2 = readRawByte(); + final byte b3 = readRawByte(); + final byte b4 = readRawByte(); + final byte b5 = readRawByte(); + final byte b6 = readRawByte(); + final byte b7 = readRawByte(); + final byte b8 = readRawByte(); return (((long)b1 & 0xff) ) | (((long)b2 & 0xff) << 8) | (((long)b3 & 0xff) << 16) | @@ -471,7 +437,7 @@ public final class CodedInputStream { * Java has no explicit unsigned support. * @return A signed 32-bit integer. */ - public static int decodeZigZag32(int n) { + public static int decodeZigZag32(final int n) { return (n >>> 1) ^ -(n & 1); } @@ -485,31 +451,31 @@ public final class CodedInputStream { * Java has no explicit unsigned support. * @return A signed 64-bit integer. */ - public static long decodeZigZag64(long n) { + public static long decodeZigZag64(final long n) { return (n >>> 1) ^ -(n & 1); } // ----------------------------------------------------------------- - private byte[] buffer; + private final byte[] buffer; private int bufferSize; - private int bufferSizeAfterLimit = 0; + private int bufferSizeAfterLimit; private int bufferPos; - private InputStream input; - private int lastTag = 0; + private final InputStream input; + private int lastTag; /** * The total number of bytes read before the current buffer. The total * bytes read up to the current position can be computed as * {@code totalBytesRetired + bufferPos}. */ - private int totalBytesRetired = 0; + private int totalBytesRetired; /** The absolute position of the end of the current message. */ private int currentLimit = Integer.MAX_VALUE; /** See setRecursionLimit() */ - private int recursionDepth = 0; + private int recursionDepth; private int recursionLimit = DEFAULT_RECURSION_LIMIT; /** See setSizeLimit() */ @@ -519,17 +485,17 @@ public final class CodedInputStream { private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB private static final int BUFFER_SIZE = 4096; - private CodedInputStream(byte[] buffer, int off, int len) { + private CodedInputStream(final byte[] buffer, final int off, final int len) { this.buffer = buffer; - this.bufferSize = off + len; - this.bufferPos = off; - this.input = null; + bufferSize = off + len; + bufferPos = off; + input = null; } - private CodedInputStream(InputStream input) { - this.buffer = new byte[BUFFER_SIZE]; - this.bufferSize = 0; - this.bufferPos = 0; + private CodedInputStream(final InputStream input) { + buffer = new byte[BUFFER_SIZE]; + bufferSize = 0; + bufferPos = 0; this.input = input; } @@ -540,12 +506,12 @@ public final class CodedInputStream { * * @return the old limit. */ - public int setRecursionLimit(int limit) { + public int setRecursionLimit(final int limit) { if (limit < 0) { throw new IllegalArgumentException( "Recursion limit cannot be negative: " + limit); } - int oldLimit = recursionLimit; + final int oldLimit = recursionLimit; recursionLimit = limit; return oldLimit; } @@ -566,12 +532,12 @@ public final class CodedInputStream { * * @return the old limit. */ - public int setSizeLimit(int limit) { + public int setSizeLimit(final int limit) { if (limit < 0) { throw new IllegalArgumentException( "Size limit cannot be negative: " + limit); } - int oldLimit = sizeLimit; + final int oldLimit = sizeLimit; sizeLimit = limit; return oldLimit; } @@ -594,7 +560,7 @@ public final class CodedInputStream { throw InvalidProtocolBufferException.negativeSize(); } byteLimit += totalBytesRetired + bufferPos; - int oldLimit = currentLimit; + final int oldLimit = currentLimit; if (byteLimit > oldLimit) { throw InvalidProtocolBufferException.truncatedMessage(); } @@ -607,7 +573,7 @@ public final class CodedInputStream { private void recomputeBufferSizeAfterLimit() { bufferSize += bufferSizeAfterLimit; - int bufferEnd = totalBytesRetired + bufferSize; + final int bufferEnd = totalBytesRetired + bufferSize; if (bufferEnd > currentLimit) { // Limit is in current buffer. bufferSizeAfterLimit = bufferEnd - currentLimit; @@ -622,7 +588,7 @@ public final class CodedInputStream { * * @param oldLimit The old limit, as returned by {@code pushLimit}. */ - public void popLimit(int oldLimit) { + public void popLimit(final int oldLimit) { currentLimit = oldLimit; recomputeBufferSizeAfterLimit(); } @@ -636,7 +602,7 @@ public final class CodedInputStream { return -1; } - int currentAbsolutePosition = totalBytesRetired + bufferPos; + final int currentAbsolutePosition = totalBytesRetired + bufferPos; return currentLimit - currentAbsolutePosition; } @@ -656,7 +622,7 @@ public final class CodedInputStream { * or it will throw an exception. If {@code mustSucceed} is false, * refillBuffer() returns false if no more bytes were available. */ - private boolean refillBuffer(boolean mustSucceed) throws IOException { + private boolean refillBuffer(final boolean mustSucceed) throws IOException { if (bufferPos < bufferSize) { throw new IllegalStateException( "refillBuffer() called when buffer wasn't empty."); @@ -689,7 +655,7 @@ public final class CodedInputStream { } } else { recomputeBufferSizeAfterLimit(); - int totalBytesRead = + final int totalBytesRead = totalBytesRetired + bufferSize + bufferSizeAfterLimit; if (totalBytesRead > sizeLimit || totalBytesRead < 0) { throw InvalidProtocolBufferException.sizeLimitExceeded(); @@ -717,7 +683,7 @@ public final class CodedInputStream { * @throws InvalidProtocolBufferException The end of the stream or the current * limit was reached. */ - public byte[] readRawBytes(int size) throws IOException { + public byte[] readRawBytes(final int size) throws IOException { if (size < 0) { throw InvalidProtocolBufferException.negativeSize(); } @@ -731,7 +697,7 @@ public final class CodedInputStream { if (size <= bufferSize - bufferPos) { // We have all the bytes we need already. - byte[] bytes = new byte[size]; + final byte[] bytes = new byte[size]; System.arraycopy(buffer, bufferPos, bytes, 0, size); bufferPos += size; return bytes; @@ -740,7 +706,7 @@ public final class CodedInputStream { // of bytes. We can safely allocate the resulting array ahead of time. // First copy what we have. - byte[] bytes = new byte[size]; + final byte[] bytes = new byte[size]; int pos = bufferSize - bufferPos; System.arraycopy(buffer, bufferPos, bytes, 0, pos); bufferPos = bufferSize; @@ -772,8 +738,8 @@ public final class CodedInputStream { // Remember the buffer markers since we'll have to copy the bytes out of // it later. - int originalBufferPos = bufferPos; - int originalBufferSize = bufferSize; + final int originalBufferPos = bufferPos; + final int originalBufferSize = bufferSize; // Mark the current buffer consumed. totalBytesRetired += bufferSize; @@ -782,13 +748,13 @@ public final class CodedInputStream { // Read all the rest of the bytes we need. int sizeLeft = size - (originalBufferSize - originalBufferPos); - List chunks = new ArrayList(); + final List chunks = new ArrayList(); while (sizeLeft > 0) { - byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)]; + final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)]; int pos = 0; while (pos < chunk.length) { - int n = (input == null) ? -1 : + final int n = (input == null) ? -1 : input.read(chunk, pos, chunk.length - pos); if (n == -1) { throw InvalidProtocolBufferException.truncatedMessage(); @@ -801,14 +767,14 @@ public final class CodedInputStream { } // OK, got everything. Now concatenate it all into one buffer. - byte[] bytes = new byte[size]; + final byte[] bytes = new byte[size]; // Start by copying the leftover bytes from this.buffer. int pos = originalBufferSize - originalBufferPos; System.arraycopy(buffer, originalBufferPos, bytes, 0, pos); // And now all the chunks. - for (byte[] chunk : chunks) { + for (final byte[] chunk : chunks) { System.arraycopy(chunk, 0, bytes, pos, chunk.length); pos += chunk.length; } @@ -824,7 +790,7 @@ public final class CodedInputStream { * @throws InvalidProtocolBufferException The end of the stream or the current * limit was reached. */ - public void skipRawBytes(int size) throws IOException { + public void skipRawBytes(final int size) throws IOException { if (size < 0) { throw InvalidProtocolBufferException.negativeSize(); } @@ -848,7 +814,7 @@ public final class CodedInputStream { // Then skip directly from the InputStream for the rest. while (pos < size) { - int n = (input == null) ? -1 : (int) input.skip(size - pos); + final int n = (input == null) ? -1 : (int) input.skip(size - pos); if (n <= 0) { throw InvalidProtocolBufferException.truncatedMessage(); } diff --git a/java/src/main/java/com/google/protobuf/CodedOutputStream.java b/java/src/main/java/com/google/protobuf/CodedOutputStream.java index 69c22d89..d3907a7c 100644 --- a/java/src/main/java/com/google/protobuf/CodedOutputStream.java +++ b/java/src/main/java/com/google/protobuf/CodedOutputStream.java @@ -32,6 +32,7 @@ package com.google.protobuf; import java.io.OutputStream; import java.io.IOException; +import java.io.UnsupportedEncodingException; /** * Encodes and writes protocol message fields. @@ -55,29 +56,30 @@ public final class CodedOutputStream { private final OutputStream output; /** - * The buffer size used in {@link #newInstance(java.io.OutputStream)}. + * The buffer size used in {@link #newInstance(OutputStream)}. */ public static final int DEFAULT_BUFFER_SIZE = 4096; - private CodedOutputStream(byte[] buffer, int offset, int length) { - this.output = null; + private CodedOutputStream(final byte[] buffer, final int offset, + final int length) { + output = null; this.buffer = buffer; - this.position = offset; - this.limit = offset + length; + position = offset; + limit = offset + length; } - private CodedOutputStream(OutputStream output, byte[] buffer) { + private CodedOutputStream(final OutputStream output, final byte[] buffer) { this.output = output; this.buffer = buffer; - this.position = 0; - this.limit = buffer.length; + position = 0; + limit = buffer.length; } /** * Create a new {@code CodedOutputStream} wrapping the given * {@code OutputStream}. */ - public static CodedOutputStream newInstance(OutputStream output) { + public static CodedOutputStream newInstance(final OutputStream output) { return newInstance(output, DEFAULT_BUFFER_SIZE); } @@ -85,8 +87,8 @@ public final class CodedOutputStream { * Create a new {@code CodedOutputStream} wrapping the given * {@code OutputStream} with a given buffer size. */ - public static CodedOutputStream newInstance(OutputStream output, - int bufferSize) { + public static CodedOutputStream newInstance(final OutputStream output, + final int bufferSize) { return new CodedOutputStream(output, new byte[bufferSize]); } @@ -97,7 +99,7 @@ public final class CodedOutputStream { * array is faster than writing to an {@code OutputStream}. See also * {@link ByteString#newCodedBuilder}. */ - public static CodedOutputStream newInstance(byte[] flatArray) { + public static CodedOutputStream newInstance(final byte[] flatArray) { return newInstance(flatArray, 0, flatArray.length); } @@ -108,96 +110,115 @@ public final class CodedOutputStream { * array is faster than writing to an {@code OutputStream}. See also * {@link ByteString#newCodedBuilder}. */ - public static CodedOutputStream newInstance(byte[] flatArray, int offset, - int length) { + public static CodedOutputStream newInstance(final byte[] flatArray, + final int offset, + final int length) { return new CodedOutputStream(flatArray, offset, length); } // ----------------------------------------------------------------- /** Write a {@code double} field, including tag, to the stream. */ - public void writeDouble(int fieldNumber, double value) throws IOException { + public void writeDouble(final int fieldNumber, final double value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); writeDoubleNoTag(value); } /** Write a {@code float} field, including tag, to the stream. */ - public void writeFloat(int fieldNumber, float value) throws IOException { + public void writeFloat(final int fieldNumber, final float value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); writeFloatNoTag(value); } /** Write a {@code uint64} field, including tag, to the stream. */ - public void writeUInt64(int fieldNumber, long value) throws IOException { + public void writeUInt64(final int fieldNumber, final long value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); writeUInt64NoTag(value); } /** Write an {@code int64} field, including tag, to the stream. */ - public void writeInt64(int fieldNumber, long value) throws IOException { + public void writeInt64(final int fieldNumber, final long value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); writeInt64NoTag(value); } /** Write an {@code int32} field, including tag, to the stream. */ - public void writeInt32(int fieldNumber, int value) throws IOException { + public void writeInt32(final int fieldNumber, final int value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); writeInt32NoTag(value); } /** Write a {@code fixed64} field, including tag, to the stream. */ - public void writeFixed64(int fieldNumber, long value) throws IOException { + public void writeFixed64(final int fieldNumber, final long value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); writeFixed64NoTag(value); } /** Write a {@code fixed32} field, including tag, to the stream. */ - public void writeFixed32(int fieldNumber, int value) throws IOException { + public void writeFixed32(final int fieldNumber, final int value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); writeFixed32NoTag(value); } /** Write a {@code bool} field, including tag, to the stream. */ - public void writeBool(int fieldNumber, boolean value) throws IOException { + public void writeBool(final int fieldNumber, final boolean value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); writeBoolNoTag(value); } /** Write a {@code string} field, including tag, to the stream. */ - public void writeString(int fieldNumber, String value) throws IOException { + public void writeString(final int fieldNumber, final String value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); writeStringNoTag(value); } /** Write a {@code group} field, including tag, to the stream. */ - public void writeGroup(int fieldNumber, Message value) throws IOException { + public void writeGroup(final int fieldNumber, final MessageLite value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP); writeGroupNoTag(value); writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP); } - /** Write a group represented by an {@link UnknownFieldSet}. */ - public void writeUnknownGroup(int fieldNumber, UnknownFieldSet value) - throws IOException { - writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP); - writeUnknownGroupNoTag(value); - writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP); + /** + * Write a group represented by an {@link UnknownFieldSet}. + * + * @deprecated UnknownFieldSet now implements MessageLite, so you can just + * call {@link #writeGroup}. + */ + @Deprecated + public void writeUnknownGroup(final int fieldNumber, + final MessageLite value) + throws IOException { + writeGroup(fieldNumber, value); } /** Write an embedded message field, including tag, to the stream. */ - public void writeMessage(int fieldNumber, Message value) throws IOException { + public void writeMessage(final int fieldNumber, final MessageLite value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); writeMessageNoTag(value); } /** Write a {@code bytes} field, including tag, to the stream. */ - public void writeBytes(int fieldNumber, ByteString value) throws IOException { + public void writeBytes(final int fieldNumber, final ByteString value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); writeBytesNoTag(value); } /** Write a {@code uint32} field, including tag, to the stream. */ - public void writeUInt32(int fieldNumber, int value) throws IOException { + public void writeUInt32(final int fieldNumber, final int value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); writeUInt32NoTag(value); } @@ -206,31 +227,36 @@ public final class CodedOutputStream { * Write an enum field, including tag, to the stream. Caller is responsible * for converting the enum value to its numeric value. */ - public void writeEnum(int fieldNumber, int value) throws IOException { + public void writeEnum(final int fieldNumber, final int value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); writeEnumNoTag(value); } /** Write an {@code sfixed32} field, including tag, to the stream. */ - public void writeSFixed32(int fieldNumber, int value) throws IOException { + public void writeSFixed32(final int fieldNumber, final int value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); writeSFixed32NoTag(value); } /** Write an {@code sfixed64} field, including tag, to the stream. */ - public void writeSFixed64(int fieldNumber, long value) throws IOException { + public void writeSFixed64(final int fieldNumber, final long value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); writeSFixed64NoTag(value); } /** Write an {@code sint32} field, including tag, to the stream. */ - public void writeSInt32(int fieldNumber, int value) throws IOException { + public void writeSInt32(final int fieldNumber, final int value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); writeSInt32NoTag(value); } /** Write an {@code sint64} field, including tag, to the stream. */ - public void writeSInt64(int fieldNumber, long value) throws IOException { + public void writeSInt64(final int fieldNumber, final long value) + throws IOException { writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); writeSInt64NoTag(value); } @@ -239,8 +265,9 @@ public final class CodedOutputStream { * Write a MessageSet extension field to the stream. For historical reasons, * the wire format differs from normal fields. */ - public void writeMessageSetExtension(int fieldNumber, Message value) - throws IOException { + public void writeMessageSetExtension(final int fieldNumber, + final MessageLite value) + throws IOException { writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value); @@ -251,7 +278,8 @@ public final class CodedOutputStream { * Write an unparsed MessageSet extension field to the stream. For * historical reasons, the wire format differs from normal fields. */ - public void writeRawMessageSetExtension(int fieldNumber, ByteString value) + public void writeRawMessageSetExtension(final int fieldNumber, + final ByteString value) throws IOException { writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); @@ -259,89 +287,30 @@ public final class CodedOutputStream { writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); } - /** - * Write a field of arbitrary type, including tag, to the stream. - * - * @param type The field's type. - * @param number The field's number. - * @param value Object representing the field's value. Must be of the exact - * type which would be returned by - * {@link Message#getField(Descriptors.FieldDescriptor)} for - * this field. - */ - public void writeField(Descriptors.FieldDescriptor.Type type, - int number, - Object value) throws IOException { - // Special case for groups, which need a start and end tag; other fields - // can just use writeTag() and writeFieldNoTag(). - if (type == Descriptors.FieldDescriptor.Type.GROUP) { - writeGroup(number, (Message) value); - } else { - writeTag(number, WireFormat.getWireFormatForFieldType(type)); - writeFieldNoTag(type, value); - } - } - - /** - * Write a field of arbitrary type, without its tag, to the stream. - * - * @param type The field's type. - * @param value Object representing the field's value. Must be of the exact - * type which would be returned by - * {@link Message#getField(Descriptors.FieldDescriptor)} for - * this field. - */ - public void writeFieldNoTag(Descriptors.FieldDescriptor.Type type, - Object value) throws IOException { - switch (type) { - case DOUBLE : writeDoubleNoTag ((Double ) value); break; - case FLOAT : writeFloatNoTag ((Float ) value); break; - case INT64 : writeInt64NoTag ((Long ) value); break; - case UINT64 : writeUInt64NoTag ((Long ) value); break; - case INT32 : writeInt32NoTag ((Integer ) value); break; - case FIXED64 : writeFixed64NoTag ((Long ) value); break; - case FIXED32 : writeFixed32NoTag ((Integer ) value); break; - case BOOL : writeBoolNoTag ((Boolean ) value); break; - case STRING : writeStringNoTag ((String ) value); break; - case GROUP : writeGroupNoTag ((Message ) value); break; - case MESSAGE : writeMessageNoTag ((Message ) value); break; - case BYTES : writeBytesNoTag ((ByteString) value); break; - case UINT32 : writeUInt32NoTag ((Integer ) value); break; - case SFIXED32: writeSFixed32NoTag((Integer ) value); break; - case SFIXED64: writeSFixed64NoTag((Long ) value); break; - case SINT32 : writeSInt32NoTag ((Integer ) value); break; - case SINT64 : writeSInt64NoTag ((Long ) value); break; - - case ENUM: - writeEnumNoTag(((Descriptors.EnumValueDescriptor) value).getNumber()); - break; - } - } - // ----------------------------------------------------------------- /** Write a {@code double} field to the stream. */ - public void writeDoubleNoTag(double value) throws IOException { + public void writeDoubleNoTag(final double value) throws IOException { writeRawLittleEndian64(Double.doubleToRawLongBits(value)); } /** Write a {@code float} field to the stream. */ - public void writeFloatNoTag(float value) throws IOException { + public void writeFloatNoTag(final float value) throws IOException { writeRawLittleEndian32(Float.floatToRawIntBits(value)); } /** Write a {@code uint64} field to the stream. */ - public void writeUInt64NoTag(long value) throws IOException { + public void writeUInt64NoTag(final long value) throws IOException { writeRawVarint64(value); } /** Write an {@code int64} field to the stream. */ - public void writeInt64NoTag(long value) throws IOException { + public void writeInt64NoTag(final long value) throws IOException { writeRawVarint64(value); } /** Write an {@code int32} field to the stream. */ - public void writeInt32NoTag(int value) throws IOException { + public void writeInt32NoTag(final int value) throws IOException { if (value >= 0) { writeRawVarint32(value); } else { @@ -351,56 +320,62 @@ public final class CodedOutputStream { } /** Write a {@code fixed64} field to the stream. */ - public void writeFixed64NoTag(long value) throws IOException { + public void writeFixed64NoTag(final long value) throws IOException { writeRawLittleEndian64(value); } /** Write a {@code fixed32} field to the stream. */ - public void writeFixed32NoTag(int value) throws IOException { + public void writeFixed32NoTag(final int value) throws IOException { writeRawLittleEndian32(value); } /** Write a {@code bool} field to the stream. */ - public void writeBoolNoTag(boolean value) throws IOException { + public void writeBoolNoTag(final boolean value) throws IOException { writeRawByte(value ? 1 : 0); } /** Write a {@code string} field to the stream. */ - public void writeStringNoTag(String value) throws IOException { + public void writeStringNoTag(final String value) throws IOException { // Unfortunately there does not appear to be any way to tell Java to encode // UTF-8 directly into our buffer, so we have to let it create its own byte // array and then copy. - byte[] bytes = value.getBytes("UTF-8"); + final byte[] bytes = value.getBytes("UTF-8"); writeRawVarint32(bytes.length); writeRawBytes(bytes); } /** Write a {@code group} field to the stream. */ - public void writeGroupNoTag(Message value) throws IOException { + public void writeGroupNoTag(final MessageLite value) throws IOException { value.writeTo(this); } - /** Write a group represented by an {@link UnknownFieldSet}. */ - public void writeUnknownGroupNoTag(UnknownFieldSet value) + /** + * Write a group represented by an {@link UnknownFieldSet}. + * + * @deprecated UnknownFieldSet now implements MessageLite, so you can just + * call {@link #writeGroupNoTag}. + */ + @Deprecated + public void writeUnknownGroupNoTag(final MessageLite value) throws IOException { - value.writeTo(this); + writeGroupNoTag(value); } /** Write an embedded message field to the stream. */ - public void writeMessageNoTag(Message value) throws IOException { + public void writeMessageNoTag(final MessageLite value) throws IOException { writeRawVarint32(value.getSerializedSize()); value.writeTo(this); } /** Write a {@code bytes} field to the stream. */ - public void writeBytesNoTag(ByteString value) throws IOException { - byte[] bytes = value.toByteArray(); + public void writeBytesNoTag(final ByteString value) throws IOException { + final byte[] bytes = value.toByteArray(); writeRawVarint32(bytes.length); writeRawBytes(bytes); } /** Write a {@code uint32} field to the stream. */ - public void writeUInt32NoTag(int value) throws IOException { + public void writeUInt32NoTag(final int value) throws IOException { writeRawVarint32(value); } @@ -408,27 +383,27 @@ public final class CodedOutputStream { * Write an enum field to the stream. Caller is responsible * for converting the enum value to its numeric value. */ - public void writeEnumNoTag(int value) throws IOException { + public void writeEnumNoTag(final int value) throws IOException { writeRawVarint32(value); } /** Write an {@code sfixed32} field to the stream. */ - public void writeSFixed32NoTag(int value) throws IOException { + public void writeSFixed32NoTag(final int value) throws IOException { writeRawLittleEndian32(value); } /** Write an {@code sfixed64} field to the stream. */ - public void writeSFixed64NoTag(long value) throws IOException { + public void writeSFixed64NoTag(final long value) throws IOException { writeRawLittleEndian64(value); } /** Write an {@code sint32} field to the stream. */ - public void writeSInt32NoTag(int value) throws IOException { + public void writeSInt32NoTag(final int value) throws IOException { writeRawVarint32(encodeZigZag32(value)); } /** Write an {@code sint64} field to the stream. */ - public void writeSInt64NoTag(long value) throws IOException { + public void writeSInt64NoTag(final long value) throws IOException { writeRawVarint64(encodeZigZag64(value)); } @@ -438,7 +413,8 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code double} field, including tag. */ - public static int computeDoubleSize(int fieldNumber, double value) { + public static int computeDoubleSize(final int fieldNumber, + final double value) { return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value); } @@ -446,7 +422,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code float} field, including tag. */ - public static int computeFloatSize(int fieldNumber, float value) { + public static int computeFloatSize(final int fieldNumber, final float value) { return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value); } @@ -454,7 +430,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code uint64} field, including tag. */ - public static int computeUInt64Size(int fieldNumber, long value) { + public static int computeUInt64Size(final int fieldNumber, final long value) { return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value); } @@ -462,7 +438,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode an * {@code int64} field, including tag. */ - public static int computeInt64Size(int fieldNumber, long value) { + public static int computeInt64Size(final int fieldNumber, final long value) { return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value); } @@ -470,7 +446,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode an * {@code int32} field, including tag. */ - public static int computeInt32Size(int fieldNumber, int value) { + public static int computeInt32Size(final int fieldNumber, final int value) { return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value); } @@ -478,7 +454,8 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code fixed64} field, including tag. */ - public static int computeFixed64Size(int fieldNumber, long value) { + public static int computeFixed64Size(final int fieldNumber, + final long value) { return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value); } @@ -486,7 +463,8 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code fixed32} field, including tag. */ - public static int computeFixed32Size(int fieldNumber, int value) { + public static int computeFixed32Size(final int fieldNumber, + final int value) { return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value); } @@ -494,7 +472,8 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code bool} field, including tag. */ - public static int computeBoolSize(int fieldNumber, boolean value) { + public static int computeBoolSize(final int fieldNumber, + final boolean value) { return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value); } @@ -502,7 +481,8 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code string} field, including tag. */ - public static int computeStringSize(int fieldNumber, String value) { + public static int computeStringSize(final int fieldNumber, + final String value) { return computeTagSize(fieldNumber) + computeStringSizeNoTag(value); } @@ -510,7 +490,8 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code group} field, including tag. */ - public static int computeGroupSize(int fieldNumber, Message value) { + public static int computeGroupSize(final int fieldNumber, + final MessageLite value) { return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value); } @@ -518,18 +499,22 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code group} field represented by an {@code UnknownFieldSet}, including * tag. + * + * @deprecated UnknownFieldSet now implements MessageLite, so you can just + * call {@link #computeGroupSize}. */ - public static int computeUnknownGroupSize(int fieldNumber, - UnknownFieldSet value) { - return computeTagSize(fieldNumber) * 2 + - computeUnknownGroupSizeNoTag(value); + @Deprecated + public static int computeUnknownGroupSize(final int fieldNumber, + final MessageLite value) { + return computeGroupSize(fieldNumber, value); } /** * Compute the number of bytes that would be needed to encode an * embedded message field, including tag. */ - public static int computeMessageSize(int fieldNumber, Message value) { + public static int computeMessageSize(final int fieldNumber, + final MessageLite value) { return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value); } @@ -537,7 +522,8 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code bytes} field, including tag. */ - public static int computeBytesSize(int fieldNumber, ByteString value) { + public static int computeBytesSize(final int fieldNumber, + final ByteString value) { return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value); } @@ -545,7 +531,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code uint32} field, including tag. */ - public static int computeUInt32Size(int fieldNumber, int value) { + public static int computeUInt32Size(final int fieldNumber, final int value) { return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value); } @@ -554,7 +540,7 @@ public final class CodedOutputStream { * enum field, including tag. Caller is responsible for converting the * enum value to its numeric value. */ - public static int computeEnumSize(int fieldNumber, int value) { + public static int computeEnumSize(final int fieldNumber, final int value) { return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value); } @@ -562,7 +548,8 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode an * {@code sfixed32} field, including tag. */ - public static int computeSFixed32Size(int fieldNumber, int value) { + public static int computeSFixed32Size(final int fieldNumber, + final int value) { return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value); } @@ -570,7 +557,8 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode an * {@code sfixed64} field, including tag. */ - public static int computeSFixed64Size(int fieldNumber, long value) { + public static int computeSFixed64Size(final int fieldNumber, + final long value) { return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value); } @@ -578,7 +566,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode an * {@code sint32} field, including tag. */ - public static int computeSInt32Size(int fieldNumber, int value) { + public static int computeSInt32Size(final int fieldNumber, final int value) { return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value); } @@ -586,7 +574,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode an * {@code sint64} field, including tag. */ - public static int computeSInt64Size(int fieldNumber, long value) { + public static int computeSInt64Size(final int fieldNumber, final long value) { return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value); } @@ -596,7 +584,7 @@ public final class CodedOutputStream { * the wire format differs from normal fields. */ public static int computeMessageSetExtensionSize( - int fieldNumber, Message value) { + final int fieldNumber, final MessageLite value) { return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) + computeMessageSize(WireFormat.MESSAGE_SET_MESSAGE, value); @@ -608,7 +596,7 @@ public final class CodedOutputStream { * historical reasons, the wire format differs from normal fields. */ public static int computeRawMessageSetExtensionSize( - int fieldNumber, ByteString value) { + final int fieldNumber, final ByteString value) { return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) + computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value); @@ -620,7 +608,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code double} field, including tag. */ - public static int computeDoubleSizeNoTag(double value) { + public static int computeDoubleSizeNoTag(final double value) { return LITTLE_ENDIAN_64_SIZE; } @@ -628,7 +616,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code float} field, including tag. */ - public static int computeFloatSizeNoTag(float value) { + public static int computeFloatSizeNoTag(final float value) { return LITTLE_ENDIAN_32_SIZE; } @@ -636,7 +624,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code uint64} field, including tag. */ - public static int computeUInt64SizeNoTag(long value) { + public static int computeUInt64SizeNoTag(final long value) { return computeRawVarint64Size(value); } @@ -644,7 +632,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode an * {@code int64} field, including tag. */ - public static int computeInt64SizeNoTag(long value) { + public static int computeInt64SizeNoTag(final long value) { return computeRawVarint64Size(value); } @@ -652,7 +640,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode an * {@code int32} field, including tag. */ - public static int computeInt32SizeNoTag(int value) { + public static int computeInt32SizeNoTag(final int value) { if (value >= 0) { return computeRawVarint32Size(value); } else { @@ -665,7 +653,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code fixed64} field. */ - public static int computeFixed64SizeNoTag(long value) { + public static int computeFixed64SizeNoTag(final long value) { return LITTLE_ENDIAN_64_SIZE; } @@ -673,7 +661,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code fixed32} field. */ - public static int computeFixed32SizeNoTag(int value) { + public static int computeFixed32SizeNoTag(final int value) { return LITTLE_ENDIAN_32_SIZE; } @@ -681,7 +669,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code bool} field. */ - public static int computeBoolSizeNoTag(boolean value) { + public static int computeBoolSizeNoTag(final boolean value) { return 1; } @@ -689,12 +677,12 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code string} field. */ - public static int computeStringSizeNoTag(String value) { + public static int computeStringSizeNoTag(final String value) { try { - byte[] bytes = value.getBytes("UTF-8"); + final byte[] bytes = value.getBytes("UTF-8"); return computeRawVarint32Size(bytes.length) + bytes.length; - } catch (java.io.UnsupportedEncodingException e) { + } catch (UnsupportedEncodingException e) { throw new RuntimeException("UTF-8 not supported.", e); } } @@ -703,7 +691,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code group} field. */ - public static int computeGroupSizeNoTag(Message value) { + public static int computeGroupSizeNoTag(final MessageLite value) { return value.getSerializedSize(); } @@ -711,17 +699,21 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code group} field represented by an {@code UnknownFieldSet}, including * tag. + * + * @deprecated UnknownFieldSet now implements MessageLite, so you can just + * call {@link #computeUnknownGroupSizeNoTag}. */ - public static int computeUnknownGroupSizeNoTag(UnknownFieldSet value) { - return value.getSerializedSize(); + @Deprecated + public static int computeUnknownGroupSizeNoTag(final MessageLite value) { + return computeGroupSizeNoTag(value); } /** * Compute the number of bytes that would be needed to encode an embedded * message field. */ - public static int computeMessageSizeNoTag(Message value) { - int size = value.getSerializedSize(); + public static int computeMessageSizeNoTag(final MessageLite value) { + final int size = value.getSerializedSize(); return computeRawVarint32Size(size) + size; } @@ -729,7 +721,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code bytes} field. */ - public static int computeBytesSizeNoTag(ByteString value) { + public static int computeBytesSizeNoTag(final ByteString value) { return computeRawVarint32Size(value.size()) + value.size(); } @@ -738,15 +730,15 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode a * {@code uint32} field. */ - public static int computeUInt32SizeNoTag(int value) { + public static int computeUInt32SizeNoTag(final int value) { return computeRawVarint32Size(value); } /** - * Compute the number of bytes that would be needed to encode an enum field. + * Compute the number of bytes that would be needed to encode an enum field. * Caller is responsible for converting the enum value to its numeric value. */ - public static int computeEnumSizeNoTag(int value) { + public static int computeEnumSizeNoTag(final int value) { return computeRawVarint32Size(value); } @@ -754,7 +746,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode an * {@code sfixed32} field. */ - public static int computeSFixed32SizeNoTag(int value) { + public static int computeSFixed32SizeNoTag(final int value) { return LITTLE_ENDIAN_32_SIZE; } @@ -762,7 +754,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode an * {@code sfixed64} field. */ - public static int computeSFixed64SizeNoTag(long value) { + public static int computeSFixed64SizeNoTag(final long value) { return LITTLE_ENDIAN_64_SIZE; } @@ -770,7 +762,7 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode an * {@code sint32} field. */ - public static int computeSInt32SizeNoTag(int value) { + public static int computeSInt32SizeNoTag(final int value) { return computeRawVarint32Size(encodeZigZag32(value)); } @@ -778,71 +770,10 @@ public final class CodedOutputStream { * Compute the number of bytes that would be needed to encode an * {@code sint64} field. */ - public static int computeSInt64SizeNoTag(long value) { + public static int computeSInt64SizeNoTag(final long value) { return computeRawVarint64Size(encodeZigZag64(value)); } - /** - * Compute the number of bytes that would be needed to encode a - * field of arbitrary type, including tag, to the stream. - * - * @param type The field's type. - * @param number The field's number. - * @param value Object representing the field's value. Must be of the exact - * type which would be returned by - * {@link Message#getField(Descriptors.FieldDescriptor)} for - * this field. - */ - public static int computeFieldSize( - Descriptors.FieldDescriptor.Type type, - int number, Object value) { - int tagSize = computeTagSize(number); - if (type == Descriptors.FieldDescriptor.Type.GROUP) { - tagSize *= 2; - } - return tagSize + computeFieldSizeNoTag(type, value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * field of arbitrary type, excluding tag, to the stream. - * - * @param type The field's type. - * @param value Object representing the field's value. Must be of the exact - * type which would be returned by - * {@link Message#getField(Descriptors.FieldDescriptor)} for - * this field. - */ - public static int computeFieldSizeNoTag( - Descriptors.FieldDescriptor.Type type, Object value) { - switch (type) { - case DOUBLE : return computeDoubleSizeNoTag ((Double )value); - case FLOAT : return computeFloatSizeNoTag ((Float )value); - case INT64 : return computeInt64SizeNoTag ((Long )value); - case UINT64 : return computeUInt64SizeNoTag ((Long )value); - case INT32 : return computeInt32SizeNoTag ((Integer )value); - case FIXED64 : return computeFixed64SizeNoTag ((Long )value); - case FIXED32 : return computeFixed32SizeNoTag ((Integer )value); - case BOOL : return computeBoolSizeNoTag ((Boolean )value); - case STRING : return computeStringSizeNoTag ((String )value); - case GROUP : return computeGroupSizeNoTag ((Message )value); - case MESSAGE : return computeMessageSizeNoTag ((Message )value); - case BYTES : return computeBytesSizeNoTag ((ByteString)value); - case UINT32 : return computeUInt32SizeNoTag ((Integer )value); - case SFIXED32: return computeSFixed32SizeNoTag((Integer )value); - case SFIXED64: return computeSFixed64SizeNoTag((Long )value); - case SINT32 : return computeSInt32SizeNoTag ((Integer )value); - case SINT64 : return computeSInt64SizeNoTag ((Long )value); - - case ENUM: - return computeEnumSizeNoTag( - ((Descriptors.EnumValueDescriptor)value).getNumber()); - } - - throw new RuntimeException( - "There is no way to get here, but the compiler thinks otherwise."); - } - // ================================================================= /** @@ -905,6 +836,8 @@ public final class CodedOutputStream { * this exception will be thrown. */ public static class OutOfSpaceException extends IOException { + private static final long serialVersionUID = -6947486886997889499L; + OutOfSpaceException() { super("CodedOutputStream was writing to a flat byte array and ran " + "out of space."); @@ -912,7 +845,7 @@ public final class CodedOutputStream { } /** Write a single byte. */ - public void writeRawByte(byte value) throws IOException { + public void writeRawByte(final byte value) throws IOException { if (position == limit) { refreshBuffer(); } @@ -921,17 +854,17 @@ public final class CodedOutputStream { } /** Write a single byte, represented by an integer value. */ - public void writeRawByte(int value) throws IOException { + public void writeRawByte(final int value) throws IOException { writeRawByte((byte) value); } /** Write an array of bytes. */ - public void writeRawBytes(byte[] value) throws IOException { + public void writeRawBytes(final byte[] value) throws IOException { writeRawBytes(value, 0, value.length); } /** Write part of an array of bytes. */ - public void writeRawBytes(byte[] value, int offset, int length) + public void writeRawBytes(final byte[] value, int offset, int length) throws IOException { if (limit - position >= length) { // We have room in the current buffer. @@ -940,7 +873,7 @@ public final class CodedOutputStream { } else { // Write extends past current buffer. Fill the rest of this buffer and // flush. - int bytesWritten = limit - position; + final int bytesWritten = limit - position; System.arraycopy(value, offset, buffer, position, bytesWritten); offset += bytesWritten; length -= bytesWritten; @@ -962,12 +895,13 @@ public final class CodedOutputStream { } /** Encode and write a tag. */ - public void writeTag(int fieldNumber, int wireType) throws IOException { + public void writeTag(final int fieldNumber, final int wireType) + throws IOException { writeRawVarint32(WireFormat.makeTag(fieldNumber, wireType)); } /** Compute the number of bytes that would be needed to encode a tag. */ - public static int computeTagSize(int fieldNumber) { + public static int computeTagSize(final int fieldNumber) { return computeRawVarint32Size(WireFormat.makeTag(fieldNumber, 0)); } @@ -992,7 +926,7 @@ public final class CodedOutputStream { * {@code value} is treated as unsigned, so it won't be sign-extended if * negative. */ - public static int computeRawVarint32Size(int value) { + public static int computeRawVarint32Size(final int value) { if ((value & (0xffffffff << 7)) == 0) return 1; if ((value & (0xffffffff << 14)) == 0) return 2; if ((value & (0xffffffff << 21)) == 0) return 3; @@ -1014,7 +948,7 @@ public final class CodedOutputStream { } /** Compute the number of bytes that would be needed to encode a varint. */ - public static int computeRawVarint64Size(long value) { + public static int computeRawVarint64Size(final long value) { if ((value & (0xffffffffffffffffL << 7)) == 0) return 1; if ((value & (0xffffffffffffffffL << 14)) == 0) return 2; if ((value & (0xffffffffffffffffL << 21)) == 0) return 3; @@ -1028,7 +962,7 @@ public final class CodedOutputStream { } /** Write a little-endian 32-bit integer. */ - public void writeRawLittleEndian32(int value) throws IOException { + public void writeRawLittleEndian32(final int value) throws IOException { writeRawByte((value ) & 0xFF); writeRawByte((value >> 8) & 0xFF); writeRawByte((value >> 16) & 0xFF); @@ -1038,7 +972,7 @@ public final class CodedOutputStream { public static final int LITTLE_ENDIAN_32_SIZE = 4; /** Write a little-endian 64-bit integer. */ - public void writeRawLittleEndian64(long value) throws IOException { + public void writeRawLittleEndian64(final long value) throws IOException { writeRawByte((int)(value ) & 0xFF); writeRawByte((int)(value >> 8) & 0xFF); writeRawByte((int)(value >> 16) & 0xFF); @@ -1061,7 +995,7 @@ public final class CodedOutputStream { * @return An unsigned 32-bit integer, stored in a signed int because * Java has no explicit unsigned support. */ - public static int encodeZigZag32(int n) { + public static int encodeZigZag32(final int n) { // Note: the right-shift must be arithmetic return (n << 1) ^ (n >> 31); } @@ -1076,7 +1010,7 @@ public final class CodedOutputStream { * @return An unsigned 64-bit integer, stored in a signed int because * Java has no explicit unsigned support. */ - public static long encodeZigZag64(long n) { + public static long encodeZigZag64(final long n) { // Note: the right-shift must be arithmetic return (n << 1) ^ (n >> 63); } diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java index 24499efb..0d5e47d1 100644 --- a/java/src/main/java/com/google/protobuf/Descriptors.java +++ b/java/src/main/java/com/google/protobuf/Descriptors.java @@ -37,11 +37,12 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.io.UnsupportedEncodingException; /** * Contains a collection of classes which describe protocol message types. * - * Every message type has a {@link Descriptors.Descriptor}, which lists all + * Every message type has a {@link Descriptor}, which lists all * its fields and other information about a type. You can get a message * type's descriptor by calling {@code MessageType.getDescriptor()}, or * (given a message object of the type) {@code message.getDescriptorForType()}. @@ -106,11 +107,13 @@ public final class Descriptors { public Descriptor findMessageTypeByName(String name) { // Don't allow looking up nested types. This will make optimization // easier later. - if (name.indexOf('.') != -1) return null; + if (name.indexOf('.') != -1) { + return null; + } if (getPackage().length() > 0) { - name = getPackage() + "." + name; + name = getPackage() + '.' + name; } - GenericDescriptor result = pool.findSymbol(name); + final GenericDescriptor result = pool.findSymbol(name); if (result != null && result instanceof Descriptor && result.getFile() == this) { return (Descriptor)result; @@ -128,11 +131,13 @@ public final class Descriptors { public EnumDescriptor findEnumTypeByName(String name) { // Don't allow looking up nested types. This will make optimization // easier later. - if (name.indexOf('.') != -1) return null; + if (name.indexOf('.') != -1) { + return null; + } if (getPackage().length() > 0) { - name = getPackage() + "." + name; + name = getPackage() + '.' + name; } - GenericDescriptor result = pool.findSymbol(name); + final GenericDescriptor result = pool.findSymbol(name); if (result != null && result instanceof EnumDescriptor && result.getFile() == this) { return (EnumDescriptor)result; @@ -150,11 +155,13 @@ public final class Descriptors { public ServiceDescriptor findServiceByName(String name) { // Don't allow looking up nested types. This will make optimization // easier later. - if (name.indexOf('.') != -1) return null; + if (name.indexOf('.') != -1) { + return null; + } if (getPackage().length() > 0) { - name = getPackage() + "." + name; + name = getPackage() + '.' + name; } - GenericDescriptor result = pool.findSymbol(name); + final GenericDescriptor result = pool.findSymbol(name); if (result != null && result instanceof ServiceDescriptor && result.getFile() == this) { return (ServiceDescriptor)result; @@ -171,11 +178,13 @@ public final class Descriptors { * @return The extension's descriptor, or {@code null} if not found. */ public FieldDescriptor findExtensionByName(String name) { - if (name.indexOf('.') != -1) return null; + if (name.indexOf('.') != -1) { + return null; + } if (getPackage().length() > 0) { - name = getPackage() + "." + name; + name = getPackage() + '.' + name; } - GenericDescriptor result = pool.findSymbol(name); + final GenericDescriptor result = pool.findSymbol(name); if (result != null && result instanceof FieldDescriptor && result.getFile() == this) { return (FieldDescriptor)result; @@ -196,8 +205,8 @@ public final class Descriptors { * because a field has an undefined type or because two messages * were defined with the same name. */ - public static FileDescriptor buildFrom(FileDescriptorProto proto, - FileDescriptor[] dependencies) + public static FileDescriptor buildFrom(final FileDescriptorProto proto, + final FileDescriptor[] dependencies) throws DescriptorValidationException { // Building decsriptors involves two steps: translating and linking. // In the translation step (implemented by FileDescriptor's @@ -208,8 +217,9 @@ public final class Descriptors { // FieldDescriptor for an embedded message contains a pointer directly // to the Descriptor for that message's type. We also detect undefined // types in the linking step. - DescriptorPool pool = new DescriptorPool(dependencies); - FileDescriptor result = new FileDescriptor(proto, dependencies, pool); + final DescriptorPool pool = new DescriptorPool(dependencies); + final FileDescriptor result = + new FileDescriptor(proto, dependencies, pool); if (dependencies.length != proto.getDependencyCount()) { throw new DescriptorValidationException(result, @@ -234,8 +244,8 @@ public final class Descriptors { * encoded in protocol buffer wire format. */ public static void internalBuildGeneratedFileFrom( - String descriptorData, FileDescriptor[] dependencies, - InternalDescriptorAssigner descriptorAssigner) { + final String descriptorData, final FileDescriptor[] dependencies, + final InternalDescriptorAssigner descriptorAssigner) { // Hack: We can't embed a raw byte array inside generated Java code // (at least, not efficiently), but we can embed Strings. So, the // protocol compiler embeds the FileDescriptorProto as a giant @@ -245,10 +255,10 @@ public final class Descriptors { // serialized form. So, if we convert it to bytes in ISO-8859-1, we // should get the original bytes that we want. - byte[] descriptorBytes; + final byte[] descriptorBytes; try { descriptorBytes = descriptorData.getBytes("ISO-8859-1"); - } catch (java.io.UnsupportedEncodingException e) { + } catch (UnsupportedEncodingException e) { throw new RuntimeException( "Standard encoding ISO-8859-1 not supported by JVM.", e); } @@ -261,7 +271,7 @@ public final class Descriptors { "Failed to parse protocol buffer descriptor for generated code.", e); } - FileDescriptor result; + final FileDescriptor result; try { result = buildFrom(proto, dependencies); } catch (DescriptorValidationException e) { @@ -269,7 +279,8 @@ public final class Descriptors { "Invalid embedded descriptor for \"" + proto.getName() + "\".", e); } - ExtensionRegistry registry = descriptorAssigner.assignDescriptors(result); + final ExtensionRegistry registry = + descriptorAssigner.assignDescriptors(result); if (registry != null) { // We must re-parse the proto using the registry. @@ -297,7 +308,7 @@ public final class Descriptors { * descriptor.proto. The callback may also return null to indicate that * no extensions are used in the decsriptor. */ - public static interface InternalDescriptorAssigner { + public interface InternalDescriptorAssigner { ExtensionRegistry assignDescriptors(FileDescriptor root); } @@ -309,9 +320,9 @@ public final class Descriptors { private final FileDescriptor[] dependencies; private final DescriptorPool pool; - private FileDescriptor(FileDescriptorProto proto, - FileDescriptor[] dependencies, - DescriptorPool pool) + private FileDescriptor(final FileDescriptorProto proto, + final FileDescriptor[] dependencies, + final DescriptorPool pool) throws DescriptorValidationException { this.pool = pool; this.proto = proto; @@ -344,16 +355,16 @@ public final class Descriptors { /** Look up and cross-link all field types, etc. */ private void crossLink() throws DescriptorValidationException { - for (int i = 0; i < messageTypes.length; i++) { - messageTypes[i].crossLink(); + for (final Descriptor messageType : messageTypes) { + messageType.crossLink(); } - for (int i = 0; i < services.length; i++) { - services[i].crossLink(); + for (final ServiceDescriptor service : services) { + service.crossLink(); } - for (int i = 0; i < extensions.length; i++) { - extensions[i].crossLink(); + for (final FieldDescriptor extension : extensions) { + extension.crossLink(); } } @@ -367,7 +378,7 @@ public final class Descriptors { * protos. So, we have to parse the descriptor protos a second time after * constructing the descriptors. */ - private void setProto(FileDescriptorProto proto) { + private void setProto(final FileDescriptorProto proto) { this.proto = proto; for (int i = 0; i < messageTypes.length; i++) { @@ -456,8 +467,9 @@ public final class Descriptors { } /** Determines if the given field number is an extension. */ - public boolean isExtensionNumber(int number) { - for (DescriptorProto.ExtensionRange range : proto.getExtensionRangeList()) { + public boolean isExtensionNumber(final int number) { + for (final DescriptorProto.ExtensionRange range : + proto.getExtensionRangeList()) { if (range.getStart() <= number && number < range.getEnd()) { return true; } @@ -470,8 +482,9 @@ public final class Descriptors { * @param name The unqualified name of the field (e.g. "foo"). * @return The field's descriptor, or {@code null} if not found. */ - public FieldDescriptor findFieldByName(String name) { - GenericDescriptor result = file.pool.findSymbol(fullName + "." + name); + public FieldDescriptor findFieldByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); if (result != null && result instanceof FieldDescriptor) { return (FieldDescriptor)result; } else { @@ -484,7 +497,7 @@ public final class Descriptors { * @param number The field number within this message type. * @return The field's descriptor, or {@code null} if not found. */ - public FieldDescriptor findFieldByNumber(int number) { + public FieldDescriptor findFieldByNumber(final int number) { return file.pool.fieldsByNumber.get( new DescriptorPool.DescriptorIntPair(this, number)); } @@ -494,8 +507,9 @@ public final class Descriptors { * @param name The unqualified name of the nested type (e.g. "Foo"). * @return The types's descriptor, or {@code null} if not found. */ - public Descriptor findNestedTypeByName(String name) { - GenericDescriptor result = file.pool.findSymbol(fullName + "." + name); + public Descriptor findNestedTypeByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); if (result != null && result instanceof Descriptor) { return (Descriptor)result; } else { @@ -508,8 +522,9 @@ public final class Descriptors { * @param name The unqualified name of the nested type (e.g. "Foo"). * @return The types's descriptor, or {@code null} if not found. */ - public EnumDescriptor findEnumTypeByName(String name) { - GenericDescriptor result = file.pool.findSymbol(fullName + "." + name); + public EnumDescriptor findEnumTypeByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); if (result != null && result instanceof EnumDescriptor) { return (EnumDescriptor)result; } else { @@ -527,38 +542,38 @@ public final class Descriptors { private final FieldDescriptor[] fields; private final FieldDescriptor[] extensions; - private Descriptor(DescriptorProto proto, - FileDescriptor file, - Descriptor parent, - int index) + private Descriptor(final DescriptorProto proto, + final FileDescriptor file, + final Descriptor parent, + final int index) throws DescriptorValidationException { this.index = index; this.proto = proto; - this.fullName = computeFullName(file, parent, proto.getName()); + fullName = computeFullName(file, parent, proto.getName()); this.file = file; - this.containingType = parent; + containingType = parent; - this.nestedTypes = new Descriptor[proto.getNestedTypeCount()]; + nestedTypes = new Descriptor[proto.getNestedTypeCount()]; for (int i = 0; i < proto.getNestedTypeCount(); i++) { - this.nestedTypes[i] = new Descriptor( + nestedTypes[i] = new Descriptor( proto.getNestedType(i), file, this, i); } - this.enumTypes = new EnumDescriptor[proto.getEnumTypeCount()]; + enumTypes = new EnumDescriptor[proto.getEnumTypeCount()]; for (int i = 0; i < proto.getEnumTypeCount(); i++) { - this.enumTypes[i] = new EnumDescriptor( + enumTypes[i] = new EnumDescriptor( proto.getEnumType(i), file, this, i); } - this.fields = new FieldDescriptor[proto.getFieldCount()]; + fields = new FieldDescriptor[proto.getFieldCount()]; for (int i = 0; i < proto.getFieldCount(); i++) { - this.fields[i] = new FieldDescriptor( + fields[i] = new FieldDescriptor( proto.getField(i), file, this, i, false); } - this.extensions = new FieldDescriptor[proto.getExtensionCount()]; + extensions = new FieldDescriptor[proto.getExtensionCount()]; for (int i = 0; i < proto.getExtensionCount(); i++) { - this.extensions[i] = new FieldDescriptor( + extensions[i] = new FieldDescriptor( proto.getExtension(i), file, this, i, true); } @@ -567,21 +582,21 @@ public final class Descriptors { /** Look up and cross-link all field types, etc. */ private void crossLink() throws DescriptorValidationException { - for (int i = 0; i < nestedTypes.length; i++) { - nestedTypes[i].crossLink(); + for (final Descriptor nestedType : nestedTypes) { + nestedType.crossLink(); } - for (int i = 0; i < fields.length; i++) { - fields[i].crossLink(); + for (final FieldDescriptor field : fields) { + field.crossLink(); } - for (int i = 0; i < extensions.length; i++) { - extensions[i].crossLink(); + for (final FieldDescriptor extension : extensions) { + extension.crossLink(); } } - /** See {@link FileDescriptor.setProto}. */ - private void setProto(DescriptorProto proto) { + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final DescriptorProto proto) { this.proto = proto; for (int i = 0; i < nestedTypes.length; i++) { @@ -606,10 +621,11 @@ public final class Descriptors { /** Describes a field of a message type. */ public static final class FieldDescriptor - implements GenericDescriptor, Comparable { + implements GenericDescriptor, Comparable, + FieldSet.FieldDescriptorLite { /** * Get the index of this descriptor within its parent. - * @see Descriptors.Descriptor#getIndex() + * @see Descriptor#getIndex() */ public int getIndex() { return index; } @@ -624,7 +640,7 @@ public final class Descriptors { /** * Get the field's fully-qualified name. - * @see Descriptors.Descriptor#getFullName() + * @see Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -634,12 +650,27 @@ public final class Descriptors { */ public JavaType getJavaType() { return type.getJavaType(); } + /** For internal use only. */ + public WireFormat.JavaType getLiteJavaType() { + return getLiteType().getJavaType(); + } + /** Get the {@code FileDescriptor} containing this descriptor. */ public FileDescriptor getFile() { return file; } /** Get the field's declared type. */ public Type getType() { return type; } + /** For internal use only. */ + public WireFormat.FieldType getLiteType() { + return table[type.ordinal()]; + } + // I'm pretty sure values() constructs a new array every time, since there + // is nothing stopping the caller from mutating the array. Therefore we + // make a static copy here. + private static final WireFormat.FieldType[] table = + WireFormat.FieldType.values(); + /** Is this field declared required? */ public boolean isRequired() { return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REQUIRED; @@ -655,6 +686,11 @@ public final class Descriptors { return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED; } + /** Does this field have the {@code [packed = true]} option? */ + public boolean isPacked() { + return getOptions().getPacked(); + } + /** Returns true if the field had an explicitly-defined default value. */ public boolean hasDefaultValue() { return proto.hasDefaultValue(); } @@ -742,7 +778,7 @@ public final class Descriptors { * @return negative, zero, or positive if {@code this} is less than, * equal to, or greater than {@code other}, respectively. */ - public int compareTo(FieldDescriptor other) { + public int compareTo(final FieldDescriptor other) { if (other.containingType != containingType) { throw new IllegalArgumentException( "FieldDescriptors can only be compared to other FieldDescriptors " + @@ -765,7 +801,7 @@ public final class Descriptors { private EnumDescriptor enumType; private Object defaultValue; - public static enum Type { + public enum Type { DOUBLE (FieldDescriptorProto.Type.TYPE_DOUBLE , JavaType.DOUBLE ), FLOAT (FieldDescriptorProto.Type.TYPE_FLOAT , JavaType.FLOAT ), INT64 (FieldDescriptorProto.Type.TYPE_INT64 , JavaType.LONG ), @@ -785,11 +821,11 @@ public final class Descriptors { SINT32 (FieldDescriptorProto.Type.TYPE_SINT32 , JavaType.INT ), SINT64 (FieldDescriptorProto.Type.TYPE_SINT64 , JavaType.LONG ); - private Type(FieldDescriptorProto.Type proto, JavaType javaType) { + Type(final FieldDescriptorProto.Type proto, final JavaType javaType) { this.proto = proto; this.javaType = javaType; - if (this.ordinal() != proto.getNumber() - 1) { + if (ordinal() != proto.getNumber() - 1) { throw new RuntimeException( "descriptor.proto changed but Desrciptors.java wasn't updated."); } @@ -801,7 +837,7 @@ public final class Descriptors { public FieldDescriptorProto.Type toProto() { return proto; } public JavaType getJavaType() { return javaType; } - public static Type valueOf(FieldDescriptorProto.Type type) { + public static Type valueOf(final FieldDescriptorProto.Type type) { return values()[type.getNumber() - 1]; } } @@ -815,7 +851,7 @@ public final class Descriptors { } } - public static enum JavaType { + public enum JavaType { INT(0), LONG(0L), FLOAT(0F), @@ -826,7 +862,7 @@ public final class Descriptors { ENUM(null), MESSAGE(null); - private JavaType(Object defaultDefault) { + JavaType(final Object defaultDefault) { this.defaultDefault = defaultDefault; } @@ -834,22 +870,22 @@ public final class Descriptors { * The default default value for fields of this type, if it's a primitive * type. This is meant for use inside this file only, hence is private. */ - private Object defaultDefault; + private final Object defaultDefault; } - private FieldDescriptor(FieldDescriptorProto proto, - FileDescriptor file, - Descriptor parent, - int index, - boolean isExtension) + private FieldDescriptor(final FieldDescriptorProto proto, + final FileDescriptor file, + final Descriptor parent, + final int index, + final boolean isExtension) throws DescriptorValidationException { this.index = index; this.proto = proto; - this.fullName = computeFullName(file, parent, proto.getName()); + fullName = computeFullName(file, parent, proto.getName()); this.file = file; if (proto.hasType()) { - this.type = Type.valueOf(proto.getType()); + type = Type.valueOf(proto.getType()); } if (getNumber() <= 0) { @@ -875,19 +911,19 @@ public final class Descriptors { throw new DescriptorValidationException(this, "FieldDescriptorProto.extendee not set for extension field."); } - this.containingType = null; // Will be filled in when cross-linking + containingType = null; // Will be filled in when cross-linking if (parent != null) { - this.extensionScope = parent; + extensionScope = parent; } else { - this.extensionScope = null; + extensionScope = null; } } else { if (proto.hasExtendee()) { throw new DescriptorValidationException(this, "FieldDescriptorProto.extendee set for non-extension field."); } - this.containingType = parent; - this.extensionScope = null; + containingType = parent; + extensionScope = null; } file.pool.addSymbol(this); @@ -896,43 +932,44 @@ public final class Descriptors { /** Look up and cross-link all field types, etc. */ private void crossLink() throws DescriptorValidationException { if (proto.hasExtendee()) { - GenericDescriptor extendee = + final GenericDescriptor extendee = file.pool.lookupSymbol(proto.getExtendee(), this); if (!(extendee instanceof Descriptor)) { throw new DescriptorValidationException(this, - "\"" + proto.getExtendee() + "\" is not a message type."); + '\"' + proto.getExtendee() + "\" is not a message type."); } - this.containingType = (Descriptor)extendee; + containingType = (Descriptor)extendee; if (!getContainingType().isExtensionNumber(getNumber())) { throw new DescriptorValidationException(this, - "\"" + getContainingType().getFullName() + "\" does not declare " + - getNumber() + " as an extension number."); + '\"' + getContainingType().getFullName() + + "\" does not declare " + getNumber() + + " as an extension number."); } } if (proto.hasTypeName()) { - GenericDescriptor typeDescriptor = + final GenericDescriptor typeDescriptor = file.pool.lookupSymbol(proto.getTypeName(), this); if (!proto.hasType()) { // Choose field type based on symbol. if (typeDescriptor instanceof Descriptor) { - this.type = Type.MESSAGE; + type = Type.MESSAGE; } else if (typeDescriptor instanceof EnumDescriptor) { - this.type = Type.ENUM; + type = Type.ENUM; } else { throw new DescriptorValidationException(this, - "\"" + proto.getTypeName() + "\" is not a type."); + '\"' + proto.getTypeName() + "\" is not a type."); } } if (getJavaType() == JavaType.MESSAGE) { if (!(typeDescriptor instanceof Descriptor)) { throw new DescriptorValidationException(this, - "\"" + proto.getTypeName() + "\" is not a message type."); + '\"' + proto.getTypeName() + "\" is not a message type."); } - this.messageType = (Descriptor)typeDescriptor; + messageType = (Descriptor)typeDescriptor; if (proto.hasDefaultValue()) { throw new DescriptorValidationException(this, @@ -941,9 +978,9 @@ public final class Descriptors { } else if (getJavaType() == JavaType.ENUM) { if (!(typeDescriptor instanceof EnumDescriptor)) { throw new DescriptorValidationException(this, - "\"" + proto.getTypeName() + "\" is not an enum type."); + '\"' + proto.getTypeName() + "\" is not an enum type."); } - this.enumType = (EnumDescriptor)typeDescriptor; + enumType = (EnumDescriptor)typeDescriptor; } else { throw new DescriptorValidationException(this, "Field with primitive type has type_name."); @@ -972,20 +1009,18 @@ public final class Descriptors { defaultValue = TextFormat.parseInt32(proto.getDefaultValue()); break; case UINT32: - case FIXED32: { + case FIXED32: defaultValue = TextFormat.parseUInt32(proto.getDefaultValue()); break; - } case INT64: case SINT64: case SFIXED64: defaultValue = TextFormat.parseInt64(proto.getDefaultValue()); break; case UINT64: - case FIXED64: { + case FIXED64: defaultValue = TextFormat.parseUInt64(proto.getDefaultValue()); break; - } case FLOAT: defaultValue = Float.valueOf(proto.getDefaultValue()); break; @@ -1002,9 +1037,9 @@ public final class Descriptors { try { defaultValue = TextFormat.unescapeBytes(proto.getDefaultValue()); - } catch (TextFormat.InvalidEscapeSequence e) { + } catch (TextFormat.InvalidEscapeSequenceException e) { throw new DescriptorValidationException(this, - "Couldn't parse default value: " + e.getMessage()); + "Couldn't parse default value: " + e.getMessage(), e); } break; case ENUM: @@ -1012,7 +1047,7 @@ public final class Descriptors { if (defaultValue == null) { throw new DescriptorValidationException(this, "Unknown enum default value: \"" + - proto.getDefaultValue() + "\""); + proto.getDefaultValue() + '\"'); } break; case MESSAGE: @@ -1021,17 +1056,17 @@ public final class Descriptors { "Message type had default value."); } } catch (NumberFormatException e) { - DescriptorValidationException validationException = + final DescriptorValidationException validationException = new DescriptorValidationException(this, "Could not parse default value: \"" + - proto.getDefaultValue() + "\""); + proto.getDefaultValue() + '\"'); validationException.initCause(e); throw validationException; } } else { // Determine the default default for this field. if (isRepeated()) { - defaultValue = Collections.EMPTY_LIST; + defaultValue = Collections.emptyList(); } else { switch (getJavaType()) { case ENUM: @@ -1067,19 +1102,32 @@ public final class Descriptors { } } - /** See {@link FileDescriptor.setProto}. */ - private void setProto(FieldDescriptorProto proto) { + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final FieldDescriptorProto proto) { this.proto = proto; } + + /** + * For internal use only. This is to satisfy the FieldDescriptorLite + * interface. + */ + @Override + public MessageLite.Builder internalMergeFrom( + MessageLite.Builder to, MessageLite from) { + // FieldDescriptors are only used with non-lite messages so we can just + // down-cast and call mergeFrom directly. + return ((Message.Builder) to).mergeFrom((Message) from); + } } // ================================================================= /** Describes an enum type. */ - public static final class EnumDescriptor implements GenericDescriptor { + public static final class EnumDescriptor + implements GenericDescriptor, Internal.EnumLiteMap { /** * Get the index of this descriptor within its parent. - * @see Descriptors.Descriptor#getIndex() + * @see Descriptor#getIndex() */ public int getIndex() { return index; } @@ -1091,7 +1139,7 @@ public final class Descriptors { /** * Get the type's fully-qualified name. - * @see Descriptors.Descriptor#getFullName() + * @see Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -1114,8 +1162,9 @@ public final class Descriptors { * @param name The unqualified name of the value (e.g. "FOO"). * @return the value's decsriptor, or {@code null} if not found. */ - public EnumValueDescriptor findValueByName(String name) { - GenericDescriptor result = file.pool.findSymbol(fullName + "." + name); + public EnumValueDescriptor findValueByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); if (result != null && result instanceof EnumValueDescriptor) { return (EnumValueDescriptor)result; } else { @@ -1129,7 +1178,7 @@ public final class Descriptors { * @param number The value's number. * @return the value's decsriptor, or {@code null} if not found. */ - public EnumValueDescriptor findValueByNumber(int number) { + public EnumValueDescriptor findValueByNumber(final int number) { return file.pool.enumValuesByNumber.get( new DescriptorPool.DescriptorIntPair(this, number)); } @@ -1141,16 +1190,16 @@ public final class Descriptors { private final Descriptor containingType; private EnumValueDescriptor[] values; - private EnumDescriptor(EnumDescriptorProto proto, - FileDescriptor file, - Descriptor parent, - int index) + private EnumDescriptor(final EnumDescriptorProto proto, + final FileDescriptor file, + final Descriptor parent, + final int index) throws DescriptorValidationException { this.index = index; this.proto = proto; - this.fullName = computeFullName(file, parent, proto.getName()); + fullName = computeFullName(file, parent, proto.getName()); this.file = file; - this.containingType = parent; + containingType = parent; if (proto.getValueCount() == 0) { // We cannot allow enums with no values because this would mean there @@ -1161,15 +1210,15 @@ public final class Descriptors { values = new EnumValueDescriptor[proto.getValueCount()]; for (int i = 0; i < proto.getValueCount(); i++) { - this.values[i] = new EnumValueDescriptor( + values[i] = new EnumValueDescriptor( proto.getValue(i), file, this, i); } file.pool.addSymbol(this); } - /** See {@link FileDescriptor.setProto}. */ - private void setProto(EnumDescriptorProto proto) { + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final EnumDescriptorProto proto) { this.proto = proto; for (int i = 0; i < values.length; i++) { @@ -1186,10 +1235,11 @@ public final class Descriptors { * with the same number after the first become aliases of the first. * However, they still have independent EnumValueDescriptors. */ - public static final class EnumValueDescriptor implements GenericDescriptor { + public static final class EnumValueDescriptor + implements GenericDescriptor, Internal.EnumLite { /** * Get the index of this descriptor within its parent. - * @see Descriptors.Descriptor#getIndex() + * @see Descriptor#getIndex() */ public int getIndex() { return index; } @@ -1204,7 +1254,7 @@ public final class Descriptors { /** * Get the value's fully-qualified name. - * @see Descriptors.Descriptor#getFullName() + * @see Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -1225,24 +1275,24 @@ public final class Descriptors { private final FileDescriptor file; private final EnumDescriptor type; - private EnumValueDescriptor(EnumValueDescriptorProto proto, - FileDescriptor file, - EnumDescriptor parent, - int index) + private EnumValueDescriptor(final EnumValueDescriptorProto proto, + final FileDescriptor file, + final EnumDescriptor parent, + final int index) throws DescriptorValidationException { this.index = index; this.proto = proto; this.file = file; - this.type = parent; + type = parent; - this.fullName = parent.getFullName() + "." + proto.getName(); + fullName = parent.getFullName() + '.' + proto.getName(); file.pool.addSymbol(this); file.pool.addEnumValueByNumber(this); } - /** See {@link FileDescriptor.setProto}. */ - private void setProto(EnumValueDescriptorProto proto) { + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final EnumValueDescriptorProto proto) { this.proto = proto; } } @@ -1265,7 +1315,7 @@ public final class Descriptors { /** * Get the type's fully-qualified name. - * @see Descriptors.Descriptor#getFullName() + * @see Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -1285,8 +1335,9 @@ public final class Descriptors { * @param name The unqualified name of the method (e.g. "Foo"). * @return the method's decsriptor, or {@code null} if not found. */ - public MethodDescriptor findMethodByName(String name) { - GenericDescriptor result = file.pool.findSymbol(fullName + "." + name); + public MethodDescriptor findMethodByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); if (result != null && result instanceof MethodDescriptor) { return (MethodDescriptor)result; } else { @@ -1300,18 +1351,18 @@ public final class Descriptors { private final FileDescriptor file; private MethodDescriptor[] methods; - private ServiceDescriptor(ServiceDescriptorProto proto, - FileDescriptor file, - int index) + private ServiceDescriptor(final ServiceDescriptorProto proto, + final FileDescriptor file, + final int index) throws DescriptorValidationException { this.index = index; this.proto = proto; - this.fullName = computeFullName(file, null, proto.getName()); + fullName = computeFullName(file, null, proto.getName()); this.file = file; - this.methods = new MethodDescriptor[proto.getMethodCount()]; + methods = new MethodDescriptor[proto.getMethodCount()]; for (int i = 0; i < proto.getMethodCount(); i++) { - this.methods[i] = new MethodDescriptor( + methods[i] = new MethodDescriptor( proto.getMethod(i), file, this, i); } @@ -1319,13 +1370,13 @@ public final class Descriptors { } private void crossLink() throws DescriptorValidationException { - for (int i = 0; i < methods.length; i++) { - methods[i].crossLink(); + for (final MethodDescriptor method : methods) { + method.crossLink(); } } - /** See {@link FileDescriptor.setProto}. */ - private void setProto(ServiceDescriptorProto proto) { + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final ServiceDescriptorProto proto) { this.proto = proto; for (int i = 0; i < methods.length; i++) { @@ -1354,7 +1405,7 @@ public final class Descriptors { /** * Get the method's fully-qualified name. - * @see Descriptors.Descriptor#getFullName() + * @see Descriptor#getFullName() */ public String getFullName() { return fullName; } @@ -1385,54 +1436,54 @@ public final class Descriptors { private Descriptor inputType; private Descriptor outputType; - private MethodDescriptor(MethodDescriptorProto proto, - FileDescriptor file, - ServiceDescriptor parent, - int index) + private MethodDescriptor(final MethodDescriptorProto proto, + final FileDescriptor file, + final ServiceDescriptor parent, + final int index) throws DescriptorValidationException { this.index = index; this.proto = proto; this.file = file; - this.service = parent; + service = parent; - this.fullName = parent.getFullName() + "." + proto.getName(); + fullName = parent.getFullName() + '.' + proto.getName(); file.pool.addSymbol(this); } private void crossLink() throws DescriptorValidationException { - GenericDescriptor inputType = + final GenericDescriptor input = file.pool.lookupSymbol(proto.getInputType(), this); - if (!(inputType instanceof Descriptor)) { + if (!(input instanceof Descriptor)) { throw new DescriptorValidationException(this, - "\"" + proto.getInputType() + "\" is not a message type."); + '\"' + proto.getInputType() + "\" is not a message type."); } - this.inputType = (Descriptor)inputType; + inputType = (Descriptor)input; - GenericDescriptor outputType = + final GenericDescriptor output = file.pool.lookupSymbol(proto.getOutputType(), this); - if (!(outputType instanceof Descriptor)) { + if (!(output instanceof Descriptor)) { throw new DescriptorValidationException(this, - "\"" + proto.getOutputType() + "\" is not a message type."); + '\"' + proto.getOutputType() + "\" is not a message type."); } - this.outputType = (Descriptor)outputType; + outputType = (Descriptor)output; } - /** See {@link FileDescriptor.setProto}. */ - private void setProto(MethodDescriptorProto proto) { + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final MethodDescriptorProto proto) { this.proto = proto; } } // ================================================================= - private static String computeFullName(FileDescriptor file, - Descriptor parent, - String name) { + private static String computeFullName(final FileDescriptor file, + final Descriptor parent, + final String name) { if (parent != null) { - return parent.getFullName() + "." + name; + return parent.getFullName() + '.' + name; } else if (file.getPackage().length() > 0) { - return file.getPackage() + "." + name; + return file.getPackage() + '.' + name; } else { return name; } @@ -1444,7 +1495,7 @@ public final class Descriptors { * All descriptors except {@code FileDescriptor} implement this to make * {@code DescriptorPool}'s life easier. */ - private static interface GenericDescriptor { + private interface GenericDescriptor { Message toProto(); String getName(); String getFullName(); @@ -1456,6 +1507,8 @@ public final class Descriptors { * are not valid. */ public static class DescriptorValidationException extends Exception { + private static final long serialVersionUID = 5750205775490483148L; + /** Gets the full name of the descriptor where the error occurred. */ public String getProblemSymbolName() { return name; } @@ -1473,27 +1526,36 @@ public final class Descriptors { private final Message proto; private final String description; - private DescriptorValidationException(GenericDescriptor problemDescriptor, - String description) { - super(problemDescriptor.getFullName() + ": " + description); + private DescriptorValidationException( + final GenericDescriptor problemDescriptor, + final String description) { + this(problemDescriptor, description, null); + } + + private DescriptorValidationException( + final GenericDescriptor problemDescriptor, + final String description, + final Throwable cause) { + super(problemDescriptor.getFullName() + ": " + description, cause); // Note that problemDescriptor may be partially uninitialized, so we // don't want to expose it directly to the user. So, we only provide // the name and the original proto. - this.name = problemDescriptor.getFullName(); - this.proto = problemDescriptor.toProto(); + name = problemDescriptor.getFullName(); + proto = problemDescriptor.toProto(); this.description = description; } - private DescriptorValidationException(FileDescriptor problemDescriptor, - String description) { + private DescriptorValidationException( + final FileDescriptor problemDescriptor, + final String description) { super(problemDescriptor.getName() + ": " + description); // Note that problemDescriptor may be partially uninitialized, so we // don't want to expose it directly to the user. So, we only provide // the name and the original proto. - this.name = problemDescriptor.getName(); - this.proto = problemDescriptor.toProto(); + name = problemDescriptor.getName(); + proto = problemDescriptor.toProto(); this.description = description; } } @@ -1505,16 +1567,16 @@ public final class Descriptors { * descriptors defined in a particular file. */ private static final class DescriptorPool { - DescriptorPool(FileDescriptor[] dependencies) { + DescriptorPool(final FileDescriptor[] dependencies) { this.dependencies = new DescriptorPool[dependencies.length]; for (int i = 0; i < dependencies.length; i++) { this.dependencies[i] = dependencies[i].pool; } - for (int i = 0; i < dependencies.length; i++) { + for (final FileDescriptor dependency : dependencies) { try { - addPackage(dependencies[i].getPackage(), dependencies[i]); + addPackage(dependency.getPackage(), dependency); } catch (DescriptorValidationException e) { // Can't happen, because addPackage() only fails when the name // conflicts with a non-package, but we have not yet added any @@ -1524,23 +1586,27 @@ public final class Descriptors { } } - final DescriptorPool[] dependencies; + private final DescriptorPool[] dependencies; - final Map descriptorsByName = + private final Map descriptorsByName = new HashMap(); - final Map fieldsByNumber = + private final Map fieldsByNumber = new HashMap(); - final Map enumValuesByNumber = - new HashMap(); + private final Map enumValuesByNumber + = new HashMap(); /** Find a generic descriptor by fully-qualified name. */ - GenericDescriptor findSymbol(String fullName) { + GenericDescriptor findSymbol(final String fullName) { GenericDescriptor result = descriptorsByName.get(fullName); - if (result != null) return result; + if (result != null) { + return result; + } - for (int i = 0; i < dependencies.length; i++) { - result = dependencies[i].descriptorsByName.get(fullName); - if (result != null) return result; + for (final DescriptorPool dependency : dependencies) { + result = dependency.descriptorsByName.get(fullName); + if (result != null) { + return result; + } } return null; @@ -1552,8 +1618,8 @@ public final class Descriptors { * partially-qualified, or unqualified. C++-like name lookup semantics * are used to search for the matching descriptor. */ - GenericDescriptor lookupSymbol(String name, - GenericDescriptor relativeTo) + GenericDescriptor lookupSymbol(final String name, + final GenericDescriptor relativeTo) throws DescriptorValidationException { // TODO(kenton): This could be optimized in a number of ways. @@ -1564,8 +1630,8 @@ public final class Descriptors { } else { // If "name" is a compound identifier, we want to search for the // first component of it, then search within it for the rest. - int firstPartLength = name.indexOf('.'); - String firstPart; + final int firstPartLength = name.indexOf('.'); + final String firstPart; if (firstPartLength == -1) { firstPart = name; } else { @@ -1574,11 +1640,12 @@ public final class Descriptors { // We will search each parent scope of "relativeTo" looking for the // symbol. - StringBuilder scopeToTry = new StringBuilder(relativeTo.getFullName()); + final StringBuilder scopeToTry = + new StringBuilder(relativeTo.getFullName()); while (true) { // Chop off the last component of the scope. - int dotpos = scopeToTry.lastIndexOf("."); + final int dotpos = scopeToTry.lastIndexOf("."); if (dotpos == -1) { result = findSymbol(name); break; @@ -1609,7 +1676,7 @@ public final class Descriptors { if (result == null) { throw new DescriptorValidationException(relativeTo, - "\"" + name + "\" is not defined."); + '\"' + name + "\" is not defined."); } else { return result; } @@ -1619,30 +1686,30 @@ public final class Descriptors { * Adds a symbol to the symbol table. If a symbol with the same name * already exists, throws an error. */ - void addSymbol(GenericDescriptor descriptor) + void addSymbol(final GenericDescriptor descriptor) throws DescriptorValidationException { validateSymbolName(descriptor); - String fullName = descriptor.getFullName(); - int dotpos = fullName.lastIndexOf('.'); + final String fullName = descriptor.getFullName(); + final int dotpos = fullName.lastIndexOf('.'); - GenericDescriptor old = descriptorsByName.put(fullName, descriptor); + final GenericDescriptor old = descriptorsByName.put(fullName, descriptor); if (old != null) { descriptorsByName.put(fullName, old); if (descriptor.getFile() == old.getFile()) { if (dotpos == -1) { throw new DescriptorValidationException(descriptor, - "\"" + fullName + "\" is already defined."); + '\"' + fullName + "\" is already defined."); } else { throw new DescriptorValidationException(descriptor, - "\"" + fullName.substring(dotpos + 1) + + '\"' + fullName.substring(dotpos + 1) + "\" is already defined in \"" + fullName.substring(0, dotpos) + "\"."); } } else { throw new DescriptorValidationException(descriptor, - "\"" + fullName + "\" is already defined in file \"" + + '\"' + fullName + "\" is already defined in file \"" + old.getFile().getName() + "\"."); } } @@ -1653,21 +1720,22 @@ public final class Descriptors { * just as placeholders so that someone cannot define, say, a message type * that has the same name as an existing package. */ - static final class PackageDescriptor implements GenericDescriptor { + private static final class PackageDescriptor implements GenericDescriptor { public Message toProto() { return file.toProto(); } public String getName() { return name; } public String getFullName() { return fullName; } public FileDescriptor getFile() { return file; } - PackageDescriptor(String name, String fullName, FileDescriptor file) { + PackageDescriptor(final String name, final String fullName, + final FileDescriptor file) { this.file = file; this.fullName = fullName; this.name = name; } - String name; - String fullName; - FileDescriptor file; + private final String name; + private final String fullName; + private final FileDescriptor file; } /** @@ -1676,46 +1744,50 @@ public final class Descriptors { * under the same name, an exception is thrown. If the package has * multiple components, this also adds the parent package(s). */ - void addPackage(String fullName, FileDescriptor file) + void addPackage(final String fullName, final FileDescriptor file) throws DescriptorValidationException { - int dotpos = fullName.lastIndexOf('.'); - String name; - if (dotpos != -1) { + final int dotpos = fullName.lastIndexOf('.'); + final String name; + if (dotpos == -1) { + name = fullName; + } else { addPackage(fullName.substring(0, dotpos), file); name = fullName.substring(dotpos + 1); - } else { - name = fullName; } - GenericDescriptor old = + final GenericDescriptor old = descriptorsByName.put(fullName, new PackageDescriptor(name, fullName, file)); if (old != null) { descriptorsByName.put(fullName, old); if (!(old instanceof PackageDescriptor)) { throw new DescriptorValidationException(file, - "\"" + name + "\" is already defined (as something other than a " + - "package) in file \"" + old.getFile().getName() + "\"."); + '\"' + name + "\" is already defined (as something other than a " + + "package) in file \"" + old.getFile().getName() + "\"."); } } } /** A (GenericDescriptor, int) pair, used as a map key. */ - static final class DescriptorIntPair { - final GenericDescriptor descriptor; - final int number; + private static final class DescriptorIntPair { + private final GenericDescriptor descriptor; + private final int number; - DescriptorIntPair(GenericDescriptor descriptor, int number) { + DescriptorIntPair(final GenericDescriptor descriptor, final int number) { this.descriptor = descriptor; this.number = number; } + @Override public int hashCode() { return descriptor.hashCode() * ((1 << 16) - 1) + number; } - public boolean equals(Object obj) { - if (!(obj instanceof DescriptorIntPair)) return false; - DescriptorIntPair other = (DescriptorIntPair)obj; + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof DescriptorIntPair)) { + return false; + } + final DescriptorIntPair other = (DescriptorIntPair)obj; return descriptor == other.descriptor && number == other.number; } } @@ -1724,11 +1796,11 @@ public final class Descriptors { * Adds a field to the fieldsByNumber table. Throws an exception if a * field with hte same containing type and number already exists. */ - void addFieldByNumber(FieldDescriptor field) + void addFieldByNumber(final FieldDescriptor field) throws DescriptorValidationException { - DescriptorIntPair key = + final DescriptorIntPair key = new DescriptorIntPair(field.getContainingType(), field.getNumber()); - FieldDescriptor old = fieldsByNumber.put(key, field); + final FieldDescriptor old = fieldsByNumber.put(key, field); if (old != null) { fieldsByNumber.put(key, old); throw new DescriptorValidationException(field, @@ -1744,10 +1816,10 @@ public final class Descriptors { * with the same type and number already exists, does nothing. (This is * allowed; the first value define with the number takes precedence.) */ - void addEnumValueByNumber(EnumValueDescriptor value) { - DescriptorIntPair key = + void addEnumValueByNumber(final EnumValueDescriptor value) { + final DescriptorIntPair key = new DescriptorIntPair(value.getType(), value.getNumber()); - EnumValueDescriptor old = enumValuesByNumber.put(key, value); + final EnumValueDescriptor old = enumValuesByNumber.put(key, value); if (old != null) { enumValuesByNumber.put(key, old); // Not an error: Multiple enum values may have the same number, but @@ -1759,15 +1831,15 @@ public final class Descriptors { * Verifies that the descriptor's name is valid (i.e. it contains only * letters, digits, and underscores, and does not start with a digit). */ - void validateSymbolName(GenericDescriptor descriptor) - throws DescriptorValidationException { - String name = descriptor.getName(); + static void validateSymbolName(final GenericDescriptor descriptor) + throws DescriptorValidationException { + final String name = descriptor.getName(); if (name.length() == 0) { throw new DescriptorValidationException(descriptor, "Missing name."); } else { boolean valid = true; for (int i = 0; i < name.length(); i++) { - char c = name.charAt(i); + final char c = name.charAt(i); // Non-ASCII characters are not valid in protobuf identifiers, even // if they are letters or digits. if (c >= 128) { @@ -1784,7 +1856,7 @@ public final class Descriptors { } if (!valid) { throw new DescriptorValidationException(descriptor, - "\"" + name + "\" is not a valid identifier."); + '\"' + name + "\" is not a valid identifier."); } } } diff --git a/java/src/main/java/com/google/protobuf/DynamicMessage.java b/java/src/main/java/com/google/protobuf/DynamicMessage.java index 59fb7b02..c106b662 100644 --- a/java/src/main/java/com/google/protobuf/DynamicMessage.java +++ b/java/src/main/java/com/google/protobuf/DynamicMessage.java @@ -45,14 +45,14 @@ import java.util.Map; */ public final class DynamicMessage extends AbstractMessage { private final Descriptor type; - private final FieldSet fields; + private final FieldSet fields; private final UnknownFieldSet unknownFields; private int memoizedSize = -1; /** * Construct a {@code DynamicMessage} using the given {@code FieldSet}. */ - private DynamicMessage(Descriptor type, FieldSet fields, + private DynamicMessage(Descriptor type, FieldSet fields, UnknownFieldSet unknownFields) { this.type = type; this.fields = fields; @@ -64,7 +64,7 @@ public final class DynamicMessage extends AbstractMessage { * given type. */ public static DynamicMessage getDefaultInstance(Descriptor type) { - return new DynamicMessage(type, FieldSet.emptySet(), + return new DynamicMessage(type, FieldSet.emptySet(), UnknownFieldSet.getDefaultInstance()); } @@ -160,7 +160,11 @@ public final class DynamicMessage extends AbstractMessage { verifyContainingType(field); Object result = fields.getField(field); if (result == null) { - result = getDefaultInstance(field.getMessageType()); + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + result = getDefaultInstance(field.getMessageType()); + } else { + result = field.getDefaultValue(); + } } return result; } @@ -179,15 +183,31 @@ public final class DynamicMessage extends AbstractMessage { return unknownFields; } + private static boolean isInitialized(Descriptor type, + FieldSet fields) { + // Check that all required fields are present. + for (final FieldDescriptor field : type.getFields()) { + if (field.isRequired()) { + if (!fields.hasField(field)) { + return false; + } + } + } + + // Check that embedded messages are initialized. + return fields.isInitialized(); + } + public boolean isInitialized() { - return fields.isInitialized(type); + return isInitialized(type, fields); } public void writeTo(CodedOutputStream output) throws IOException { - fields.writeTo(output); if (type.getOptions().getMessageSetWireFormat()) { + fields.writeMessageSetTo(output); unknownFields.writeAsMessageSetTo(output); } else { + fields.writeTo(output); unknownFields.writeTo(output); } } @@ -196,10 +216,11 @@ public final class DynamicMessage extends AbstractMessage { int size = memoizedSize; if (size != -1) return size; - size = fields.getSerializedSize(); if (type.getOptions().getMessageSetWireFormat()) { + size = fields.getMessageSetSerializedSize(); size += unknownFields.getSerializedSizeAsMessageSet(); } else { + size = fields.getSerializedSize(); size += unknownFields.getSerializedSize(); } @@ -230,7 +251,7 @@ public final class DynamicMessage extends AbstractMessage { */ public static final class Builder extends AbstractMessage.Builder { private final Descriptor type; - private FieldSet fields; + private FieldSet fields; private UnknownFieldSet unknownFields; /** Construct a {@code Builder} for the given type. */ @@ -244,25 +265,33 @@ public final class DynamicMessage extends AbstractMessage { // Implementation of Message.Builder interface. public Builder clear() { + if (fields == null) { + throw new IllegalStateException("Cannot call clear() after build()."); + } fields.clear(); return this; } public Builder mergeFrom(Message other) { - if (other.getDescriptorForType() != type) { - throw new IllegalArgumentException( - "mergeFrom(Message) can only merge messages of the same type."); + if (other instanceof DynamicMessage) { + // This should be somewhat faster than calling super.mergeFrom(). + DynamicMessage otherDynamicMessage = (DynamicMessage) other; + if (otherDynamicMessage.type != type) { + throw new IllegalArgumentException( + "mergeFrom(Message) can only merge messages of the same type."); + } + fields.mergeFrom(otherDynamicMessage.fields); + mergeUnknownFields(otherDynamicMessage.unknownFields); + return this; + } else { + return super.mergeFrom(other); } - - fields.mergeFrom(other); - mergeUnknownFields(other.getUnknownFields()); - return this; } public DynamicMessage build() { // If fields == null, we'll throw an appropriate exception later. if (fields != null && !isInitialized()) { - throw new UninitializedMessageException( + throw newUninitializedMessageException( new DynamicMessage(type, fields, unknownFields)); } return buildPartial(); @@ -275,7 +304,7 @@ public final class DynamicMessage extends AbstractMessage { */ private DynamicMessage buildParsed() throws InvalidProtocolBufferException { if (!isInitialized()) { - throw new UninitializedMessageException( + throw newUninitializedMessageException( new DynamicMessage(type, fields, unknownFields)) .asInvalidProtocolBufferException(); } @@ -302,17 +331,7 @@ public final class DynamicMessage extends AbstractMessage { } public boolean isInitialized() { - return fields.isInitialized(type); - } - - public Builder mergeFrom(CodedInputStream input, - ExtensionRegistry extensionRegistry) - throws IOException { - UnknownFieldSet.Builder unknownFieldsBuilder = - UnknownFieldSet.newBuilder(unknownFields); - fields.mergeFrom(input, unknownFieldsBuilder, extensionRegistry, this); - unknownFields = unknownFieldsBuilder.build(); - return this; + return DynamicMessage.isInitialized(type, fields); } public Descriptor getDescriptorForType() { @@ -347,7 +366,11 @@ public final class DynamicMessage extends AbstractMessage { verifyContainingType(field); Object result = fields.getField(field); if (result == null) { - result = getDefaultInstance(field.getMessageType()); + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + result = getDefaultInstance(field.getMessageType()); + } else { + result = field.getDefaultValue(); + } } return result; } diff --git a/java/src/main/java/com/google/protobuf/ExtensionRegistry.java b/java/src/main/java/com/google/protobuf/ExtensionRegistry.java index 45396f6f..87bbd6eb 100644 --- a/java/src/main/java/com/google/protobuf/ExtensionRegistry.java +++ b/java/src/main/java/com/google/protobuf/ExtensionRegistry.java @@ -84,18 +84,16 @@ import java.util.Map; * would be slow. Second, corrupt data would not be detected until first * access, at which point it would be much harder to deal with it. Third, it * could violate the expectation that message objects are immutable, since the - * type provided could be any arbitrary message class. An unpriviledged user + * type provided could be any arbitrary message class. An unprivileged user * could take advantage of this to inject a mutable object into a message - * belonging to priviledged code and create mischief. + * belonging to privileged code and create mischief. * * @author kenton@google.com Kenton Varda */ -public final class ExtensionRegistry { +public final class ExtensionRegistry extends ExtensionRegistryLite { /** Construct a new, empty instance. */ public static ExtensionRegistry newInstance() { - return new ExtensionRegistry( - new HashMap(), - new HashMap()); + return new ExtensionRegistry(); } /** Get the unmodifiable singleton empty instance. */ @@ -104,10 +102,9 @@ public final class ExtensionRegistry { } /** Returns an unmodifiable view of the registry. */ + @Override public ExtensionRegistry getUnmodifiable() { - return new ExtensionRegistry( - Collections.unmodifiableMap(extensionsByName), - Collections.unmodifiableMap(extensionsByNumber)); + return new ExtensionRegistry(this); } /** A (Descriptor, Message) pair, returned by lookup methods. */ @@ -121,11 +118,12 @@ public final class ExtensionRegistry { */ public final Message defaultInstance; - private ExtensionInfo(FieldDescriptor descriptor) { + private ExtensionInfo(final FieldDescriptor descriptor) { this.descriptor = descriptor; - this.defaultInstance = null; + defaultInstance = null; } - private ExtensionInfo(FieldDescriptor descriptor, Message defaultInstance) { + private ExtensionInfo(final FieldDescriptor descriptor, + final Message defaultInstance) { this.descriptor = descriptor; this.defaultInstance = defaultInstance; } @@ -139,7 +137,7 @@ public final class ExtensionRegistry { * @return Information about the extension if found, or {@code null} * otherwise. */ - public ExtensionInfo findExtensionByName(String fullName) { + public ExtensionInfo findExtensionByName(final String fullName) { return extensionsByName.get(fullName); } @@ -149,14 +147,14 @@ public final class ExtensionRegistry { * @return Information about the extension if found, or {@code null} * otherwise. */ - public ExtensionInfo findExtensionByNumber(Descriptor containingType, - int fieldNumber) { + public ExtensionInfo findExtensionByNumber(final Descriptor containingType, + final int fieldNumber) { return extensionsByNumber.get( new DescriptorIntPair(containingType, fieldNumber)); } /** Add an extension from a generated file to the registry. */ - public void add(GeneratedMessage.GeneratedExtension extension) { + public void add(final GeneratedMessage.GeneratedExtension extension) { if (extension.getDescriptor().getJavaType() == FieldDescriptor.JavaType.MESSAGE) { add(new ExtensionInfo(extension.getDescriptor(), @@ -167,7 +165,7 @@ public final class ExtensionRegistry { } /** Add a non-message-type extension to the registry by descriptor. */ - public void add(FieldDescriptor type) { + public void add(final FieldDescriptor type) { if (type.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { throw new IllegalArgumentException( "ExtensionRegistry.add() must be provided a default instance when " + @@ -177,7 +175,7 @@ public final class ExtensionRegistry { } /** Add a message-type extension to the registry by descriptor. */ - public void add(FieldDescriptor type, Message defaultInstance) { + public void add(final FieldDescriptor type, final Message defaultInstance) { if (type.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { throw new IllegalArgumentException( "ExtensionRegistry.add() provided a default instance for a " + @@ -189,22 +187,30 @@ public final class ExtensionRegistry { // ================================================================= // Private stuff. - private ExtensionRegistry( - Map extensionsByName, - Map extensionsByNumber) { - this.extensionsByName = extensionsByName; - this.extensionsByNumber = extensionsByNumber; + private ExtensionRegistry() { + this.extensionsByName = new HashMap(); + this.extensionsByNumber = new HashMap(); + } + + private ExtensionRegistry(ExtensionRegistry other) { + super(other); + this.extensionsByName = Collections.unmodifiableMap(other.extensionsByName); + this.extensionsByNumber = + Collections.unmodifiableMap(other.extensionsByNumber); } private final Map extensionsByName; private final Map extensionsByNumber; - private static final ExtensionRegistry EMPTY = - new ExtensionRegistry( - Collections.emptyMap(), - Collections.emptyMap()); + private ExtensionRegistry(boolean empty) { + super(ExtensionRegistryLite.getEmptyRegistry()); + this.extensionsByName = Collections.emptyMap(); + this.extensionsByNumber = + Collections.emptyMap(); + } + private static final ExtensionRegistry EMPTY = new ExtensionRegistry(true); - private void add(ExtensionInfo extension) { + private void add(final ExtensionInfo extension) { if (!extension.descriptor.isExtension()) { throw new IllegalArgumentException( "ExtensionRegistry.add() was given a FieldDescriptor for a regular " + @@ -217,7 +223,7 @@ public final class ExtensionRegistry { extension.descriptor.getNumber()), extension); - FieldDescriptor field = extension.descriptor; + final FieldDescriptor field = extension.descriptor; if (field.getContainingType().getOptions().getMessageSetWireFormat() && field.getType() == FieldDescriptor.Type.MESSAGE && field.isOptional() && @@ -231,20 +237,24 @@ public final class ExtensionRegistry { /** A (GenericDescriptor, int) pair, used as a map key. */ private static final class DescriptorIntPair { - final Descriptor descriptor; - final int number; + private final Descriptor descriptor; + private final int number; - DescriptorIntPair(Descriptor descriptor, int number) { + DescriptorIntPair(final Descriptor descriptor, final int number) { this.descriptor = descriptor; this.number = number; } + @Override public int hashCode() { return descriptor.hashCode() * ((1 << 16) - 1) + number; } - public boolean equals(Object obj) { - if (!(obj instanceof DescriptorIntPair)) return false; - DescriptorIntPair other = (DescriptorIntPair)obj; + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof DescriptorIntPair)) { + return false; + } + final DescriptorIntPair other = (DescriptorIntPair)obj; return descriptor == other.descriptor && number == other.number; } } diff --git a/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java b/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java new file mode 100644 index 00000000..d5288dd8 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java @@ -0,0 +1,169 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Equivalent to {@link ExtensionRegistry} but supports only "lite" types. + *

+ * If all of your types are lite types, then you only need to use + * {@code ExtensionRegistryLite}. Similarly, if all your types are regular + * types, then you only need {@link ExtensionRegistry}. Typically it does not + * make sense to mix the two, since if you have any regular types in your + * program, you then require the full runtime and lose all the benefits of + * the lite runtime, so you might as well make all your types be regular types. + * However, in some cases (e.g. when depending on multiple third-patry libraries + * where one uses lite types and one uses regular), you may find yourself + * wanting to mix the two. In this case things get more complicated. + *

+ * There are three factors to consider: Whether the type being extended is + * lite, whether the embedded type (in the case of a message-typed extension) + * is lite, and whether the extension itself is lite. Since all three are + * declared in different files, they could all be different. Here are all + * the combinations and which type of registry to use: + *

+ *   Extended type     Inner type    Extension         Use registry
+ *   =======================================================================
+ *   lite              lite          lite              ExtensionRegistryLite
+ *   lite              regular       lite              ExtensionRegistry
+ *   regular           regular       regular           ExtensionRegistry
+ *   all other combinations                            not supported
+ * 
+ *

+ * Note that just as regular types are not allowed to contain lite-type fields, + * they are also not allowed to contain lite-type extensions. This is because + * regular types must be fully accessible via reflection, which in turn means + * that all the inner messages must also support reflection. On the other hand, + * since regular types implement the entire lite interface, there is no problem + * with embedding regular types inside lite types. + * + * @author kenton@google.com Kenton Varda + */ +public class ExtensionRegistryLite { + /** Construct a new, empty instance. */ + public static ExtensionRegistryLite newInstance() { + return new ExtensionRegistryLite(); + } + + /** Get the unmodifiable singleton empty instance. */ + public static ExtensionRegistryLite getEmptyRegistry() { + return EMPTY; + } + + /** Returns an unmodifiable view of the registry. */ + public ExtensionRegistryLite getUnmodifiable() { + return new ExtensionRegistryLite(this); + } + + /** + * Find an extension by containing type and field number. + * + * @return Information about the extension if found, or {@code null} + * otherwise. + */ + @SuppressWarnings("unchecked") + public + GeneratedMessageLite.GeneratedExtension + findLiteExtensionByNumber( + final ContainingType containingTypeDefaultInstance, + final int fieldNumber) { + return (GeneratedMessageLite.GeneratedExtension) + extensionsByNumber.get( + new ObjectIntPair(containingTypeDefaultInstance, fieldNumber)); + } + + /** Add an extension from a lite generated file to the registry. */ + public final void add( + final GeneratedMessageLite.GeneratedExtension extension) { + extensionsByNumber.put( + new ObjectIntPair(extension.getContainingTypeDefaultInstance(), + extension.getNumber()), + extension); + } + + // ================================================================= + // Private stuff. + + // Constructors are package-private so that ExtensionRegistry can subclass + // this. + + ExtensionRegistryLite() { + this.extensionsByNumber = + new HashMap>(); + } + + ExtensionRegistryLite(ExtensionRegistryLite other) { + if (other == EMPTY) { + this.extensionsByNumber = Collections.emptyMap(); + } else { + this.extensionsByNumber = + Collections.unmodifiableMap(other.extensionsByNumber); + } + } + + private final Map> + extensionsByNumber; + + private ExtensionRegistryLite(boolean empty) { + this.extensionsByNumber = Collections.emptyMap(); + } + private static final ExtensionRegistryLite EMPTY = + new ExtensionRegistryLite(true); + + /** A (Object, int) pair, used as a map key. */ + private static final class ObjectIntPair { + private final Object object; + private final int number; + + ObjectIntPair(final Object object, final int number) { + this.object = object; + this.number = number; + } + + @Override + public int hashCode() { + return System.identityHashCode(object) * ((1 << 16) - 1) + number; + } + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof ObjectIntPair)) { + return false; + } + final ObjectIntPair other = (ObjectIntPair)obj; + return object == other.object && number == other.number; + } + } +} diff --git a/java/src/main/java/com/google/protobuf/FieldSet.java b/java/src/main/java/com/google/protobuf/FieldSet.java index 01da3faf..93e55f29 100644 --- a/java/src/main/java/com/google/protobuf/FieldSet.java +++ b/java/src/main/java/com/google/protobuf/FieldSet.java @@ -30,16 +30,13 @@ package com.google.protobuf; -import com.google.protobuf.Descriptors.Descriptor; -import com.google.protobuf.Descriptors.FieldDescriptor; -import com.google.protobuf.Descriptors.EnumValueDescriptor; - import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.TreeMap; import java.util.List; import java.util.Map; +import java.io.IOException; /** * A class which represents an arbitrary set of fields of some message type. @@ -49,43 +46,70 @@ import java.util.Map; * * @author kenton@google.com Kenton Varda */ -final class FieldSet { - private Map fields; +final class FieldSet> { + /** + * Interface for a FieldDescriptor or lite extension descriptor. This + * prevents FieldSet from depending on {@link Descriptors.FieldDescriptor}. + */ + public interface FieldDescriptorLite> + extends Comparable { + int getNumber(); + WireFormat.FieldType getLiteType(); + WireFormat.JavaType getLiteJavaType(); + boolean isRepeated(); + boolean isPacked(); + Internal.EnumLiteMap getEnumType(); + + // If getLiteJavaType() == MESSAGE, this merges a message object of the + // type into a builder of the type. Returns {@code to}. + MessageLite.Builder internalMergeFrom( + MessageLite.Builder to, MessageLite from); + } + + private Map fields; /** Construct a new FieldSet. */ private FieldSet() { // Use a TreeMap because fields need to be in canonical order when // serializing. - this.fields = new TreeMap(); + // TODO(kenton): Maybe use some sort of sparse array instead? It would + // even make sense to store the first 16 or so tags in a flat array + // to make DynamicMessage faster. + fields = new TreeMap(); } /** - * Construct a new FieldSet with the given map. This is only used by - * DEFAULT_INSTANCE, to pass in an immutable empty map. + * Construct an empty FieldSet. This is only used to initialize + * DEFAULT_INSTANCE. */ - private FieldSet(Map fields) { - this.fields = fields; + private FieldSet(final boolean dummy) { + this.fields = Collections.emptyMap(); } /** Construct a new FieldSet. */ - public static FieldSet newFieldSet() { - return new FieldSet(); + public static > + FieldSet newFieldSet() { + return new FieldSet(); } /** Get an immutable empty FieldSet. */ - public static FieldSet emptySet() { + @SuppressWarnings("unchecked") + public static > + FieldSet emptySet() { return DEFAULT_INSTANCE; } - private static final FieldSet DEFAULT_INSTANCE = - new FieldSet(Collections.emptyMap()); + @SuppressWarnings("unchecked") + private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true); /** Make this FieldSet immutable from this point forward. */ @SuppressWarnings("unchecked") public void makeImmutable() { - for (Map.Entry entry: fields.entrySet()) { + for (final Map.Entry entry: + fields.entrySet()) { if (entry.getKey().isRepeated()) { - List value = (List)entry.getValue(); - entry.setValue(Collections.unmodifiableList(value)); + final List value = (List)entry.getValue(); + fields.put(entry.getKey(), Collections.unmodifiableList(value)); } } fields = Collections.unmodifiableMap(fields); @@ -98,56 +122,52 @@ final class FieldSet { fields.clear(); } - /** See {@link Message#getAllFields()}. */ - public Map getAllFields() { + /** + * Get a simple map containing all the fields. + */ + public Map getAllFields() { return Collections.unmodifiableMap(fields); } /** - * Get an interator to the field map. This iterator should not be leaked + * Get an iterator to the field map. This iterator should not be leaked * out of the protobuf library as it is not protected from mutation. */ - public Iterator> iterator() { + public Iterator> iterator() { return fields.entrySet().iterator(); } - /** See {@link Message#hasField(Descriptors.FieldDescriptor)}. */ - public boolean hasField(Descriptors.FieldDescriptor field) { - if (field.isRepeated()) { + /** + * Useful for implementing + * {@link Message#hasField(Descriptors.FieldDescriptor)}. + */ + public boolean hasField(final FieldDescriptorType descriptor) { + if (descriptor.isRepeated()) { throw new IllegalArgumentException( "hasField() can only be called on non-repeated fields."); } - return fields.containsKey(field); + return fields.get(descriptor) != null; } /** - * See {@link Message#getField(Descriptors.FieldDescriptor)}. This method - * returns {@code null} if the field is a singular message type and is not - * set; in this case it is up to the caller to fetch the message's default - * instance. + * Useful for implementing + * {@link Message#getField(Descriptors.FieldDescriptor)}. This method + * returns {@code null} if the field is not set; in this case it is up + * to the caller to fetch the field's default value. */ - public Object getField(Descriptors.FieldDescriptor field) { - Object result = fields.get(field); - if (result == null) { - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - if (field.isRepeated()) { - return Collections.emptyList(); - } else { - return null; - } - } else { - return field.getDefaultValue(); - } - } else { - return result; - } + public Object getField(final FieldDescriptorType descriptor) { + return fields.get(descriptor); } - /** See {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}. */ + /** + * Useful for implementing + * {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}. + */ @SuppressWarnings("unchecked") - public void setField(Descriptors.FieldDescriptor field, Object value) { - if (field.isRepeated()) { + public void setField(final FieldDescriptorType descriptor, + Object value) { + if (descriptor.isRepeated()) { if (!(value instanceof List)) { throw new IllegalArgumentException( "Wrong object type used with protocol message reflection."); @@ -155,78 +175,108 @@ final class FieldSet { // Wrap the contents in a new list so that the caller cannot change // the list's contents after setting it. - List newList = new ArrayList(); + final List newList = new ArrayList(); newList.addAll((List)value); - for (Object element : newList) { - verifyType(field, element); + for (final Object element : newList) { + verifyType(descriptor.getLiteType(), element); } value = newList; } else { - verifyType(field, value); + verifyType(descriptor.getLiteType(), value); } - fields.put(field, value); + fields.put(descriptor, value); } - /** See {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}. */ - public void clearField(Descriptors.FieldDescriptor field) { - fields.remove(field); + /** + * Useful for implementing + * {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}. + */ + public void clearField(final FieldDescriptorType descriptor) { + fields.remove(descriptor); } - /** See {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}. */ - public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) { - if (!field.isRepeated()) { + /** + * Useful for implementing + * {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}. + */ + public int getRepeatedFieldCount(final FieldDescriptorType descriptor) { + if (!descriptor.isRepeated()) { throw new IllegalArgumentException( - "getRepeatedFieldCount() can only be called on repeated fields."); + "getRepeatedField() can only be called on repeated fields."); } - return ((List)getField(field)).size(); + final Object value = fields.get(descriptor); + if (value == null) { + return 0; + } else { + return ((List) value).size(); + } } - /** See {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}. */ - public Object getRepeatedField(Descriptors.FieldDescriptor field, int index) { - if (!field.isRepeated()) { + /** + * Useful for implementing + * {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}. + */ + public Object getRepeatedField(final FieldDescriptorType descriptor, + final int index) { + if (!descriptor.isRepeated()) { throw new IllegalArgumentException( "getRepeatedField() can only be called on repeated fields."); } - return ((List)getField(field)).get(index); + final Object value = fields.get(descriptor); + + if (value == null) { + throw new IndexOutOfBoundsException(); + } else { + return ((List) value).get(index); + } } - /** See {@link Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}. */ + /** + * Useful for implementing + * {@link Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}. + */ @SuppressWarnings("unchecked") - public void setRepeatedField(Descriptors.FieldDescriptor field, int index, - Object value) { - if (!field.isRepeated()) { + public void setRepeatedField(final FieldDescriptorType descriptor, + final int index, + final Object value) { + if (!descriptor.isRepeated()) { throw new IllegalArgumentException( - "setRepeatedField() can only be called on repeated fields."); + "getRepeatedField() can only be called on repeated fields."); } - verifyType(field, value); - - List list = (List)fields.get(field); + final Object list = fields.get(descriptor); if (list == null) { throw new IndexOutOfBoundsException(); } - list.set(index, value); + verifyType(descriptor.getLiteType(), value); + ((List) list).set(index, value); } - /** See {@link Message.Builder#addRepeatedField(Descriptors.FieldDescriptor,Object)}. */ + /** + * Useful for implementing + * {@link Message.Builder#addRepeatedField(Descriptors.FieldDescriptor,Object)}. + */ @SuppressWarnings("unchecked") - public void addRepeatedField(Descriptors.FieldDescriptor field, - Object value) { - if (!field.isRepeated()) { + public void addRepeatedField(final FieldDescriptorType descriptor, + final Object value) { + if (!descriptor.isRepeated()) { throw new IllegalArgumentException( - "setRepeatedField() can only be called on repeated fields."); + "addRepeatedField() can only be called on repeated fields."); } - verifyType(field, value); + verifyType(descriptor.getLiteType(), value); - List list = (List)fields.get(field); - if (list == null) { + final Object existingValue = fields.get(descriptor); + List list; + if (existingValue == null) { list = new ArrayList(); - fields.put(field, list); + fields.put(descriptor, list); + } else { + list = (List) existingValue; } list.add(value); @@ -239,9 +289,14 @@ final class FieldSet { * * @throws IllegalArgumentException The value is not of the right type. */ - private void verifyType(FieldDescriptor field, Object value) { + private static void verifyType(final WireFormat.FieldType type, + final Object value) { + if (value == null) { + throw new NullPointerException(); + } + boolean isValid = false; - switch (field.getJavaType()) { + switch (type.getJavaType()) { case INT: isValid = value instanceof Integer ; break; case LONG: isValid = value instanceof Long ; break; case FLOAT: isValid = value instanceof Float ; break; @@ -250,26 +305,25 @@ final class FieldSet { case STRING: isValid = value instanceof String ; break; case BYTE_STRING: isValid = value instanceof ByteString; break; case ENUM: - isValid = value instanceof EnumValueDescriptor && - ((EnumValueDescriptor)value).getType() == field.getEnumType(); + // TODO(kenton): Caller must do type checking here, I guess. + isValid = value instanceof Internal.EnumLite; break; case MESSAGE: - isValid = value instanceof Message && - ((Message)value).getDescriptorForType() == field.getMessageType(); + // TODO(kenton): Caller must do type checking here, I guess. + isValid = value instanceof MessageLite; break; } if (!isValid) { - // When chaining calls to setField(), it can be hard to tell from - // the stack trace which exact call failed, since the whole chain is - // considered one line of code. So, let's make sure to include the - // field name and other useful info in the exception. + // TODO(kenton): When chaining calls to setField(), it can be hard to + // tell from the stack trace which exact call failed, since the whole + // chain is considered one line of code. It would be nice to print + // more information here, e.g. naming the field. We used to do that. + // But we can't now that FieldSet doesn't use descriptors. Maybe this + // isn't a big deal, though, since it would only really apply when using + // reflection and generally people don't chain reflection setters. throw new IllegalArgumentException( - "Wrong object type used with protocol message reflection. " + - "Message type \"" + field.getContainingType().getFullName() + - "\", field \"" + - (field.isExtension() ? field.getFullName() : field.getName()) + - "\", value was type \"" + value.getClass().getName() + "\"."); + "Wrong object type used with protocol message reflection."); } } @@ -284,17 +338,19 @@ final class FieldSet { */ @SuppressWarnings("unchecked") public boolean isInitialized() { - for (Map.Entry entry : fields.entrySet()) { - FieldDescriptor field = entry.getKey(); - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - if (field.isRepeated()) { - for (Message element : (List) entry.getValue()) { + for (final Map.Entry entry: + fields.entrySet()) { + final FieldDescriptorType descriptor = entry.getKey(); + if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { + if (descriptor.isRepeated()) { + for (final MessageLite element: + (List) entry.getValue()) { if (!element.isInitialized()) { return false; } } } else { - if (!((Message) entry.getValue()).isInitialized()) { + if (!((MessageLite) entry.getValue()).isInitialized()) { return false; } } @@ -305,59 +361,17 @@ final class FieldSet { } /** - * Like {@link #isInitialized()}, but also checks for the presence of - * all required fields in the given type. + * Given a field type, return the wire type. + * + * @returns One of the {@code WIRETYPE_} constants defined in + * {@link WireFormat}. */ - @SuppressWarnings("unchecked") - public boolean isInitialized(Descriptor type) { - // Check that all required fields are present. - for (FieldDescriptor field : type.getFields()) { - if (field.isRequired()) { - if (!hasField(field)) { - return false; - } - } - } - - // Check that embedded messages are initialized. - return isInitialized(); - } - - /** See {@link Message.Builder#mergeFrom(Message)}. */ - @SuppressWarnings("unchecked") - public void mergeFrom(Message other) { - // Note: We don't attempt to verify that other's fields have valid - // types. Doing so would be a losing battle. We'd have to verify - // all sub-messages as well, and we'd have to make copies of all of - // them to insure that they don't change after verification (since - // the Message interface itself cannot enforce immutability of - // implementations). - // TODO(kenton): Provide a function somewhere called makeDeepCopy() - // which allows people to make secure deep copies of messages. - - for (Map.Entry entry : - other.getAllFields().entrySet()) { - FieldDescriptor field = entry.getKey(); - if (field.isRepeated()) { - List existingValue = (List)fields.get(field); - if (existingValue == null) { - existingValue = new ArrayList(); - fields.put(field, existingValue); - } - existingValue.addAll((List)entry.getValue()); - } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - Message existingValue = (Message)fields.get(field); - if (existingValue == null) { - setField(field, entry.getValue()); - } else { - setField(field, - existingValue.toBuilder() - .mergeFrom((Message)entry.getValue()) - .build()); - } - } else { - setField(field, entry.getValue()); - } + static int getWireFormatForFieldType(final WireFormat.FieldType type, + boolean isPacked) { + if (isPacked) { + return WireFormat.WIRETYPE_LENGTH_DELIMITED; + } else { + return type.getWireType(); } } @@ -365,360 +379,334 @@ final class FieldSet { * Like {@link #mergeFrom(Message)}, but merges from another {@link FieldSet}. */ @SuppressWarnings("unchecked") - public void mergeFrom(FieldSet other) { - for (Map.Entry entry : other.fields.entrySet()) { - FieldDescriptor field = entry.getKey(); - Object value = entry.getValue(); - - if (field.isRepeated()) { - List existingValue = (List)fields.get(field); - if (existingValue == null) { - existingValue = new ArrayList(); - fields.put(field, existingValue); + public void mergeFrom(final FieldSet other) { + for (final Map.Entry entry: + other.fields.entrySet()) { + final FieldDescriptorType descriptor = entry.getKey(); + final Object otherValue = entry.getValue(); + + if (descriptor.isRepeated()) { + Object value = fields.get(descriptor); + if (value == null) { + // Our list is empty, but we still need to make a defensive copy of + // the other list since we don't know if the other FieldSet is still + // mutable. + fields.put(descriptor, new ArrayList((List) otherValue)); + } else { + // Concatenate the lists. + ((List) value).addAll((List) otherValue); } - existingValue.addAll((List)value); - } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - Message existingValue = (Message)fields.get(field); - if (existingValue == null) { - setField(field, value); + } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { + Object value = fields.get(descriptor); + if (value == null) { + fields.put(descriptor, otherValue); } else { - setField(field, - existingValue.toBuilder() - .mergeFrom((Message)value) + // Merge the messages. + fields.put(descriptor, + descriptor.internalMergeFrom( + ((MessageLite) value).toBuilder(), (MessageLite) otherValue) .build()); } + } else { - setField(field, value); + fields.put(descriptor, otherValue); } } } - // TODO(kenton): Move parsing code into AbstractMessage, since it no longer - // uses any special knowledge from FieldSet. + // TODO(kenton): Move static parsing and serialization methods into some + // other class. Probably WireFormat. /** - * See {@link Message.Builder#mergeFrom(CodedInputStream)}. - * @param builder The {@code Builder} for the target message. + * Read a field of any primitive type from a CodedInputStream. Enums, + * groups, and embedded messages are not handled by this method. + * + * @param input The stream from which to read. + * @param type Declared type of the field. + * @return An object representing the field's value, of the exact + * type which would be returned by + * {@link Message#getField(Descriptors.FieldDescriptor)} for + * this field. */ - public static void mergeFrom(CodedInputStream input, - UnknownFieldSet.Builder unknownFields, - ExtensionRegistry extensionRegistry, - Message.Builder builder) - throws java.io.IOException { - while (true) { - int tag = input.readTag(); - if (tag == 0) { - break; - } + public static Object readPrimitiveField( + CodedInputStream input, + final WireFormat.FieldType type) throws IOException { + switch (type) { + case DOUBLE : return input.readDouble (); + case FLOAT : return input.readFloat (); + case INT64 : return input.readInt64 (); + case UINT64 : return input.readUInt64 (); + case INT32 : return input.readInt32 (); + case FIXED64 : return input.readFixed64 (); + case FIXED32 : return input.readFixed32 (); + case BOOL : return input.readBool (); + case STRING : return input.readString (); + case BYTES : return input.readBytes (); + case UINT32 : return input.readUInt32 (); + case SFIXED32: return input.readSFixed32(); + case SFIXED64: return input.readSFixed64(); + case SINT32 : return input.readSInt32 (); + case SINT64 : return input.readSInt64 (); + + case GROUP: + throw new IllegalArgumentException( + "readPrimitiveField() cannot handle nested groups."); + case MESSAGE: + throw new IllegalArgumentException( + "readPrimitiveField() cannot handle embedded messages."); + case ENUM: + // We don't handle enums because we don't know what to do if the + // value is not recognized. + throw new IllegalArgumentException( + "readPrimitiveField() cannot handle enums."); + } - if (!mergeFieldFrom(input, unknownFields, extensionRegistry, - builder, tag)) { - // end group tag - break; - } + throw new RuntimeException( + "There is no way to get here, but the compiler thinks otherwise."); + } + + /** See {@link Message#writeTo(CodedOutputStream)}. */ + public void writeTo(final CodedOutputStream output) + throws IOException { + for (final Map.Entry entry: + fields.entrySet()) { + writeField(entry.getKey(), entry.getValue(), output); } } /** - * Like {@link #mergeFrom(CodedInputStream, UnknownFieldSet.Builder, - * ExtensionRegistry, Message.Builder)}, but parses a single field. - * @param tag The tag, which should have already been read. - * @return {@code true} unless the tag is an end-group tag. + * Like {@link #writeTo} but uses MessageSet wire format. */ - @SuppressWarnings("unchecked") - public static boolean mergeFieldFrom( - CodedInputStream input, - UnknownFieldSet.Builder unknownFields, - ExtensionRegistry extensionRegistry, - Message.Builder builder, - int tag) throws java.io.IOException { - Descriptor type = builder.getDescriptorForType(); - - if (type.getOptions().getMessageSetWireFormat() && - tag == WireFormat.MESSAGE_SET_ITEM_TAG) { - mergeMessageSetExtensionFromCodedStream( - input, unknownFields, extensionRegistry, builder); - return true; - } - - int wireType = WireFormat.getTagWireType(tag); - int fieldNumber = WireFormat.getTagFieldNumber(tag); - - FieldDescriptor field; - Message defaultInstance = null; - - if (type.isExtensionNumber(fieldNumber)) { - ExtensionRegistry.ExtensionInfo extension = - extensionRegistry.findExtensionByNumber(type, fieldNumber); - if (extension == null) { - field = null; + public void writeMessageSetTo(final CodedOutputStream output) + throws IOException { + for (final Map.Entry entry: + fields.entrySet()) { + final FieldDescriptorType descriptor = entry.getKey(); + if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE && + !descriptor.isRepeated() && !descriptor.isPacked()) { + output.writeMessageSetExtension(entry.getKey().getNumber(), + (MessageLite) entry.getValue()); } else { - field = extension.descriptor; - defaultInstance = extension.defaultInstance; + writeField(descriptor, entry.getValue(), output); } - } else { - field = type.findFieldByNumber(fieldNumber); } + } - if (field == null || - wireType != WireFormat.getWireFormatForField(field)) { - // Unknown field or wrong wire type. Skip. - return unknownFields.mergeFieldFrom(tag, input); + /** + * Write a single tag-value pair to the stream. + * + * @param output The output stream. + * @param type The field's type. + * @param number The field's number. + * @param value Object representing the field's value. Must be of the exact + * type which would be returned by + * {@link Message#getField(Descriptors.FieldDescriptor)} for + * this field. + */ + private static void writeElement(final CodedOutputStream output, + final WireFormat.FieldType type, + final int number, + final Object value) throws IOException { + // Special case for groups, which need a start and end tag; other fields + // can just use writeTag() and writeFieldNoTag(). + if (type == WireFormat.FieldType.GROUP) { + output.writeGroup(number, (MessageLite) value); } else { - if (field.getOptions().getPacked()) { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (field.getType() == FieldDescriptor.Type.ENUM) { - while (input.getBytesUntilLimit() > 0) { - int rawValue = input.readEnum(); - Object value = field.getEnumType().findValueByNumber(rawValue); - if (value == null) { - // If the number isn't recognized as a valid value for this - // enum, drop it (don't even add it to unknownFields). - return true; - } - builder.addRepeatedField(field, value); - } - } else { - while (input.getBytesUntilLimit() > 0) { - Object value = input.readPrimitiveField(field.getType()); - builder.addRepeatedField(field, value); - } - } - input.popLimit(limit); - } else { - Object value; - switch (field.getType()) { - case GROUP: { - Message.Builder subBuilder; - if (defaultInstance != null) { - subBuilder = defaultInstance.newBuilderForType(); - } else { - subBuilder = builder.newBuilderForField(field); - } - if (!field.isRepeated()) { - subBuilder.mergeFrom((Message) builder.getField(field)); - } - input.readGroup(field.getNumber(), subBuilder, extensionRegistry); - value = subBuilder.build(); - break; - } - case MESSAGE: { - Message.Builder subBuilder; - if (defaultInstance != null) { - subBuilder = defaultInstance.newBuilderForType(); - } else { - subBuilder = builder.newBuilderForField(field); - } - if (!field.isRepeated()) { - subBuilder.mergeFrom((Message) builder.getField(field)); - } - input.readMessage(subBuilder, extensionRegistry); - value = subBuilder.build(); - break; - } - case ENUM: { - int rawValue = input.readEnum(); - value = field.getEnumType().findValueByNumber(rawValue); - // If the number isn't recognized as a valid value for this enum, - // drop it. - if (value == null) { - unknownFields.mergeVarintField(fieldNumber, rawValue); - return true; - } - break; - } - default: - value = input.readPrimitiveField(field.getType()); - break; - } - - if (field.isRepeated()) { - builder.addRepeatedField(field, value); - } else { - builder.setField(field, value); - } - } + output.writeTag(number, getWireFormatForFieldType(type, false)); + writeElementNoTag(output, type, value); } - - return true; } - /** Called by {@code #mergeFieldFrom()} to parse a MessageSet extension. */ - private static void mergeMessageSetExtensionFromCodedStream( - CodedInputStream input, - UnknownFieldSet.Builder unknownFields, - ExtensionRegistry extensionRegistry, - Message.Builder builder) throws java.io.IOException { - Descriptor type = builder.getDescriptorForType(); - - // The wire format for MessageSet is: - // message MessageSet { - // repeated group Item = 1 { - // required int32 typeId = 2; - // required bytes message = 3; - // } - // } - // "typeId" is the extension's field number. The extension can only be - // a message type, where "message" contains the encoded bytes of that - // message. - // - // In practice, we will probably never see a MessageSet item in which - // the message appears before the type ID, or where either field does not - // appear exactly once. However, in theory such cases are valid, so we - // should be prepared to accept them. - - int typeId = 0; - ByteString rawBytes = null; // If we encounter "message" before "typeId" - Message.Builder subBuilder = null; - FieldDescriptor field = null; - - while (true) { - int tag = input.readTag(); - if (tag == 0) { + /** + * Write a field of arbitrary type, without its tag, to the stream. + * + * @param output The output stream. + * @param type The field's type. + * @param value Object representing the field's value. Must be of the exact + * type which would be returned by + * {@link Message#getField(Descriptors.FieldDescriptor)} for + * this field. + */ + private static void writeElementNoTag( + final CodedOutputStream output, + final WireFormat.FieldType type, + final Object value) throws IOException { + switch (type) { + case DOUBLE : output.writeDoubleNoTag ((Double ) value); break; + case FLOAT : output.writeFloatNoTag ((Float ) value); break; + case INT64 : output.writeInt64NoTag ((Long ) value); break; + case UINT64 : output.writeUInt64NoTag ((Long ) value); break; + case INT32 : output.writeInt32NoTag ((Integer ) value); break; + case FIXED64 : output.writeFixed64NoTag ((Long ) value); break; + case FIXED32 : output.writeFixed32NoTag ((Integer ) value); break; + case BOOL : output.writeBoolNoTag ((Boolean ) value); break; + case STRING : output.writeStringNoTag ((String ) value); break; + case GROUP : output.writeGroupNoTag ((MessageLite) value); break; + case MESSAGE : output.writeMessageNoTag ((MessageLite) value); break; + case BYTES : output.writeBytesNoTag ((ByteString ) value); break; + case UINT32 : output.writeUInt32NoTag ((Integer ) value); break; + case SFIXED32: output.writeSFixed32NoTag((Integer ) value); break; + case SFIXED64: output.writeSFixed64NoTag((Long ) value); break; + case SINT32 : output.writeSInt32NoTag ((Integer ) value); break; + case SINT64 : output.writeSInt64NoTag ((Long ) value); break; + + case ENUM: + output.writeEnumNoTag(((Internal.EnumLite) value).getNumber()); break; - } + } + } - if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) { - typeId = input.readUInt32(); - // Zero is not a valid type ID. - if (typeId != 0) { - ExtensionRegistry.ExtensionInfo extension = - extensionRegistry.findExtensionByNumber(type, typeId); - if (extension != null) { - field = extension.descriptor; - subBuilder = extension.defaultInstance.newBuilderForType(); - Message originalMessage = (Message)builder.getField(field); - if (originalMessage != null) { - subBuilder.mergeFrom(originalMessage); - } - if (rawBytes != null) { - // We already encountered the message. Parse it now. - subBuilder.mergeFrom( - CodedInputStream.newInstance(rawBytes.newInput())); - rawBytes = null; - } - } else { - // Unknown extension number. If we already saw data, put it - // in rawBytes. - if (rawBytes != null) { - unknownFields.mergeField(typeId, - UnknownFieldSet.Field.newBuilder() - .addLengthDelimited(rawBytes) - .build()); - rawBytes = null; - } - } + /** Write a single field. */ + public static void writeField(final FieldDescriptorLite descriptor, + final Object value, + final CodedOutputStream output) + throws IOException { + WireFormat.FieldType type = descriptor.getLiteType(); + int number = descriptor.getNumber(); + if (descriptor.isRepeated()) { + final List valueList = (List)value; + if (descriptor.isPacked()) { + output.writeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED); + // Compute the total data size so the length can be written. + int dataSize = 0; + for (final Object element : valueList) { + dataSize += computeElementSizeNoTag(type, element); } - } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) { - if (typeId == 0) { - // We haven't seen a type ID yet, so we have to store the raw bytes - // for now. - rawBytes = input.readBytes(); - } else if (subBuilder == null) { - // We don't know how to parse this. Ignore it. - unknownFields.mergeField(typeId, - UnknownFieldSet.Field.newBuilder() - .addLengthDelimited(input.readBytes()) - .build()); - } else { - // We already know the type, so we can parse directly from the input - // with no copying. Hooray! - input.readMessage(subBuilder, extensionRegistry); + output.writeRawVarint32(dataSize); + // Write the data itself, without any tags. + for (final Object element : valueList) { + writeElementNoTag(output, type, element); } } else { - // Unknown tag. Skip it. - if (!input.skipField(tag)) { - break; // end of group + for (final Object element : valueList) { + writeElement(output, type, number, element); } } - } - - input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG); - - if (subBuilder != null) { - builder.setField(field, subBuilder.build()); + } else { + writeElement(output, type, number, value); } } - /** See {@link Message#writeTo(CodedOutputStream)}. */ - public void writeTo(CodedOutputStream output) - throws java.io.IOException { - for (Map.Entry entry : fields.entrySet()) { - writeField(entry.getKey(), entry.getValue(), output); + /** + * See {@link Message#getSerializedSize()}. It's up to the caller to cache + * the resulting size if desired. + */ + public int getSerializedSize() { + int size = 0; + for (final Map.Entry entry: + fields.entrySet()) { + size += computeFieldSize(entry.getKey(), entry.getValue()); } + return size; } - /** Write a single field. */ - public void writeField(FieldDescriptor field, Object value, - CodedOutputStream output) throws java.io.IOException { - if (field.isExtension() && - field.getContainingType().getOptions().getMessageSetWireFormat()) { - output.writeMessageSetExtension(field.getNumber(), (Message)value); - } else { - if (field.isRepeated()) { - List valueList = (List)value; - if (field.getOptions().getPacked()) { - output.writeTag(field.getNumber(), - WireFormat.WIRETYPE_LENGTH_DELIMITED); - // Compute the total data size so the length can be written. - int dataSize = 0; - for (Object element : valueList) { - dataSize += output.computeFieldSizeNoTag(field.getType(), element); - } - output.writeRawVarint32(dataSize); - // Write the data itself, without any tags. - for (Object element : valueList) { - output.writeFieldNoTag(field.getType(), element); - } - } else { - for (Object element : valueList) { - output.writeField(field.getType(), field.getNumber(), element); - } - } + /** + * Like {@link #getSerializedSize} but uses MessageSet wire format. + */ + public int getMessageSetSerializedSize() { + int size = 0; + for (final Map.Entry entry: + fields.entrySet()) { + final FieldDescriptorType descriptor = entry.getKey(); + if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE && + !descriptor.isRepeated() && !descriptor.isPacked()) { + size += CodedOutputStream.computeMessageSetExtensionSize( + entry.getKey().getNumber(), (MessageLite) entry.getValue()); } else { - output.writeField(field.getType(), field.getNumber(), value); + size += computeFieldSize(descriptor, entry.getValue()); } } + return size; } /** - * See {@link Message#getSerializedSize()}. It's up to the caller to cache - * the resulting size if desired. + * Compute the number of bytes that would be needed to encode a + * single tag/value pair of arbitrary type. + * + * @param type The field's type. + * @param number The field's number. + * @param value Object representing the field's value. Must be of the exact + * type which would be returned by + * {@link Message#getField(Descriptors.FieldDescriptor)} for + * this field. */ - public int getSerializedSize() { - int size = 0; - for (Map.Entry entry : fields.entrySet()) { - FieldDescriptor field = entry.getKey(); - Object value = entry.getValue(); + private static int computeElementSize( + final WireFormat.FieldType type, + final int number, final Object value) { + int tagSize = CodedOutputStream.computeTagSize(number); + if (type == WireFormat.FieldType.GROUP) { + tagSize *= 2; + } + return tagSize + computeElementSizeNoTag(type, value); + } - if (field.isExtension() && - field.getContainingType().getOptions().getMessageSetWireFormat()) { - size += CodedOutputStream.computeMessageSetExtensionSize( - field.getNumber(), (Message) value); + /** + * Compute the number of bytes that would be needed to encode a + * particular value of arbitrary type, excluding tag. + * + * @param type The field's type. + * @param value Object representing the field's value. Must be of the exact + * type which would be returned by + * {@link Message#getField(Descriptors.FieldDescriptor)} for + * this field. + */ + private static int computeElementSizeNoTag( + final WireFormat.FieldType type, final Object value) { + switch (type) { + // Note: Minor violation of 80-char limit rule here because this would + // actually be harder to read if we wrapped the lines. + case DOUBLE : return CodedOutputStream.computeDoubleSizeNoTag ((Double )value); + case FLOAT : return CodedOutputStream.computeFloatSizeNoTag ((Float )value); + case INT64 : return CodedOutputStream.computeInt64SizeNoTag ((Long )value); + case UINT64 : return CodedOutputStream.computeUInt64SizeNoTag ((Long )value); + case INT32 : return CodedOutputStream.computeInt32SizeNoTag ((Integer )value); + case FIXED64 : return CodedOutputStream.computeFixed64SizeNoTag ((Long )value); + case FIXED32 : return CodedOutputStream.computeFixed32SizeNoTag ((Integer )value); + case BOOL : return CodedOutputStream.computeBoolSizeNoTag ((Boolean )value); + case STRING : return CodedOutputStream.computeStringSizeNoTag ((String )value); + case GROUP : return CodedOutputStream.computeGroupSizeNoTag ((MessageLite)value); + case MESSAGE : return CodedOutputStream.computeMessageSizeNoTag ((MessageLite)value); + case BYTES : return CodedOutputStream.computeBytesSizeNoTag ((ByteString )value); + case UINT32 : return CodedOutputStream.computeUInt32SizeNoTag ((Integer )value); + case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer )value); + case SFIXED64: return CodedOutputStream.computeSFixed64SizeNoTag((Long )value); + case SINT32 : return CodedOutputStream.computeSInt32SizeNoTag ((Integer )value); + case SINT64 : return CodedOutputStream.computeSInt64SizeNoTag ((Long )value); + + case ENUM: + return CodedOutputStream.computeEnumSizeNoTag( + ((Internal.EnumLite) value).getNumber()); + } + + throw new RuntimeException( + "There is no way to get here, but the compiler thinks otherwise."); + } + + /** + * Compute the number of bytes needed to encode a particular field. + */ + public static int computeFieldSize(final FieldDescriptorLite descriptor, + final Object value) { + WireFormat.FieldType type = descriptor.getLiteType(); + int number = descriptor.getNumber(); + if (descriptor.isRepeated()) { + if (descriptor.isPacked()) { + int dataSize = 0; + for (final Object element : (List)value) { + dataSize += computeElementSizeNoTag(type, element); + } + return dataSize + + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeRawVarint32Size(dataSize); } else { - if (field.isRepeated()) { - if (field.getOptions().getPacked()) { - int dataSize = 0; - for (Object element : (List)value) { - dataSize += CodedOutputStream.computeFieldSizeNoTag( - field.getType(), element); - } - size += dataSize + - CodedOutputStream.computeTagSize(field.getNumber()) + - CodedOutputStream.computeRawVarint32Size(dataSize); - } else { - for (Object element : (List)value) { - size += CodedOutputStream.computeFieldSize( - field.getType(), field.getNumber(), element); - } - } - } else { - size += CodedOutputStream.computeFieldSize( - field.getType(), field.getNumber(), value); + int size = 0; + for (final Object element : (List)value) { + size += computeElementSize(type, number, element); } + return size; } + } else { + return computeElementSize(type, number, value); } - return size; } } diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java index 77c88c30..4994faad 100644 --- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java +++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java @@ -36,8 +36,8 @@ import com.google.protobuf.Descriptors.FieldDescriptor; import java.io.IOException; import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -69,13 +69,13 @@ public abstract class GeneratedMessage extends AbstractMessage { } /** Internal helper which returns a mutable map. */ - private final Map getAllFieldsMutable() { - TreeMap result = + private Map getAllFieldsMutable() { + final TreeMap result = new TreeMap(); - Descriptor descriptor = internalGetFieldAccessorTable().descriptor; - for (FieldDescriptor field : descriptor.getFields()) { + final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; + for (final FieldDescriptor field : descriptor.getFields()) { if (field.isRepeated()) { - List value = (List) getField(field); + final List value = (List) getField(field); if (!value.isEmpty()) { result.put(field, value); } @@ -88,8 +88,9 @@ public abstract class GeneratedMessage extends AbstractMessage { return result; } + @Override public boolean isInitialized() { - for (FieldDescriptor field : getDescriptorForType().getFields()) { + for (final FieldDescriptor field : getDescriptorForType().getFields()) { // Check that all required fields are present. if (field.isRequired()) { if (!hasField(field)) { @@ -99,9 +100,9 @@ public abstract class GeneratedMessage extends AbstractMessage { // Check that embedded messages are initialized. if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { if (field.isRepeated()) { - @SuppressWarnings("unchecked") + @SuppressWarnings("unchecked") final List messageList = (List) getField(field); - for (Message element : messageList) { + for (final Message element : messageList) { if (!element.isInitialized()) { return false; } @@ -121,20 +122,20 @@ public abstract class GeneratedMessage extends AbstractMessage { return Collections.unmodifiableMap(getAllFieldsMutable()); } - public boolean hasField(Descriptors.FieldDescriptor field) { + public boolean hasField(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field).has(this); } - public Object getField(FieldDescriptor field) { + public Object getField(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field).get(this); } - public int getRepeatedFieldCount(FieldDescriptor field) { + public int getRepeatedFieldCount(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field) .getRepeatedCount(this); } - public Object getRepeatedField(FieldDescriptor field, int index) { + public Object getRepeatedField(final FieldDescriptor field, final int index) { return internalGetFieldAccessorTable().getField(field) .getRepeated(this, index); } @@ -148,6 +149,15 @@ public abstract class GeneratedMessage extends AbstractMessage { extends AbstractMessage.Builder { protected Builder() {} + // This is implemented here only to work around an apparent bug in the + // Java compiler and/or build system. See bug #1898463. The mere presence + // of this dummy clone() implementation makes it go away. + @Override + public BuilderType clone() { + throw new UnsupportedOperationException( + "This is supposed to be overridden by subclasses."); + } + /** * Get the message being built. We don't just pass this to the * constructor because it becomes null when build() is called. @@ -163,55 +173,24 @@ public abstract class GeneratedMessage extends AbstractMessage { return internalGetResult().internalGetFieldAccessorTable(); } - public BuilderType mergeFrom(Message other) { - if (other.getDescriptorForType() != - internalGetFieldAccessorTable().descriptor) { - throw new IllegalArgumentException("Message type mismatch."); - } - - for (Map.Entry entry : - other.getAllFields().entrySet()) { - FieldDescriptor field = entry.getKey(); - if (field.isRepeated()) { - // Concatenate repeated fields. - for (Object element : (List) entry.getValue()) { - addRepeatedField(field, element); - } - } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE && - hasField(field)) { - // Merge singular embedded messages. - Message oldValue = (Message) getField(field); - setField(field, - oldValue.newBuilderForType() - .mergeFrom(oldValue) - .mergeFrom((Message) entry.getValue()) - .buildPartial()); - } else { - // Just overwrite. - setField(field, entry.getValue()); - } - } - return (BuilderType) this; - } - public Descriptor getDescriptorForType() { return internalGetFieldAccessorTable().descriptor; } - public Map getAllFields() { + public Map getAllFields() { return internalGetResult().getAllFields(); } public Message.Builder newBuilderForField( - Descriptors.FieldDescriptor field) { + final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field).newBuilder(); } - public boolean hasField(Descriptors.FieldDescriptor field) { + public boolean hasField(final FieldDescriptor field) { return internalGetResult().hasField(field); } - public Object getField(Descriptors.FieldDescriptor field) { + public Object getField(final FieldDescriptor field) { if (field.isRepeated()) { // The underlying list object is still modifiable at this point. // Make sure not to expose the modifiable list to the caller. @@ -222,35 +201,35 @@ public abstract class GeneratedMessage extends AbstractMessage { } } - public BuilderType setField(Descriptors.FieldDescriptor field, - Object value) { + public BuilderType setField(final FieldDescriptor field, + final Object value) { internalGetFieldAccessorTable().getField(field).set(this, value); return (BuilderType) this; } - public BuilderType clearField(Descriptors.FieldDescriptor field) { + public BuilderType clearField(final FieldDescriptor field) { internalGetFieldAccessorTable().getField(field).clear(this); return (BuilderType) this; } - public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) { + public int getRepeatedFieldCount(final FieldDescriptor field) { return internalGetResult().getRepeatedFieldCount(field); } - public Object getRepeatedField(Descriptors.FieldDescriptor field, - int index) { + public Object getRepeatedField(final FieldDescriptor field, + final int index) { return internalGetResult().getRepeatedField(field, index); } - public BuilderType setRepeatedField(Descriptors.FieldDescriptor field, - int index, Object value) { + public BuilderType setRepeatedField(final FieldDescriptor field, + final int index, final Object value) { internalGetFieldAccessorTable().getField(field) .setRepeated(this, index, value); return (BuilderType) this; } - public BuilderType addRepeatedField(Descriptors.FieldDescriptor field, - Object value) { + public BuilderType addRepeatedField(final FieldDescriptor field, + final Object value) { internalGetFieldAccessorTable().getField(field).addRepeated(this, value); return (BuilderType) this; } @@ -259,13 +238,16 @@ public abstract class GeneratedMessage extends AbstractMessage { return internalGetResult().unknownFields; } - public final BuilderType setUnknownFields(UnknownFieldSet unknownFields) { + public final BuilderType setUnknownFields( + final UnknownFieldSet unknownFields) { internalGetResult().unknownFields = unknownFields; return (BuilderType) this; } - public final BuilderType mergeUnknownFields(UnknownFieldSet unknownFields) { - GeneratedMessage result = internalGetResult(); + @Override + public final BuilderType mergeUnknownFields( + final UnknownFieldSet unknownFields) { + final GeneratedMessage result = internalGetResult(); result.unknownFields = UnknownFieldSet.newBuilder(result.unknownFields) .mergeFrom(unknownFields) @@ -281,36 +263,13 @@ public abstract class GeneratedMessage extends AbstractMessage { * Called by subclasses to parse an unknown field. * @return {@code true} unless the tag is an end-group tag. */ - protected boolean parseUnknownField(CodedInputStream input, - UnknownFieldSet.Builder unknownFields, - ExtensionRegistry extensionRegistry, - int tag) - throws IOException { + protected boolean parseUnknownField( + final CodedInputStream input, + final UnknownFieldSet.Builder unknownFields, + final ExtensionRegistryLite extensionRegistry, + final int tag) throws IOException { return unknownFields.mergeFieldFrom(tag, input); } - - /** - * Adds the {@code values} to the {@code list}. - * - * @throws NullPointerException if any of the elements of {@code values} is - * null. - */ - protected void addAll(Iterable values, Collection list) { - for (T value : values) { - if (value == null) { - throw new NullPointerException(); - } - } - if (values instanceof Collection) { - @SuppressWarnings("unsafe") - Collection collection = (Collection) values; - list.addAll(collection); - } else { - for (T value : values) { - list.add(value); - } - } - } } // ================================================================= @@ -355,10 +314,10 @@ public abstract class GeneratedMessage extends AbstractMessage { MessageType extends ExtendableMessage> extends GeneratedMessage { protected ExtendableMessage() {} - private final FieldSet extensions = FieldSet.newFieldSet(); + private final FieldSet extensions = FieldSet.newFieldSet(); - private final void verifyExtensionContainingType( - GeneratedExtension extension) { + private void verifyExtensionContainingType( + final GeneratedExtension extension) { if (extension.getDescriptor().getContainingType() != getDescriptorForType()) { // This can only happen if someone uses unchecked operations. @@ -372,26 +331,33 @@ public abstract class GeneratedMessage extends AbstractMessage { /** Check if a singular extension is present. */ public final boolean hasExtension( - GeneratedExtension extension) { + final GeneratedExtension extension) { verifyExtensionContainingType(extension); return extensions.hasField(extension.getDescriptor()); } /** Get the number of elements in a repeated extension. */ public final int getExtensionCount( - GeneratedExtension> extension) { + final GeneratedExtension> extension) { verifyExtensionContainingType(extension); - return extensions.getRepeatedFieldCount(extension.getDescriptor()); + final FieldDescriptor descriptor = extension.getDescriptor(); + return extensions.getRepeatedFieldCount(descriptor); } /** Get the value of an extension. */ @SuppressWarnings("unchecked") public final Type getExtension( - GeneratedExtension extension) { + final GeneratedExtension extension) { verifyExtensionContainingType(extension); - Object value = extensions.getField(extension.getDescriptor()); + FieldDescriptor descriptor = extension.getDescriptor(); + final Object value = extensions.getField(descriptor); if (value == null) { - return (Type) extension.getMessageDefaultInstance(); + if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + return (Type) extension.getMessageDefaultInstance(); + } else { + return (Type) extension.fromReflectionType( + descriptor.getDefaultValue()); + } } else { return (Type) extension.fromReflectionType(value); } @@ -400,10 +366,12 @@ public abstract class GeneratedMessage extends AbstractMessage { /** Get one element of a repeated extension. */ @SuppressWarnings("unchecked") public final Type getExtension( - GeneratedExtension> extension, int index) { + final GeneratedExtension> extension, + final int index) { verifyExtensionContainingType(extension); + FieldDescriptor descriptor = extension.getDescriptor(); return (Type) extension.singularFromReflectionType( - extensions.getRepeatedField(extension.getDescriptor(), index)); + extensions.getRepeatedField(descriptor, index)); } /** Called by subclasses to check if all extensions are initialized. */ @@ -411,6 +379,7 @@ public abstract class GeneratedMessage extends AbstractMessage { return extensions.isInitialized(); } + @Override public boolean isInitialized() { return super.isInitialized() && extensionsAreInitialized(); } @@ -425,20 +394,30 @@ public abstract class GeneratedMessage extends AbstractMessage { // Imagine how much simpler this code would be if Java iterators had // a way to get the next element without advancing the iterator. - final Iterator> iter = + private final Iterator> iter = extensions.iterator(); - Map.Entry next = null; + private Map.Entry next; + private final boolean messageSetWireFormat; - private ExtensionWriter() { + private ExtensionWriter(final boolean messageSetWireFormat) { if (iter.hasNext()) { next = iter.next(); } + this.messageSetWireFormat = messageSetWireFormat; } - public void writeUntil(int end, CodedOutputStream output) + public void writeUntil(final int end, final CodedOutputStream output) throws IOException { while (next != null && next.getKey().getNumber() < end) { - extensions.writeField(next.getKey(), next.getValue(), output); + FieldDescriptor descriptor = next.getKey(); + if (messageSetWireFormat && descriptor.getLiteJavaType() == + WireFormat.JavaType.MESSAGE && + !descriptor.isRepeated()) { + output.writeMessageSetExtension(descriptor.getNumber(), + (Message) next.getValue()); + } else { + FieldSet.writeField(descriptor, next.getValue(), output); + } if (iter.hasNext()) { next = iter.next(); } else { @@ -449,24 +428,32 @@ public abstract class GeneratedMessage extends AbstractMessage { } protected ExtensionWriter newExtensionWriter() { - return new ExtensionWriter(); + return new ExtensionWriter(false); + } + protected ExtensionWriter newMessageSetExtensionWriter() { + return new ExtensionWriter(true); } /** Called by subclasses to compute the size of extensions. */ protected int extensionsSerializedSize() { return extensions.getSerializedSize(); } + protected int extensionsSerializedSizeAsMessageSet() { + return extensions.getMessageSetSerializedSize(); + } // --------------------------------------------------------------- // Reflection - public Map getAllFields() { - Map result = super.getAllFieldsMutable(); + @Override + public Map getAllFields() { + final Map result = super.getAllFieldsMutable(); result.putAll(extensions.getAllFields()); return Collections.unmodifiableMap(result); } - public boolean hasField(FieldDescriptor field) { + @Override + public boolean hasField(final FieldDescriptor field) { if (field.isExtension()) { verifyContainingType(field); return extensions.hasField(field); @@ -475,14 +462,19 @@ public abstract class GeneratedMessage extends AbstractMessage { } } - public Object getField(FieldDescriptor field) { + @Override + public Object getField(final FieldDescriptor field) { if (field.isExtension()) { verifyContainingType(field); - Object value = extensions.getField(field); + final Object value = extensions.getField(field); if (value == null) { - // Lacking an ExtensionRegistry, we have no way to determine the - // extension's real type, so we return a DynamicMessage. - return DynamicMessage.getDefaultInstance(field.getMessageType()); + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + // Lacking an ExtensionRegistry, we have no way to determine the + // extension's real type, so we return a DynamicMessage. + return DynamicMessage.getDefaultInstance(field.getMessageType()); + } else { + return field.getDefaultValue(); + } } else { return value; } @@ -491,7 +483,8 @@ public abstract class GeneratedMessage extends AbstractMessage { } } - public int getRepeatedFieldCount(FieldDescriptor field) { + @Override + public int getRepeatedFieldCount(final FieldDescriptor field) { if (field.isExtension()) { verifyContainingType(field); return extensions.getRepeatedFieldCount(field); @@ -500,7 +493,9 @@ public abstract class GeneratedMessage extends AbstractMessage { } } - public Object getRepeatedField(FieldDescriptor field, int index) { + @Override + public Object getRepeatedField(final FieldDescriptor field, + final int index) { if (field.isExtension()) { verifyContainingType(field); return extensions.getRepeatedField(field, index); @@ -509,7 +504,7 @@ public abstract class GeneratedMessage extends AbstractMessage { } } - private void verifyContainingType(FieldDescriptor field) { + private void verifyContainingType(final FieldDescriptor field) { if (field.getContainingType() != getDescriptorForType()) { throw new IllegalArgumentException( "FieldDescriptor does not match message type."); @@ -558,70 +553,87 @@ public abstract class GeneratedMessage extends AbstractMessage { public abstract static class ExtendableBuilder< MessageType extends ExtendableMessage, BuilderType extends ExtendableBuilder> - extends GeneratedMessage.Builder { + extends Builder { protected ExtendableBuilder() {} + + // This is implemented here only to work around an apparent bug in the + // Java compiler and/or build system. See bug #1898463. The mere presence + // of this dummy clone() implementation makes it go away. + @Override + public BuilderType clone() { + throw new UnsupportedOperationException( + "This is supposed to be overridden by subclasses."); + } + + @Override protected abstract ExtendableMessage internalGetResult(); /** Check if a singular extension is present. */ public final boolean hasExtension( - GeneratedExtension extension) { + final GeneratedExtension extension) { return internalGetResult().hasExtension(extension); } /** Get the number of elements in a repeated extension. */ public final int getExtensionCount( - GeneratedExtension> extension) { + final GeneratedExtension> extension) { return internalGetResult().getExtensionCount(extension); } /** Get the value of an extension. */ public final Type getExtension( - GeneratedExtension extension) { + final GeneratedExtension extension) { return internalGetResult().getExtension(extension); } /** Get one element of a repeated extension. */ public final Type getExtension( - GeneratedExtension> extension, int index) { + final GeneratedExtension> extension, + final int index) { return internalGetResult().getExtension(extension, index); } /** Set the value of an extension. */ public final BuilderType setExtension( - GeneratedExtension extension, Type value) { - ExtendableMessage message = internalGetResult(); + final GeneratedExtension extension, + final Type value) { + final ExtendableMessage message = internalGetResult(); message.verifyExtensionContainingType(extension); - message.extensions.setField(extension.getDescriptor(), + final FieldDescriptor descriptor = extension.getDescriptor(); + message.extensions.setField(descriptor, extension.toReflectionType(value)); return (BuilderType) this; } /** Set the value of one element of a repeated extension. */ public final BuilderType setExtension( - GeneratedExtension> extension, - int index, Type value) { - ExtendableMessage message = internalGetResult(); + final GeneratedExtension> extension, + final int index, final Type value) { + final ExtendableMessage message = internalGetResult(); message.verifyExtensionContainingType(extension); + final FieldDescriptor descriptor = extension.getDescriptor(); message.extensions.setRepeatedField( - extension.getDescriptor(), index, + descriptor, index, extension.singularToReflectionType(value)); return (BuilderType) this; } /** Append a value to a repeated extension. */ public final BuilderType addExtension( - GeneratedExtension> extension, Type value) { - ExtendableMessage message = internalGetResult(); + final GeneratedExtension> extension, + final Type value) { + final ExtendableMessage message = internalGetResult(); message.verifyExtensionContainingType(extension); + final FieldDescriptor descriptor = extension.getDescriptor(); message.extensions.addRepeatedField( - extension.getDescriptor(), extension.singularToReflectionType(value)); + descriptor, extension.singularToReflectionType(value)); return (BuilderType) this; } /** Clear an extension. */ public final BuilderType clearExtension( - GeneratedExtension extension) { - ExtendableMessage message = internalGetResult(); + final GeneratedExtension extension) { + final ExtendableMessage message = internalGetResult(); message.verifyExtensionContainingType(extension); message.extensions.clearField(extension.getDescriptor()); return (BuilderType) this; @@ -631,13 +643,14 @@ public abstract class GeneratedMessage extends AbstractMessage { * Called by subclasses to parse an unknown field or an extension. * @return {@code true} unless the tag is an end-group tag. */ - protected boolean parseUnknownField(CodedInputStream input, - UnknownFieldSet.Builder unknownFields, - ExtensionRegistry extensionRegistry, - int tag) - throws IOException { - ExtendableMessage message = internalGetResult(); - return message.extensions.mergeFieldFrom( + @Override + protected boolean parseUnknownField( + final CodedInputStream input, + final UnknownFieldSet.Builder unknownFields, + final ExtensionRegistryLite extensionRegistry, + final int tag) throws IOException { + final ExtendableMessage message = internalGetResult(); + return AbstractMessage.Builder.mergeFieldFrom( input, unknownFields, extensionRegistry, this, tag); } @@ -647,9 +660,11 @@ public abstract class GeneratedMessage extends AbstractMessage { // We don't have to override the get*() methods here because they already // just forward to the underlying message. - public BuilderType setField(FieldDescriptor field, Object value) { + @Override + public BuilderType setField(final FieldDescriptor field, + final Object value) { if (field.isExtension()) { - ExtendableMessage message = internalGetResult(); + final ExtendableMessage message = internalGetResult(); message.verifyContainingType(field); message.extensions.setField(field, value); return (BuilderType) this; @@ -658,9 +673,10 @@ public abstract class GeneratedMessage extends AbstractMessage { } } - public BuilderType clearField(Descriptors.FieldDescriptor field) { + @Override + public BuilderType clearField(final FieldDescriptor field) { if (field.isExtension()) { - ExtendableMessage message = internalGetResult(); + final ExtendableMessage message = internalGetResult(); message.verifyContainingType(field); message.extensions.clearField(field); return (BuilderType) this; @@ -669,10 +685,11 @@ public abstract class GeneratedMessage extends AbstractMessage { } } - public BuilderType setRepeatedField(Descriptors.FieldDescriptor field, - int index, Object value) { + @Override + public BuilderType setRepeatedField(final FieldDescriptor field, + final int index, final Object value) { if (field.isExtension()) { - ExtendableMessage message = internalGetResult(); + final ExtendableMessage message = internalGetResult(); message.verifyContainingType(field); message.extensions.setRepeatedField(field, index, value); return (BuilderType) this; @@ -681,10 +698,11 @@ public abstract class GeneratedMessage extends AbstractMessage { } } - public BuilderType addRepeatedField(Descriptors.FieldDescriptor field, - Object value) { + @Override + public BuilderType addRepeatedField(final FieldDescriptor field, + final Object value) { if (field.isExtension()) { - ExtendableMessage message = internalGetResult(); + final ExtendableMessage message = internalGetResult(); message.verifyContainingType(field); message.extensions.addRepeatedField(field, value); return (BuilderType) this; @@ -693,7 +711,7 @@ public abstract class GeneratedMessage extends AbstractMessage { } } - protected final void mergeExtensionFields(ExtendableMessage other) { + protected final void mergeExtensionFields(final ExtendableMessage other) { internalGetResult().extensions.mergeFrom(other.extensions); } } @@ -703,7 +721,8 @@ public abstract class GeneratedMessage extends AbstractMessage { /** For use by generated code only. */ public static GeneratedExtension - newGeneratedExtension(FieldDescriptor descriptor, Class type) { + newGeneratedExtension(final FieldDescriptor descriptor, + final Class type) { if (descriptor.isRepeated()) { throw new IllegalArgumentException( "Must call newRepeatedGeneratedExtension() for repeated types."); @@ -715,7 +734,7 @@ public abstract class GeneratedMessage extends AbstractMessage { public static GeneratedExtension> newRepeatedGeneratedExtension( - FieldDescriptor descriptor, Class type) { + final FieldDescriptor descriptor, final Class type) { if (!descriptor.isRepeated()) { throw new IllegalArgumentException( "Must call newGeneratedExtension() for non-repeated types."); @@ -753,7 +772,8 @@ public abstract class GeneratedMessage extends AbstractMessage { // TODO(kenton): Find ways to avoid using Java reflection within this // class. Also try to avoid suppressing unchecked warnings. - private GeneratedExtension(FieldDescriptor descriptor, Class type) { + private GeneratedExtension(final FieldDescriptor descriptor, + final Class type) { if (!descriptor.isExtension()) { throw new IllegalArgumentException( "GeneratedExtension given a regular (non-extension) field."); @@ -808,13 +828,13 @@ public abstract class GeneratedMessage extends AbstractMessage { * type. */ @SuppressWarnings("unchecked") - private Object fromReflectionType(Object value) { + private Object fromReflectionType(final Object value) { if (descriptor.isRepeated()) { if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE || descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { // Must convert the whole list. - List result = new ArrayList(); - for (Object element : (List) value) { + final List result = new ArrayList(); + for (final Object element : (List) value) { result.add(singularFromReflectionType(element)); } return result; @@ -830,7 +850,7 @@ public abstract class GeneratedMessage extends AbstractMessage { * Like {@link #fromReflectionType(Object)}, but if the type is a repeated * type, this converts a single element. */ - private Object singularFromReflectionType(Object value) { + private Object singularFromReflectionType(final Object value) { switch (descriptor.getJavaType()) { case MESSAGE: if (type.isInstance(value)) { @@ -859,12 +879,12 @@ public abstract class GeneratedMessage extends AbstractMessage { * type. */ @SuppressWarnings("unchecked") - private Object toReflectionType(Object value) { + private Object toReflectionType(final Object value) { if (descriptor.isRepeated()) { if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { // Must convert the whole list. - List result = new ArrayList(); - for (Object element : (List) value) { + final List result = new ArrayList(); + for (final Object element : (List) value) { result.add(singularToReflectionType(element)); } return result; @@ -880,7 +900,7 @@ public abstract class GeneratedMessage extends AbstractMessage { * Like {@link #toReflectionType(Object)}, but if the type is a repeated * type, this converts a single element. */ - private Object singularToReflectionType(Object value) { + private Object singularToReflectionType(final Object value) { switch (descriptor.getJavaType()) { case ENUM: return invokeOrDie(enumGetValueDescriptor, value); @@ -895,7 +915,7 @@ public abstract class GeneratedMessage extends AbstractMessage { /** Calls Class.getMethod and throws a RuntimeException if it fails. */ @SuppressWarnings("unchecked") private static Method getMethodOrDie( - Class clazz, String name, Class... params) { + final Class clazz, final String name, final Class... params) { try { return clazz.getMethod(name, params); } catch (NoSuchMethodException e) { @@ -907,15 +927,15 @@ public abstract class GeneratedMessage extends AbstractMessage { /** Calls invoke and throws a RuntimeException if it fails. */ private static Object invokeOrDie( - Method method, Object object, Object... params) { + final Method method, final Object object, final Object... params) { try { return method.invoke(object, params); } catch (IllegalAccessException e) { throw new RuntimeException( "Couldn't use Java reflection to implement protocol message " + "reflection.", e); - } catch (java.lang.reflect.InvocationTargetException e) { - Throwable cause = e.getCause(); + } catch (InvocationTargetException e) { + final Throwable cause = e.getCause(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { @@ -944,15 +964,15 @@ public abstract class GeneratedMessage extends AbstractMessage { * @param builderClass The builder type. */ public FieldAccessorTable( - Descriptor descriptor, - String[] camelCaseNames, - Class messageClass, - Class builderClass) { + final Descriptor descriptor, + final String[] camelCaseNames, + final Class messageClass, + final Class builderClass) { this.descriptor = descriptor; fields = new FieldAccessor[descriptor.getFields().size()]; for (int i = 0; i < fields.length; i++) { - FieldDescriptor field = descriptor.getFields().get(i); + final FieldDescriptor field = descriptor.getFields().get(i); if (field.isRepeated()) { if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { fields[i] = new RepeatedMessageFieldAccessor( @@ -983,7 +1003,7 @@ public abstract class GeneratedMessage extends AbstractMessage { private final FieldAccessor[] fields; /** Get the FieldAccessor for a particular field. */ - private FieldAccessor getField(FieldDescriptor field) { + private FieldAccessor getField(final FieldDescriptor field) { if (field.getContainingType() != descriptor) { throw new IllegalArgumentException( "FieldDescriptor does not match message type."); @@ -1000,16 +1020,16 @@ public abstract class GeneratedMessage extends AbstractMessage { * Abstract interface that provides access to a single field. This is * implemented differently depending on the field type and cardinality. */ - private static interface FieldAccessor { + private interface FieldAccessor { Object get(GeneratedMessage message); - void set(GeneratedMessage.Builder builder, Object value); + void set(Builder builder, Object value); Object getRepeated(GeneratedMessage message, int index); - void setRepeated(GeneratedMessage.Builder builder, + void setRepeated(Builder builder, int index, Object value); - void addRepeated(GeneratedMessage.Builder builder, Object value); + void addRepeated(Builder builder, Object value); boolean has(GeneratedMessage message); int getRepeatedCount(GeneratedMessage message); - void clear(GeneratedMessage.Builder builder); + void clear(Builder builder); Message.Builder newBuilder(); } @@ -1017,9 +1037,9 @@ public abstract class GeneratedMessage extends AbstractMessage { private static class SingularFieldAccessor implements FieldAccessor { SingularFieldAccessor( - FieldDescriptor descriptor, String camelCaseName, - Class messageClass, - Class builderClass) { + final FieldDescriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass) { getMethod = getMethodOrDie(messageClass, "get" + camelCaseName); type = getMethod.getReturnType(); setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type); @@ -1031,39 +1051,40 @@ public abstract class GeneratedMessage extends AbstractMessage { // Note: We use Java reflection to call public methods rather than // access private fields directly as this avoids runtime security // checks. - Class type; - Method getMethod; - Method setMethod; - Method hasMethod; - Method clearMethod; + protected final Class type; + protected final Method getMethod; + protected final Method setMethod; + protected final Method hasMethod; + protected final Method clearMethod; - public Object get(GeneratedMessage message) { + public Object get(final GeneratedMessage message) { return invokeOrDie(getMethod, message); } - public void set(GeneratedMessage.Builder builder, Object value) { + public void set(final Builder builder, final Object value) { invokeOrDie(setMethod, builder, value); } - public Object getRepeated(GeneratedMessage message, int index) { + public Object getRepeated(final GeneratedMessage message, + final int index) { throw new UnsupportedOperationException( "getRepeatedField() called on a singular field."); } - public void setRepeated(GeneratedMessage.Builder builder, - int index, Object value) { + public void setRepeated(final Builder builder, + final int index, final Object value) { throw new UnsupportedOperationException( "setRepeatedField() called on a singular field."); } - public void addRepeated(GeneratedMessage.Builder builder, Object value) { + public void addRepeated(final Builder builder, final Object value) { throw new UnsupportedOperationException( "addRepeatedField() called on a singular field."); } - public boolean has(GeneratedMessage message) { + public boolean has(final GeneratedMessage message) { return (Boolean) invokeOrDie(hasMethod, message); } - public int getRepeatedCount(GeneratedMessage message) { + public int getRepeatedCount(final GeneratedMessage message) { throw new UnsupportedOperationException( "getRepeatedFieldSize() called on a singular field."); } - public void clear(GeneratedMessage.Builder builder) { + public void clear(final Builder builder) { invokeOrDie(clearMethod, builder); } public Message.Builder newBuilder() { @@ -1074,10 +1095,11 @@ public abstract class GeneratedMessage extends AbstractMessage { private static class RepeatedFieldAccessor implements FieldAccessor { RepeatedFieldAccessor( - FieldDescriptor descriptor, String camelCaseName, - Class messageClass, - Class builderClass) { - getMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "List"); + final FieldDescriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass) { + getMethod = getMethodOrDie(messageClass, + "get" + camelCaseName + "List"); getRepeatedMethod = getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE); @@ -1093,45 +1115,46 @@ public abstract class GeneratedMessage extends AbstractMessage { clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); } - Class type; - Method getMethod; - Method getRepeatedMethod; - Method setRepeatedMethod; - Method addRepeatedMethod; - Method getCountMethod; - Method clearMethod; + protected final Class type; + protected final Method getMethod; + protected final Method getRepeatedMethod; + protected final Method setRepeatedMethod; + protected final Method addRepeatedMethod; + protected final Method getCountMethod; + protected final Method clearMethod; - public Object get(GeneratedMessage message) { + public Object get(final GeneratedMessage message) { return invokeOrDie(getMethod, message); } - public void set(GeneratedMessage.Builder builder, Object value) { + public void set(final Builder builder, final Object value) { // Add all the elements individually. This serves two purposes: // 1) Verifies that each element has the correct type. // 2) Insures that the caller cannot modify the list later on and // have the modifications be reflected in the message. clear(builder); - for (Object element : (List) value) { + for (final Object element : (List) value) { addRepeated(builder, element); } } - public Object getRepeated(GeneratedMessage message, int index) { + public Object getRepeated(final GeneratedMessage message, + final int index) { return invokeOrDie(getRepeatedMethod, message, index); } - public void setRepeated(GeneratedMessage.Builder builder, - int index, Object value) { + public void setRepeated(final Builder builder, + final int index, final Object value) { invokeOrDie(setRepeatedMethod, builder, index, value); } - public void addRepeated(GeneratedMessage.Builder builder, Object value) { + public void addRepeated(final Builder builder, final Object value) { invokeOrDie(addRepeatedMethod, builder, value); } - public boolean has(GeneratedMessage message) { + public boolean has(final GeneratedMessage message) { throw new UnsupportedOperationException( "hasField() called on a singular field."); } - public int getRepeatedCount(GeneratedMessage message) { + public int getRepeatedCount(final GeneratedMessage message) { return (Integer) invokeOrDie(getCountMethod, message); } - public void clear(GeneratedMessage.Builder builder) { + public void clear(final Builder builder) { invokeOrDie(clearMethod, builder); } public Message.Builder newBuilder() { @@ -1145,9 +1168,9 @@ public abstract class GeneratedMessage extends AbstractMessage { private static final class SingularEnumFieldAccessor extends SingularFieldAccessor { SingularEnumFieldAccessor( - FieldDescriptor descriptor, String camelCaseName, - Class messageClass, - Class builderClass) { + final FieldDescriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass) { super(descriptor, camelCaseName, messageClass, builderClass); valueOfMethod = getMethodOrDie(type, "valueOf", @@ -1159,10 +1182,12 @@ public abstract class GeneratedMessage extends AbstractMessage { private Method valueOfMethod; private Method getValueDescriptorMethod; - public Object get(GeneratedMessage message) { + @Override + public Object get(final GeneratedMessage message) { return invokeOrDie(getValueDescriptorMethod, super.get(message)); } - public void set(GeneratedMessage.Builder builder, Object value) { + @Override + public void set(final Builder builder, final Object value) { super.set(builder, invokeOrDie(valueOfMethod, null, value)); } } @@ -1170,9 +1195,9 @@ public abstract class GeneratedMessage extends AbstractMessage { private static final class RepeatedEnumFieldAccessor extends RepeatedFieldAccessor { RepeatedEnumFieldAccessor( - FieldDescriptor descriptor, String camelCaseName, - Class messageClass, - Class builderClass) { + final FieldDescriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass) { super(descriptor, camelCaseName, messageClass, builderClass); valueOfMethod = getMethodOrDie(type, "valueOf", @@ -1181,26 +1206,32 @@ public abstract class GeneratedMessage extends AbstractMessage { getMethodOrDie(type, "getValueDescriptor"); } - private Method valueOfMethod; - private Method getValueDescriptorMethod; + private final Method valueOfMethod; + private final Method getValueDescriptorMethod; + @Override @SuppressWarnings("unchecked") - public Object get(GeneratedMessage message) { - List newList = new ArrayList(); - for (Object element : (List) super.get(message)) { + public Object get(final GeneratedMessage message) { + final List newList = new ArrayList(); + for (final Object element : (List) super.get(message)) { newList.add(invokeOrDie(getValueDescriptorMethod, element)); } return Collections.unmodifiableList(newList); } - public Object getRepeated(GeneratedMessage message, int index) { + @Override + public Object getRepeated(final GeneratedMessage message, + final int index) { return invokeOrDie(getValueDescriptorMethod, super.getRepeated(message, index)); } - public void setRepeated(GeneratedMessage.Builder builder, - int index, Object value) { - super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, value)); + @Override + public void setRepeated(final Builder builder, + final int index, final Object value) { + super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, + value)); } - public void addRepeated(GeneratedMessage.Builder builder, Object value) { + @Override + public void addRepeated(final Builder builder, final Object value) { super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value)); } } @@ -1210,17 +1241,17 @@ public abstract class GeneratedMessage extends AbstractMessage { private static final class SingularMessageFieldAccessor extends SingularFieldAccessor { SingularMessageFieldAccessor( - FieldDescriptor descriptor, String camelCaseName, - Class messageClass, - Class builderClass) { + final FieldDescriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass) { super(descriptor, camelCaseName, messageClass, builderClass); newBuilderMethod = getMethodOrDie(type, "newBuilder"); } - private Method newBuilderMethod; + private final Method newBuilderMethod; - private Object coerceType(Object value) { + private Object coerceType(final Object value) { if (type.isInstance(value)) { return value; } else { @@ -1233,9 +1264,11 @@ public abstract class GeneratedMessage extends AbstractMessage { } } - public void set(GeneratedMessage.Builder builder, Object value) { + @Override + public void set(final Builder builder, final Object value) { super.set(builder, coerceType(value)); } + @Override public Message.Builder newBuilder() { return (Message.Builder) invokeOrDie(newBuilderMethod, null); } @@ -1244,17 +1277,17 @@ public abstract class GeneratedMessage extends AbstractMessage { private static final class RepeatedMessageFieldAccessor extends RepeatedFieldAccessor { RepeatedMessageFieldAccessor( - FieldDescriptor descriptor, String camelCaseName, - Class messageClass, - Class builderClass) { + final FieldDescriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass) { super(descriptor, camelCaseName, messageClass, builderClass); newBuilderMethod = getMethodOrDie(type, "newBuilder"); } - private Method newBuilderMethod; + private final Method newBuilderMethod; - private Object coerceType(Object value) { + private Object coerceType(final Object value) { if (type.isInstance(value)) { return value; } else { @@ -1267,13 +1300,16 @@ public abstract class GeneratedMessage extends AbstractMessage { } } - public void setRepeated(GeneratedMessage.Builder builder, - int index, Object value) { + @Override + public void setRepeated(final Builder builder, + final int index, final Object value) { super.setRepeated(builder, index, coerceType(value)); } - public void addRepeated(GeneratedMessage.Builder builder, Object value) { + @Override + public void addRepeated(final Builder builder, final Object value) { super.addRepeated(builder, coerceType(value)); } + @Override public Message.Builder newBuilder() { return (Message.Builder) invokeOrDie(newBuilderMethod, null); } diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java new file mode 100644 index 00000000..c68414bd --- /dev/null +++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java @@ -0,0 +1,539 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.io.IOException; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Lite version of {@link GeneratedMessage}. + * + * @author kenton@google.com Kenton Varda + */ +public abstract class GeneratedMessageLite extends AbstractMessageLite { + protected GeneratedMessageLite() {} + + @SuppressWarnings("unchecked") + public abstract static class Builder + extends AbstractMessageLite.Builder { + protected Builder() {} + + // This is implemented here only to work around an apparent bug in the + // Java compiler and/or build system. See bug #1898463. The mere presence + // of this dummy clone() implementation makes it go away. + @Override + public BuilderType clone() { + throw new UnsupportedOperationException( + "This is supposed to be overridden by subclasses."); + } + + /** All subclasses implement this. */ + public abstract BuilderType mergeFrom(MessageType message); + + // Defined here for return type covariance. + public abstract MessageType getDefaultInstanceForType(); + + /** + * Get the message being built. We don't just pass this to the + * constructor because it becomes null when build() is called. + */ + protected abstract MessageType internalGetResult(); + + /** + * Called by subclasses to parse an unknown field. + * @return {@code true} unless the tag is an end-group tag. + */ + protected boolean parseUnknownField( + final CodedInputStream input, + final ExtensionRegistryLite extensionRegistry, + final int tag) throws IOException { + return input.skipField(tag); + } + } + + // ================================================================= + // Extensions-related stuff + + /** + * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}. + */ + public abstract static class ExtendableMessage< + MessageType extends ExtendableMessage> + extends GeneratedMessageLite { + protected ExtendableMessage() {} + private final FieldSet extensions = + FieldSet.newFieldSet(); + + private void verifyExtensionContainingType( + final GeneratedExtension extension) { + if (extension.getContainingTypeDefaultInstance() != + getDefaultInstanceForType()) { + // This can only happen if someone uses unchecked operations. + throw new IllegalArgumentException( + "This extension is for a different message type. Please make " + + "sure that you are not suppressing any generics type warnings."); + } + } + + /** Check if a singular extension is present. */ + public final boolean hasExtension( + final GeneratedExtension extension) { + verifyExtensionContainingType(extension); + return extensions.hasField(extension.descriptor); + } + + /** Get the number of elements in a repeated extension. */ + public final int getExtensionCount( + final GeneratedExtension> extension) { + verifyExtensionContainingType(extension); + return extensions.getRepeatedFieldCount(extension.descriptor); + } + + /** Get the value of an extension. */ + @SuppressWarnings("unchecked") + public final Type getExtension( + final GeneratedExtension extension) { + verifyExtensionContainingType(extension); + final Object value = extensions.getField(extension.descriptor); + if (value == null) { + return extension.defaultValue; + } else { + return (Type) value; + } + } + + /** Get one element of a repeated extension. */ + @SuppressWarnings("unchecked") + public final Type getExtension( + final GeneratedExtension> extension, + final int index) { + verifyExtensionContainingType(extension); + return (Type) extensions.getRepeatedField(extension.descriptor, index); + } + + /** Called by subclasses to check if all extensions are initialized. */ + protected boolean extensionsAreInitialized() { + return extensions.isInitialized(); + } + + /** + * Used by subclasses to serialize extensions. Extension ranges may be + * interleaved with field numbers, but we must write them in canonical + * (sorted by field number) order. ExtensionWriter helps us write + * individual ranges of extensions at once. + */ + protected class ExtensionWriter { + // Imagine how much simpler this code would be if Java iterators had + // a way to get the next element without advancing the iterator. + + private final Iterator> iter = + extensions.iterator(); + private Map.Entry next; + private final boolean messageSetWireFormat; + + private ExtensionWriter(boolean messageSetWireFormat) { + if (iter.hasNext()) { + next = iter.next(); + } + this.messageSetWireFormat = messageSetWireFormat; + } + + public void writeUntil(final int end, final CodedOutputStream output) + throws IOException { + while (next != null && next.getKey().getNumber() < end) { + ExtensionDescriptor extension = next.getKey(); + if (messageSetWireFormat && extension.getLiteJavaType() == + WireFormat.JavaType.MESSAGE && + !extension.isRepeated()) { + output.writeMessageSetExtension(extension.getNumber(), + (MessageLite) next.getValue()); + } else { + FieldSet.writeField(extension, next.getValue(), output); + } + if (iter.hasNext()) { + next = iter.next(); + } else { + next = null; + } + } + } + } + + protected ExtensionWriter newExtensionWriter() { + return new ExtensionWriter(false); + } + protected ExtensionWriter newMessageSetExtensionWriter() { + return new ExtensionWriter(true); + } + + /** Called by subclasses to compute the size of extensions. */ + protected int extensionsSerializedSize() { + return extensions.getSerializedSize(); + } + protected int extensionsSerializedSizeAsMessageSet() { + return extensions.getMessageSetSerializedSize(); + } + } + + /** + * Lite equivalent of {@link GeneratedMessage.ExtendableBuilder}. + */ + @SuppressWarnings("unchecked") + public abstract static class ExtendableBuilder< + MessageType extends ExtendableMessage, + BuilderType extends ExtendableBuilder> + extends Builder { + protected ExtendableBuilder() {} + + // This is implemented here only to work around an apparent bug in the + // Java compiler and/or build system. See bug #1898463. The mere presence + // of this dummy clone() implementation makes it go away. + @Override + public BuilderType clone() { + throw new UnsupportedOperationException( + "This is supposed to be overridden by subclasses."); + } + + @Override + protected abstract MessageType internalGetResult(); + + /** Check if a singular extension is present. */ + public final boolean hasExtension( + final GeneratedExtension extension) { + return internalGetResult().hasExtension(extension); + } + + /** Get the number of elements in a repeated extension. */ + public final int getExtensionCount( + final GeneratedExtension> extension) { + return internalGetResult().getExtensionCount(extension); + } + + /** Get the value of an extension. */ + public final Type getExtension( + final GeneratedExtension extension) { + return internalGetResult().getExtension(extension); + } + + /** Get one element of a repeated extension. */ + public final Type getExtension( + final GeneratedExtension> extension, + final int index) { + return internalGetResult().getExtension(extension, index); + } + + /** Set the value of an extension. */ + public final BuilderType setExtension( + final GeneratedExtension extension, + final Type value) { + final ExtendableMessage message = internalGetResult(); + message.verifyExtensionContainingType(extension); + message.extensions.setField(extension.descriptor, value); + return (BuilderType) this; + } + + /** Set the value of one element of a repeated extension. */ + public final BuilderType setExtension( + final GeneratedExtension> extension, + final int index, final Type value) { + final ExtendableMessage message = internalGetResult(); + message.verifyExtensionContainingType(extension); + message.extensions.setRepeatedField(extension.descriptor, index, value); + return (BuilderType) this; + } + + /** Append a value to a repeated extension. */ + public final BuilderType addExtension( + final GeneratedExtension> extension, + final Type value) { + final ExtendableMessage message = internalGetResult(); + message.verifyExtensionContainingType(extension); + message.extensions.addRepeatedField(extension.descriptor, value); + return (BuilderType) this; + } + + /** Clear an extension. */ + public final BuilderType clearExtension( + final GeneratedExtension extension) { + final ExtendableMessage message = internalGetResult(); + message.verifyExtensionContainingType(extension); + message.extensions.clearField(extension.descriptor); + return (BuilderType) this; + } + + /** + * Called by subclasses to parse an unknown field or an extension. + * @return {@code true} unless the tag is an end-group tag. + */ + @Override + protected boolean parseUnknownField( + final CodedInputStream input, + final ExtensionRegistryLite extensionRegistry, + final int tag) throws IOException { + final FieldSet extensions = + internalGetResult().extensions; + + final int wireType = WireFormat.getTagWireType(tag); + final int fieldNumber = WireFormat.getTagFieldNumber(tag); + + final GeneratedExtension extension = + extensionRegistry.findLiteExtensionByNumber( + getDefaultInstanceForType(), fieldNumber); + + if (extension == null || wireType != + FieldSet.getWireFormatForFieldType( + extension.descriptor.getLiteType(), + extension.descriptor.isPacked())) { + // Unknown field or wrong wire type. Skip. + return input.skipField(tag); + } + + if (extension.descriptor.isPacked()) { + final int length = input.readRawVarint32(); + final int limit = input.pushLimit(length); + if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) { + while (input.getBytesUntilLimit() > 0) { + final int rawValue = input.readEnum(); + final Object value = + extension.descriptor.getEnumType().findValueByNumber(rawValue); + if (value == null) { + // If the number isn't recognized as a valid value for this + // enum, drop it (don't even add it to unknownFields). + return true; + } + extensions.addRepeatedField(extension.descriptor, value); + } + } else { + while (input.getBytesUntilLimit() > 0) { + final Object value = + FieldSet.readPrimitiveField(input, + extension.descriptor.getLiteType()); + extensions.addRepeatedField(extension.descriptor, value); + } + } + input.popLimit(limit); + } else { + final Object value; + switch (extension.descriptor.getLiteJavaType()) { + case MESSAGE: { + MessageLite.Builder subBuilder = null; + if (!extension.descriptor.isRepeated()) { + MessageLite existingValue = + (MessageLite) extensions.getField(extension.descriptor); + if (existingValue != null) { + subBuilder = existingValue.toBuilder(); + } + } + if (subBuilder == null) { + subBuilder = extension.messageDefaultInstance.newBuilderForType(); + } + if (extension.descriptor.getLiteType() == + WireFormat.FieldType.GROUP) { + input.readGroup(extension.getNumber(), + subBuilder, extensionRegistry); + } else { + input.readMessage(subBuilder, extensionRegistry); + } + value = subBuilder.build(); + break; + } + case ENUM: + final int rawValue = input.readEnum(); + value = extension.descriptor.getEnumType() + .findValueByNumber(rawValue); + // If the number isn't recognized as a valid value for this enum, + // drop it. + if (value == null) { + return true; + } + break; + default: + value = FieldSet.readPrimitiveField(input, + extension.descriptor.getLiteType()); + break; + } + + if (extension.descriptor.isRepeated()) { + extensions.addRepeatedField(extension.descriptor, value); + } else { + extensions.setField(extension.descriptor, value); + } + } + + return true; + } + + protected final void mergeExtensionFields(final MessageType other) { + internalGetResult().extensions.mergeFrom(other.extensions); + } + } + + // ----------------------------------------------------------------- + + /** For use by generated code only. */ + public static + GeneratedExtension + newGeneratedExtension( + final ContainingType containingTypeDefaultInstance, + final Type defaultValue, + final MessageLite messageDefaultInstance, + final Internal.EnumLiteMap enumTypeMap, + final int number, + final WireFormat.FieldType type) { + return new GeneratedExtension( + containingTypeDefaultInstance, defaultValue, messageDefaultInstance, + new ExtensionDescriptor(enumTypeMap, number, type, + false /* isRepeated */, false /* isPacked */)); + } + + /** For use by generated code only. */ + public static + GeneratedExtension> + newRepeatedGeneratedExtension( + final ContainingType containingTypeDefaultInstance, + final MessageLite messageDefaultInstance, + final Internal.EnumLiteMap enumTypeMap, + final int number, + final WireFormat.FieldType type, + final boolean isPacked) { + return new GeneratedExtension>( + containingTypeDefaultInstance, Collections.emptyList(), + messageDefaultInstance, + new ExtensionDescriptor( + enumTypeMap, number, type, true /* isRepeated */, isPacked)); + } + + private static final class ExtensionDescriptor + implements FieldSet.FieldDescriptorLite< + ExtensionDescriptor> { + private ExtensionDescriptor( + final Internal.EnumLiteMap enumTypeMap, + final int number, + final WireFormat.FieldType type, + final boolean isRepeated, + final boolean isPacked) { + this.enumTypeMap = enumTypeMap; + this.number = number; + this.type = type; + this.isRepeated = isRepeated; + this.isPacked = isPacked; + } + + private final Internal.EnumLiteMap enumTypeMap; + private final int number; + private final WireFormat.FieldType type; + private final boolean isRepeated; + private final boolean isPacked; + + public int getNumber() { + return number; + } + + public WireFormat.FieldType getLiteType() { + return type; + } + + public WireFormat.JavaType getLiteJavaType() { + return type.getJavaType(); + } + + public boolean isRepeated() { + return isRepeated; + } + + public boolean isPacked() { + return isPacked; + } + + public Internal.EnumLiteMap getEnumType() { + return enumTypeMap; + } + + @SuppressWarnings("unchecked") + public MessageLite.Builder internalMergeFrom( + MessageLite.Builder to, MessageLite from) { + return ((Builder) to).mergeFrom((GeneratedMessageLite) from); + } + + public int compareTo(ExtensionDescriptor other) { + return number - other.number; + } + } + + /** + * Lite equivalent to {@link GeneratedMessage.GeneratedExtension}. + * + * Users should ignore the contents of this class and only use objects of + * this type as parameters to extension accessors and ExtensionRegistry.add(). + */ + public static final class GeneratedExtension< + ContainingType extends MessageLite, Type> { + private GeneratedExtension( + final ContainingType containingTypeDefaultInstance, + final Type defaultValue, + final MessageLite messageDefaultInstance, + final ExtensionDescriptor descriptor) { + this.containingTypeDefaultInstance = containingTypeDefaultInstance; + this.defaultValue = defaultValue; + this.messageDefaultInstance = messageDefaultInstance; + this.descriptor = descriptor; + } + + private final ContainingType containingTypeDefaultInstance; + private final Type defaultValue; + private final MessageLite messageDefaultInstance; + private final ExtensionDescriptor descriptor; + + /** + * Default instance of the type being extended, used to identify that type. + */ + public ContainingType getContainingTypeDefaultInstance() { + return containingTypeDefaultInstance; + } + + /** Get the field number. */ + public int getNumber() { + return descriptor.getNumber(); + } + + /** + * If the extension is an embedded message, this is the default instance of + * that type. + */ + public MessageLite getMessageDefaultInstance() { + return messageDefaultInstance; + } + } +} diff --git a/java/src/main/java/com/google/protobuf/Internal.java b/java/src/main/java/com/google/protobuf/Internal.java new file mode 100644 index 00000000..ba8e6aee --- /dev/null +++ b/java/src/main/java/com/google/protobuf/Internal.java @@ -0,0 +1,194 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import java.io.UnsupportedEncodingException; + +/** + * The classes contained within are used internally by the Protocol Buffer + * library and generated message implementations. They are public only because + * those generated messages do not reside in the {@code protobuf} package. + * Others should not use this class directly. + * + * @author cyrusn@google.com (Cyrus Najmabadi) + */ +public class Internal { + /** + * Implementation of a Queue designed to have as little overhead as possible. + * No guarantees are made as to the order you will get values back from the + * queue. Currently it is a Last-In-First-Out implementation, but that may + * change in the future. + * + * Duplicate values are allowed, as are null values. + * + * Not threadsafe. + * + * @author cyrusn@google.com (Cyrus Najmabadi) + */ + public static final class QuickQueue { + @SuppressWarnings("unchecked") + private T[] array = (T[]) new Object[16]; + private int size; + + /** + * Adds a value to the queue. + * + * @param value The value to add to the queue. + */ + public void offer(final T value) { + if (size == array.length) { + // I'd like to use Arrays.copy here. However, it is currently + // unavailable + // on android. So, for now, we just use the tried and true arraycopy + // technique. + @SuppressWarnings("unchecked") + final T[] copy = (T[]) new Object[size * 2]; + System.arraycopy(array, 0, copy, 0, array.length); + array = copy; + } + + array[size++] = value; + } + + /** + * Removes some previously added value to the queue, or {@code null} if the + * queue is empty. + * + * @return An existing value in the queue, or {@code null} if the queue is + * empty. + */ + public T poll() { + if (size == 0) { + return null; + } + + final T result = array[--size]; + // make sure we null out the entry so that we're not keeping anything + // alive unnecessarily. + array[size] = null; + + return result; + } + } + + /** + * Instances of this class will provide a unique {@code QuickQueue} to each + * thread that accesses it. Very useful for providing free lists without + * needing to take any locks. + * + * @author cyrusn@google.com (Cyrus Najmabadi) + */ + public static final class ThreadLocalQuickQueue + extends ThreadLocal> { + @Override + protected QuickQueue initialValue() { + return new QuickQueue(); + } + } + + /** + * Helper called by generated code to construct default values for string + * fields. + *

+ * The protocol compiler does not actually contain a UTF-8 decoder -- it + * just pushes UTF-8-encoded text around without touching it. The one place + * where this presents a problem is when generating Java string literals. + * Unicode characters in the string literal would normally need to be encoded + * using a Unicode escape sequence, which would require decoding them. + * To get around this, protoc instead embeds the UTF-8 bytes into the + * generated code and leaves it to the runtime library to decode them. + *

+ * It gets worse, though. If protoc just generated a byte array, like: + * new byte[] {0x12, 0x34, 0x56, 0x78} + * Java actually generates *code* which allocates an array and then fills + * in each value. This is much less efficient than just embedding the bytes + * directly into the bytecode. To get around this, we need another + * work-around. String literals are embedded directly, so protoc actually + * generates a string literal corresponding to the bytes. The easiest way + * to do this is to use the ISO-8859-1 character set, which corresponds to + * the first 256 characters of the Unicode range. Protoc can then use + * good old CEscape to generate the string. + *

+ * So we have a string literal which represents a set of bytes which + * represents another string. This function -- stringDefaultValue -- + * converts from the generated string to the string we actually want. The + * generated code calls this automatically. + */ + public static String stringDefaultValue(String bytes) { + try { + return new String(bytes.getBytes("ISO-8859-1"), "UTF-8"); + } catch (UnsupportedEncodingException e) { + // This should never happen since all JVMs are required to implement + // both of the above character sets. + throw new IllegalStateException( + "Java VM does not support a standard character set.", e); + } + } + + /** + * Helper called by generated code to construct default values for bytes + * fields. + *

+ * This is a lot like {@link #stringDefaultValue}, but for bytes fields. + * In this case we only need the second of the two hacks -- allowing us to + * embed raw bytes as a string literal with ISO-8859-1 encoding. + */ + public static ByteString bytesDefaultValue(String bytes) { + try { + return ByteString.copyFrom(bytes.getBytes("ISO-8859-1")); + } catch (UnsupportedEncodingException e) { + // This should never happen since all JVMs are required to implement + // ISO-8859-1. + throw new IllegalStateException( + "Java VM does not support a standard character set.", e); + } + } + + /** + * Interface for an enum value or value descriptor, to be used in FieldSet. + * The lite library stores enum values directly in FieldSets but the full + * library stores EnumValueDescriptors in order to better support reflection. + */ + public interface EnumLite { + int getNumber(); + } + + /** + * Interface for an object which maps integers to {@link EnumLite}s. + * {@link Descriptors.EnumDescriptor} implements this interface by mapping + * numbers to {@link Descriptors.EnumValueDescriptor}s. Additionally, + * every generated enum type has a static method internalGetValueMap() which + * returns an implementation of this type that maps numbers to enum values. + */ + public interface EnumLiteMap { + T findValueByNumber(int number); + } +} diff --git a/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java index 593be0e9..90f7ffbc 100644 --- a/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java +++ b/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java @@ -39,7 +39,9 @@ import java.io.IOException; * @author kenton@google.com Kenton Varda */ public class InvalidProtocolBufferException extends IOException { - public InvalidProtocolBufferException(String description) { + private static final long serialVersionUID = -1616151763072450476L; + + public InvalidProtocolBufferException(final String description) { super(description); } diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java index a5951232..c11abdc5 100644 --- a/java/src/main/java/com/google/protobuf/Message.java +++ b/java/src/main/java/com/google/protobuf/Message.java @@ -33,17 +33,22 @@ package com.google.protobuf; -import java.io.InputStream; import java.io.IOException; -import java.io.OutputStream; +import java.io.InputStream; import java.util.Map; /** * Abstract interface implemented by Protocol Message objects. + *

+ * See also {@link MessageLite}, which defines most of the methods that typical + * users care about. {@link Message} adds to it methods that are not available + * in the "lite" runtime. The biggest added features are introspection and + * reflection -- i.e., getting descriptors for the message type and accessing + * the field values dynamically. * * @author kenton@google.com Kenton Varda */ -public interface Message { +public interface Message extends MessageLite { /** * Get the message's type's descriptor. This differs from the * {@code getDescriptor()} method of generated message classes in that @@ -53,14 +58,7 @@ public interface Message { */ Descriptors.Descriptor getDescriptorForType(); - /** - * Get an instance of the type with all fields set to their default values. - * This may or may not be a singleton. This differs from the - * {@code getDefaultInstance()} method of generated message classes in that - * this method is an abstract method of the {@code Message} interface - * whereas {@code getDefaultInstance()} is a static method of a specific - * class. They return the same thing. - */ + // (From MessageLite, re-declared here only for return type covariance.) Message getDefaultInstanceForType(); /** @@ -114,24 +112,6 @@ public interface Message { /** Get the {@link UnknownFieldSet} for this message. */ UnknownFieldSet getUnknownFields(); - /** - * Returns true if all required fields in the message and all embedded - * messages are set, false otherwise. - */ - boolean isInitialized(); - - /** - * Serializes the message and writes it to {@code output}. This does not - * flush or close the stream. - */ - void writeTo(CodedOutputStream output) throws IOException; - - /** - * Get the number of bytes required to encode this message. The result - * is only computed on the first call and memoized after that. - */ - int getSerializedSize(); - // ----------------------------------------------------------------- // Comparison and hashing @@ -144,6 +124,7 @@ public interface Message { * @param other object to be compared for equality with this message * @return true if the specified object is equal to this message */ + @Override boolean equals(Object other); /** @@ -154,6 +135,7 @@ public interface Message { * @return the hash code value for this message * @see Map#hashCode() */ + @Override int hashCode(); // ----------------------------------------------------------------- @@ -163,67 +145,22 @@ public interface Message { * Converts the message to a string in protocol buffer text format. This is * just a trivial wrapper around {@link TextFormat#printToString(Message)}. */ + @Override String toString(); - /** - * Serializes the message to a {@code ByteString} and returns it. This is - * just a trivial wrapper around - * {@link #writeTo(CodedOutputStream)}. - */ - ByteString toByteString(); - - /** - * Serializes the message to a {@code byte} array and returns it. This is - * just a trivial wrapper around - * {@link #writeTo(CodedOutputStream)}. - */ - byte[] toByteArray(); - - /** - * Serializes the message and writes it to {@code output}. This is just a - * trivial wrapper around {@link #writeTo(CodedOutputStream)}. This does - * not flush or close the stream. - *

- * NOTE: Protocol Buffers are not self-delimiting. Therefore, if you write - * any more data to the stream after the message, you must somehow ensure - * that the parser on the receiving end does not interpret this as being - * part of the protocol message. This can be done e.g. by writing the size - * of the message before the data, then making sure to limit the input to - * that size on the receiving end (e.g. by wrapping the InputStream in one - * which limits the input). Alternatively, just use - * {@link #writeDelimitedTo(OutputStream)}. - */ - void writeTo(OutputStream output) throws IOException; - - /** - * Like {@link #writeTo(OutputStream)}, but writes the size of the message - * as a varint before writing the data. This allows more data to be written - * to the stream after the message without the need to delimit the message - * data yourself. Use {@link Builder#mergeDelimitedFrom(InputStream)} (or - * the static method {@code YourMessageType.parseDelimitedFrom(InputStream)}) - * to parse messages written by this method. - */ - void writeDelimitedTo(OutputStream output) throws IOException; - // ================================================================= // Builders - /** - * Constructs a new builder for a message of the same type as this message. - */ + // (From MessageLite, re-declared here only for return type covariance.) Builder newBuilderForType(); - - /** - * Constructs a builder initialized with the current message. Use this to - * derive a new message from the current one. - */ Builder toBuilder(); /** * Abstract interface implemented by Protocol Message builders. */ - public static interface Builder extends Cloneable { - /** Resets all fields to their default values. */ + interface Builder extends MessageLite.Builder { + // (From MessageLite.Builder, re-declared here only for return type + // covariance.) Builder clear(); /** @@ -244,71 +181,14 @@ public interface Message { */ Builder mergeFrom(Message other); - /** - * Construct the final message. Once this is called, the Builder is no - * longer valid, and calling any other method may throw a - * NullPointerException. If you need to continue working with the builder - * after calling {@code build()}, {@code clone()} it first. - * @throws UninitializedMessageException The message is missing one or more - * required fields (i.e. {@link #isInitialized()} returns false). - * Use {@link #buildPartial()} to bypass this check. - */ + // (From MessageLite.Builder, re-declared here only for return type + // covariance.) Message build(); - - /** - * Like {@link #build()}, but does not throw an exception if the message - * is missing required fields. Instead, a partial message is returned. - */ Message buildPartial(); - - /** - * Clones the Builder. - * @see Object#clone() - */ Builder clone(); - - /** - * Returns true if all required fields in the message and all embedded - * messages are set, false otherwise. - */ - boolean isInitialized(); - - /** - * Parses a message of this type from the input and merges it with this - * message, as if using {@link Builder#mergeFrom(Message)}. - * - *

Warning: This does not verify that all required fields are present in - * the input message. If you call {@link #build()} without setting all - * required fields, it will throw an {@link UninitializedMessageException}, - * which is a {@code RuntimeException} and thus might not be caught. There - * are a few good ways to deal with this: - *

    - *
  • Call {@link #isInitialized()} to verify that all required fields - * are set before building. - *
  • Parse the message separately using one of the static - * {@code parseFrom} methods, then use {@link #mergeFrom(Message)} - * to merge it with this one. {@code parseFrom} will throw an - * {@link InvalidProtocolBufferException} (an {@code IOException}) - * if some required fields are missing. - *
  • Use {@code buildPartial()} to build, which ignores missing - * required fields. - *
- * - *

Note: The caller should call - * {@link CodedInputStream#checkLastTagWas(int)} after calling this to - * verify that the last tag seen was the appropriate end-group tag, - * or zero for EOF. - */ Builder mergeFrom(CodedInputStream input) throws IOException; - - /** - * Like {@link Builder#mergeFrom(CodedInputStream)}, but also - * parses extensions. The extensions that you want to be able to parse - * must be registered in {@code extensionRegistry}. Extensions not in - * the registry will be treated as unknown fields. - */ Builder mergeFrom(CodedInputStream input, - ExtensionRegistry extensionRegistry) + ExtensionRegistryLite extensionRegistry) throws IOException; /** @@ -317,10 +197,8 @@ public interface Message { */ Descriptors.Descriptor getDescriptorForType(); - /** - * Get the message's type's default instance. - * See {@link Message#getDefaultInstanceForType()}. - */ + // (From MessageLite.Builder, re-declared here only for return type + // covariance.) Message getDefaultInstanceForType(); /** @@ -399,92 +277,29 @@ public interface Message { // --------------------------------------------------------------- // Convenience methods. - /** - * Parse {@code data} as a message of this type and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream)}. - */ + // (From MessageLite.Builder, re-declared here only for return type + // covariance.) Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException; - - /** - * Parse {@code data} as a message of this type and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. - */ Builder mergeFrom(ByteString data, - ExtensionRegistry extensionRegistry) + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException; + Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException; - - /** - * Parse {@code data} as a message of this type and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream)}. - */ - public Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException; - - /** - * Parse {@code data} as a message of this type and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream)}. - */ - public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException; - - /** - * Parse {@code data} as a message of this type and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. - */ Builder mergeFrom(byte[] data, - ExtensionRegistry extensionRegistry) + ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; - - /** - * Parse {@code data} as a message of this type and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. - */ Builder mergeFrom(byte[] data, int off, int len, - ExtensionRegistry extensionRegistry) + ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException; - - /** - * Parse a message of this type from {@code input} and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream)}. Note that this method always - * reads the entire input (unless it throws an exception). If you - * want it to stop earlier, you will need to wrap your input in some - * wrapper stream that limits reading. Or, use - * {@link Message#writeDelimitedTo(OutputStream)} to write your message and - * {@link #mergeDelimitedFrom(InputStream)} to read it. - *

- * Despite usually reading the entire input, this does not close the stream. - */ Builder mergeFrom(InputStream input) throws IOException; - - /** - * Parse a message of this type from {@code input} and merge it with the - * message being built. This is just a small wrapper around - * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. - */ Builder mergeFrom(InputStream input, - ExtensionRegistry extensionRegistry) + ExtensionRegistryLite extensionRegistry) throws IOException; - - /** - * Like {@link #mergeFrom(InputStream)}, but does not read until EOF. - * Instead, the size of the message (encoded as a varint) is read first, - * then the message data. Use - * {@link Message#writeDelimitedTo(OutputStream)} to write messages in this - * format. - */ Builder mergeDelimitedFrom(InputStream input) throws IOException; - - /** - * Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions. - */ Builder mergeDelimitedFrom(InputStream input, - ExtensionRegistry extensionRegistry) + ExtensionRegistryLite extensionRegistry) throws IOException; } } diff --git a/java/src/main/java/com/google/protobuf/MessageLite.java b/java/src/main/java/com/google/protobuf/MessageLite.java new file mode 100644 index 00000000..3001f360 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/MessageLite.java @@ -0,0 +1,331 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// TODO(kenton): Use generics? E.g. Builder, then +// mergeFrom*() could return BuilderType for better type-safety. + +package com.google.protobuf; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Abstract interface implemented by Protocol Message objects. + * + *

This interface is implemented by all protocol message objects. Most + * users will be more interested in the Message interface, which is a subclass + * of MessageLite. Use MessageLite instead when you only need the subset of + * features which it supports -- namely, nothing that uses descriptors or + * reflection. You can instruct the protocol compiler to generate classes + * which implement only MessageLite, not the full Message interface, by adding + * the follow line to the .proto file: + *

+ *   option optimize_for = LITE_RUNTIME;
+ * 
+ * + *

This is particularly useful on resource-constrained systems where the + * full protocol buffers runtime library is too big. + * + *

Note that on non-constrained systems (e.g. servers) when you need to link + * in lots of protocol definitions, a better way to reduce total code footprint + * is to use {@code optimize_for = CODE_SIZE}. This will make the generated + * code smaller while still supporting all the same features (at the expense of + * speed). {@code optimize_for = LITE_RUNTIME} is best when you only have a + * small number of message types linked into your binary, in which case the + * size of the protocol buffers runtime itself is the biggest problem. + * + * @author kenton@google.com Kenton Varda + */ +public interface MessageLite { + /** + * Get an instance of the type with all fields set to their default values. + * This may or may not be a singleton. This differs from the + * {@code getDefaultInstance()} method of generated message classes in that + * this method is an abstract method of the {@code MessageLite} interface + * whereas {@code getDefaultInstance()} is a static method of a specific + * class. They return the same thing. + */ + MessageLite getDefaultInstanceForType(); + + /** + * Returns true if all required fields in the message and all embedded + * messages are set, false otherwise. + */ + boolean isInitialized(); + + /** + * Serializes the message and writes it to {@code output}. This does not + * flush or close the stream. + */ + void writeTo(CodedOutputStream output) throws IOException; + + /** + * Get the number of bytes required to encode this message. The result + * is only computed on the first call and memoized after that. + */ + int getSerializedSize(); + + // ----------------------------------------------------------------- + // Convenience methods. + + /** + * Serializes the message to a {@code ByteString} and returns it. This is + * just a trivial wrapper around + * {@link #writeTo(CodedOutputStream)}. + */ + ByteString toByteString(); + + /** + * Serializes the message to a {@code byte} array and returns it. This is + * just a trivial wrapper around + * {@link #writeTo(CodedOutputStream)}. + */ + byte[] toByteArray(); + + /** + * Serializes the message and writes it to {@code output}. This is just a + * trivial wrapper around {@link #writeTo(CodedOutputStream)}. This does + * not flush or close the stream. + *

+ * NOTE: Protocol Buffers are not self-delimiting. Therefore, if you write + * any more data to the stream after the message, you must somehow ensure + * that the parser on the receiving end does not interpret this as being + * part of the protocol message. This can be done e.g. by writing the size + * of the message before the data, then making sure to limit the input to + * that size on the receiving end (e.g. by wrapping the InputStream in one + * which limits the input). Alternatively, just use + * {@link #writeDelimitedTo(OutputStream)}. + */ + void writeTo(OutputStream output) throws IOException; + + /** + * Like {@link #writeTo(OutputStream)}, but writes the size of the message + * as a varint before writing the data. This allows more data to be written + * to the stream after the message without the need to delimit the message + * data yourself. Use {@link Builder#mergeDelimitedFrom(InputStream)} (or + * the static method {@code YourMessageType.parseDelimitedFrom(InputStream)}) + * to parse messages written by this method. + */ + void writeDelimitedTo(OutputStream output) throws IOException; + + // ================================================================= + // Builders + + /** + * Constructs a new builder for a message of the same type as this message. + */ + Builder newBuilderForType(); + + /** + * Constructs a builder initialized with the current message. Use this to + * derive a new message from the current one. + */ + Builder toBuilder(); + + /** + * Abstract interface implemented by Protocol Message builders. + */ + interface Builder extends Cloneable { + /** Resets all fields to their default values. */ + Builder clear(); + + /** + * Construct the final message. Once this is called, the Builder is no + * longer valid, and calling any other method will result in undefined + * behavior and may throw a NullPointerException. If you need to continue + * working with the builder after calling {@code build()}, {@code clone()} + * it first. + * @throws UninitializedMessageException The message is missing one or more + * required fields (i.e. {@link #isInitialized()} returns false). + * Use {@link #buildPartial()} to bypass this check. + */ + MessageLite build(); + + /** + * Like {@link #build()}, but does not throw an exception if the message + * is missing required fields. Instead, a partial message is returned. + * Once this is called, the Builder is no longer valid, and calling any + * will result in undefined behavior and may throw a NullPointerException. + * + * If you need to continue working with the builder after calling + * {@code buildPartial()}, {@code clone()} it first. + */ + MessageLite buildPartial(); + + /** + * Clones the Builder. + * @see Object#clone() + */ + Builder clone(); + + /** + * Returns true if all required fields in the message and all embedded + * messages are set, false otherwise. + */ + boolean isInitialized(); + + /** + * Parses a message of this type from the input and merges it with this + * message, as if using {@link Builder#mergeFrom(MessageLite)}. + * + *

Warning: This does not verify that all required fields are present in + * the input message. If you call {@link #build()} without setting all + * required fields, it will throw an {@link UninitializedMessageException}, + * which is a {@code RuntimeException} and thus might not be caught. There + * are a few good ways to deal with this: + *

    + *
  • Call {@link #isInitialized()} to verify that all required fields + * are set before building. + *
  • Parse the message separately using one of the static + * {@code parseFrom} methods, then use {@link #mergeFrom(MessageLite)} + * to merge it with this one. {@code parseFrom} will throw an + * {@link InvalidProtocolBufferException} (an {@code IOException}) + * if some required fields are missing. + *
  • Use {@code buildPartial()} to build, which ignores missing + * required fields. + *
+ * + *

Note: The caller should call + * {@link CodedInputStream#checkLastTagWas(int)} after calling this to + * verify that the last tag seen was the appropriate end-group tag, + * or zero for EOF. + */ + Builder mergeFrom(CodedInputStream input) throws IOException; + + /** + * Like {@link Builder#mergeFrom(CodedInputStream)}, but also + * parses extensions. The extensions that you want to be able to parse + * must be registered in {@code extensionRegistry}. Extensions not in + * the registry will be treated as unknown fields. + */ + Builder mergeFrom(CodedInputStream input, + ExtensionRegistryLite extensionRegistry) + throws IOException; + + /** + * Get the message's type's default instance. + * See {@link MessageLite#getDefaultInstanceForType()}. + */ + MessageLite getDefaultInstanceForType(); + + // --------------------------------------------------------------- + // Convenience methods. + + /** + * Parse {@code data} as a message of this type and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream)}. + */ + Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException; + + /** + * Parse {@code data} as a message of this type and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. + */ + Builder mergeFrom(ByteString data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Parse {@code data} as a message of this type and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream)}. + */ + Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException; + + /** + * Parse {@code data} as a message of this type and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream)}. + */ + Builder mergeFrom(byte[] data, int off, int len) + throws InvalidProtocolBufferException; + + /** + * Parse {@code data} as a message of this type and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. + */ + Builder mergeFrom(byte[] data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Parse {@code data} as a message of this type and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. + */ + Builder mergeFrom(byte[] data, int off, int len, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Parse a message of this type from {@code input} and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream)}. Note that this method always + * reads the entire input (unless it throws an exception). If you + * want it to stop earlier, you will need to wrap your input in some + * wrapper stream that limits reading. Or, use + * {@link MessageLite#writeDelimitedTo(OutputStream)} to write your message + * and {@link #mergeDelimitedFrom(InputStream)} to read it. + *

+ * Despite usually reading the entire input, this does not close the stream. + */ + Builder mergeFrom(InputStream input) throws IOException; + + /** + * Parse a message of this type from {@code input} and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. + */ + Builder mergeFrom(InputStream input, + ExtensionRegistryLite extensionRegistry) + throws IOException; + + /** + * Like {@link #mergeFrom(InputStream)}, but does not read until EOF. + * Instead, the size of the message (encoded as a varint) is read first, + * then the message data. Use + * {@link MessageLite#writeDelimitedTo(OutputStream)} to write messages in + * this format. + */ + Builder mergeDelimitedFrom(InputStream input) + throws IOException; + + /** + * Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions. + */ + Builder mergeDelimitedFrom(InputStream input, + ExtensionRegistryLite extensionRegistry) + throws IOException; + } +} diff --git a/java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java b/java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java index 8efca8af..112400f4 100644 --- a/java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java +++ b/java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java @@ -37,7 +37,7 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor; * Interface of useful methods added to all enums generated by the protocol * compiler. */ -public interface ProtocolMessageEnum { +public interface ProtocolMessageEnum extends Internal.EnumLite { /** * Return the value's numeric value as defined in the .proto file. diff --git a/java/src/main/java/com/google/protobuf/RpcUtil.java b/java/src/main/java/com/google/protobuf/RpcUtil.java index 8144bbfb..b1b959a8 100644 --- a/java/src/main/java/com/google/protobuf/RpcUtil.java +++ b/java/src/main/java/com/google/protobuf/RpcUtil.java @@ -71,11 +71,11 @@ public final class RpcUtil { final Class originalClass, final Type defaultInstance) { return new RpcCallback() { - public void run(Message parameter) { + public void run(final Message parameter) { Type typedParameter; try { typedParameter = originalClass.cast(parameter); - } catch (ClassCastException e) { + } catch (ClassCastException ignored) { typedParameter = copyAsType(defaultInstance, parameter); } originalCallback.run(typedParameter); @@ -90,7 +90,7 @@ public final class RpcUtil { */ @SuppressWarnings("unchecked") private static Type copyAsType( - Type typeDefaultInstance, Message source) { + final Type typeDefaultInstance, final Message source) { return (Type)typeDefaultInstance.newBuilderForType() .mergeFrom(source) .build(); @@ -106,8 +106,9 @@ public final class RpcUtil { RpcCallback newOneTimeCallback( final RpcCallback originalCallback) { return new RpcCallback() { - boolean alreadyCalled = false; - public void run(ParameterType parameter) { + private boolean alreadyCalled = false; + + public void run(final ParameterType parameter) { synchronized(this) { if (alreadyCalled) { throw new AlreadyCalledException(); @@ -124,6 +125,8 @@ public final class RpcUtil { * Exception thrown when a one-time callback is called more than once. */ public static final class AlreadyCalledException extends RuntimeException { + private static final long serialVersionUID = 5469741279507848266L; + public AlreadyCalledException() { super("This RpcCallback was already called and cannot be called " + "multiple times."); diff --git a/java/src/main/java/com/google/protobuf/ServiceException.java b/java/src/main/java/com/google/protobuf/ServiceException.java index 70b9d0c1..c043a775 100644 --- a/java/src/main/java/com/google/protobuf/ServiceException.java +++ b/java/src/main/java/com/google/protobuf/ServiceException.java @@ -32,11 +32,13 @@ package com.google.protobuf; /** * Thrown by blocking RPC methods when a failure occurs. - * + * * @author cpovirk@google.com (Chris Povirk) */ public final class ServiceException extends Exception { - public ServiceException(String message) { + private static final long serialVersionUID = -1219262335729891920L; + + public ServiceException(final String message) { super(message); } } diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java index 3dcf68c8..a855720b 100644 --- a/java/src/main/java/com/google/protobuf/TextFormat.java +++ b/java/src/main/java/com/google/protobuf/TextFormat.java @@ -52,22 +52,25 @@ import java.util.regex.Pattern; * @author kenton@google.com Kenton Varda */ public final class TextFormat { + private TextFormat() { + } /** * Outputs a textual representation of the Protocol Message supplied into * the parameter output. (This representation is the new version of the * classic "ProtocolPrinter" output from the original Protocol Buffer system) */ - public static void print(Message message, Appendable output) + public static void print(final Message message, final Appendable output) throws IOException { - TextGenerator generator = new TextGenerator(output); + final TextGenerator generator = new TextGenerator(output); print(message, generator); } /** Outputs a textual representation of {@code fields} to {@code output}. */ - public static void print(UnknownFieldSet fields, Appendable output) + public static void print(final UnknownFieldSet fields, + final Appendable output) throws IOException { - TextGenerator generator = new TextGenerator(output); + final TextGenerator generator = new TextGenerator(output); printUnknownFields(fields, generator); } @@ -75,9 +78,9 @@ public final class TextFormat { * Like {@code print()}, but writes directly to a {@code String} and * returns it. */ - public static String printToString(Message message) { + public static String printToString(final Message message) { try { - StringBuilder text = new StringBuilder(); + final StringBuilder text = new StringBuilder(); print(message, text); return text.toString(); } catch (IOException e) { @@ -91,9 +94,9 @@ public final class TextFormat { * Like {@code print()}, but writes directly to a {@code String} and * returns it. */ - public static String printToString(UnknownFieldSet fields) { + public static String printToString(final UnknownFieldSet fields) { try { - StringBuilder text = new StringBuilder(); + final StringBuilder text = new StringBuilder(); print(fields, text); return text.toString(); } catch (IOException e) { @@ -103,22 +106,44 @@ public final class TextFormat { } } - private static void print(Message message, TextGenerator generator) + private static void print(final Message message, + final TextGenerator generator) throws IOException { - for (Map.Entry field : + for (final Map.Entry field : message.getAllFields().entrySet()) { printField(field.getKey(), field.getValue(), generator); } printUnknownFields(message.getUnknownFields(), generator); } + + public static void printField(final FieldDescriptor field, + final Object value, + final Appendable output) + throws IOException { + final TextGenerator generator = new TextGenerator(output); + printField(field, value, generator); + } - public static void printField(FieldDescriptor field, - Object value, - TextGenerator generator) + public static String printFieldToString(final FieldDescriptor field, + final Object value) { + try { + final StringBuilder text = new StringBuilder(); + printField(field, value, text); + return text.toString(); + } catch (IOException e) { + throw new RuntimeException( + "Writing to a StringBuilder threw an IOException (should never " + + "happen).", e); + } + } + + private static void printField(final FieldDescriptor field, + final Object value, + final TextGenerator generator) throws IOException { if (field.isRepeated()) { // Repeated field. Print each element. - for (Object element : (List) value) { + for (final Object element : (List) value) { printSingleField(field, element, generator); } } else { @@ -126,9 +151,9 @@ public final class TextFormat { } } - private static void printSingleField(FieldDescriptor field, - Object value, - TextGenerator generator) + private static void printSingleField(final FieldDescriptor field, + final Object value, + final TextGenerator generator) throws IOException { if (field.isExtension()) { generator.print("["); @@ -168,9 +193,9 @@ public final class TextFormat { generator.print("\n"); } - private static void printFieldValue(FieldDescriptor field, - Object value, - TextGenerator generator) + private static void printFieldValue(final FieldDescriptor field, + final Object value, + final TextGenerator generator) throws IOException { switch (field.getType()) { case INT32: @@ -202,17 +227,15 @@ public final class TextFormat { generator.print("\""); break; - case BYTES: { + case BYTES: generator.print("\""); generator.print(escapeBytes((ByteString) value)); generator.print("\""); break; - } - case ENUM: { + case ENUM: generator.print(((EnumValueDescriptor) value).getName()); break; - } case MESSAGE: case GROUP: @@ -221,39 +244,39 @@ public final class TextFormat { } } - private static void printUnknownFields(UnknownFieldSet unknownFields, - TextGenerator generator) + private static void printUnknownFields(final UnknownFieldSet unknownFields, + final TextGenerator generator) throws IOException { - for (Map.Entry entry : + for (final Map.Entry entry : unknownFields.asMap().entrySet()) { - String prefix = entry.getKey().toString() + ": "; - UnknownFieldSet.Field field = entry.getValue(); + final String prefix = entry.getKey().toString() + ": "; + final UnknownFieldSet.Field field = entry.getValue(); - for (long value : field.getVarintList()) { + for (final long value : field.getVarintList()) { generator.print(entry.getKey().toString()); generator.print(": "); generator.print(unsignedToString(value)); generator.print("\n"); } - for (int value : field.getFixed32List()) { + for (final int value : field.getFixed32List()) { generator.print(entry.getKey().toString()); generator.print(": "); generator.print(String.format((Locale) null, "0x%08x", value)); generator.print("\n"); } - for (long value : field.getFixed64List()) { + for (final long value : field.getFixed64List()) { generator.print(entry.getKey().toString()); generator.print(": "); generator.print(String.format((Locale) null, "0x%016x", value)); generator.print("\n"); } - for (ByteString value : field.getLengthDelimitedList()) { + for (final ByteString value : field.getLengthDelimitedList()) { generator.print(entry.getKey().toString()); generator.print(": \""); generator.print(escapeBytes(value)); generator.print("\"\n"); } - for (UnknownFieldSet value : field.getGroupList()) { + for (final UnknownFieldSet value : field.getGroupList()) { generator.print(entry.getKey().toString()); generator.print(" {\n"); generator.indent(); @@ -265,7 +288,7 @@ public final class TextFormat { } /** Convert an unsigned 32-bit integer to a string. */ - private static String unsignedToString(int value) { + private static String unsignedToString(final int value) { if (value >= 0) { return Integer.toString(value); } else { @@ -274,7 +297,7 @@ public final class TextFormat { } /** Convert an unsigned 64-bit integer to a string. */ - private static String unsignedToString(long value) { + private static String unsignedToString(final long value) { if (value >= 0) { return Long.toString(value); } else { @@ -288,13 +311,12 @@ public final class TextFormat { /** * An inner class for writing text to the output stream. */ - static private final class TextGenerator { + private static final class TextGenerator { + private Appendable output; + private boolean atStartOfLine = true; + private final StringBuilder indent = new StringBuilder(); - Appendable output; - boolean atStartOfLine = true; - StringBuilder indent = new StringBuilder(); - - public TextGenerator(Appendable output) { + private TextGenerator(final Appendable output) { this.output = output; } @@ -312,7 +334,7 @@ public final class TextFormat { * level is zero. */ public void outdent() { - int length = indent.length(); + final int length = indent.length(); if (length == 0) { throw new IllegalArgumentException( " Outdent() without matching Indent()."); @@ -323,8 +345,8 @@ public final class TextFormat { /** * Print text to the output stream. */ - public void print(CharSequence text) throws IOException { - int size = text.length(); + public void print(final CharSequence text) throws IOException { + final int size = text.length(); int pos = 0; for (int i = 0; i < size; i++) { @@ -337,7 +359,8 @@ public final class TextFormat { write(text.subSequence(pos, size), size - pos); } - private void write(CharSequence data, int size) throws IOException { + private void write(final CharSequence data, final int size) + throws IOException { if (size == 0) { return; } @@ -399,27 +422,27 @@ public final class TextFormat { // We use possesive quantifiers (*+ and ++) because otherwise the Java // regex matcher has stack overflows on large inputs. - private static Pattern WHITESPACE = + private static final Pattern WHITESPACE = Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE); - private static Pattern TOKEN = Pattern.compile( + private static final Pattern TOKEN = Pattern.compile( "[a-zA-Z_][0-9a-zA-Z_+-]*+|" + // an identifier "[0-9+-][0-9a-zA-Z_.+-]*+|" + // a number "\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" + // a double-quoted string "\'([^\"\n\\\\]|\\\\.)*+(\'|\\\\?$)", // a single-quoted string Pattern.MULTILINE); - private static Pattern DOUBLE_INFINITY = Pattern.compile( + private static final Pattern DOUBLE_INFINITY = Pattern.compile( "-?inf(inity)?", Pattern.CASE_INSENSITIVE); - private static Pattern FLOAT_INFINITY = Pattern.compile( + private static final Pattern FLOAT_INFINITY = Pattern.compile( "-?inf(inity)?f?", Pattern.CASE_INSENSITIVE); - private static Pattern FLOAT_NAN = Pattern.compile( + private static final Pattern FLOAT_NAN = Pattern.compile( "nanf?", Pattern.CASE_INSENSITIVE); /** Construct a tokenizer that parses tokens from the given text. */ - public Tokenizer(CharSequence text) { + private Tokenizer(final CharSequence text) { this.text = text; this.matcher = WHITESPACE.matcher(text); skipWhitespace(); @@ -481,7 +504,7 @@ public final class TextFormat { * If the next token exactly matches {@code token}, consume it and return * {@code true}. Otherwise, return {@code false} without doing anything. */ - public boolean tryConsume(String token) { + public boolean tryConsume(final String token) { if (currentToken.equals(token)) { nextToken(); return true; @@ -494,7 +517,7 @@ public final class TextFormat { * If the next token exactly matches {@code token}, consume it. Otherwise, * throw a {@link ParseException}. */ - public void consume(String token) throws ParseException { + public void consume(final String token) throws ParseException { if (!tryConsume(token)) { throw parseException("Expected \"" + token + "\"."); } @@ -509,7 +532,7 @@ public final class TextFormat { return false; } - char c = currentToken.charAt(0); + final char c = currentToken.charAt(0); return ('0' <= c && c <= '9') || c == '-' || c == '+'; } @@ -520,7 +543,7 @@ public final class TextFormat { */ public String consumeIdentifier() throws ParseException { for (int i = 0; i < currentToken.length(); i++) { - char c = currentToken.charAt(i); + final char c = currentToken.charAt(i); if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || @@ -531,7 +554,7 @@ public final class TextFormat { } } - String result = currentToken; + final String result = currentToken; nextToken(); return result; } @@ -542,7 +565,7 @@ public final class TextFormat { */ public int consumeInt32() throws ParseException { try { - int result = parseInt32(currentToken); + final int result = parseInt32(currentToken); nextToken(); return result; } catch (NumberFormatException e) { @@ -556,7 +579,7 @@ public final class TextFormat { */ public int consumeUInt32() throws ParseException { try { - int result = parseUInt32(currentToken); + final int result = parseUInt32(currentToken); nextToken(); return result; } catch (NumberFormatException e) { @@ -570,7 +593,7 @@ public final class TextFormat { */ public long consumeInt64() throws ParseException { try { - long result = parseInt64(currentToken); + final long result = parseInt64(currentToken); nextToken(); return result; } catch (NumberFormatException e) { @@ -584,7 +607,7 @@ public final class TextFormat { */ public long consumeUInt64() throws ParseException { try { - long result = parseUInt64(currentToken); + final long result = parseUInt64(currentToken); nextToken(); return result; } catch (NumberFormatException e) { @@ -600,7 +623,7 @@ public final class TextFormat { // We need to parse infinity and nan separately because // Double.parseDouble() does not accept "inf", "infinity", or "nan". if (DOUBLE_INFINITY.matcher(currentToken).matches()) { - boolean negative = currentToken.startsWith("-"); + final boolean negative = currentToken.startsWith("-"); nextToken(); return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; } @@ -609,7 +632,7 @@ public final class TextFormat { return Double.NaN; } try { - double result = Double.parseDouble(currentToken); + final double result = Double.parseDouble(currentToken); nextToken(); return result; } catch (NumberFormatException e) { @@ -625,7 +648,7 @@ public final class TextFormat { // We need to parse infinity and nan separately because // Float.parseFloat() does not accept "inf", "infinity", or "nan". if (FLOAT_INFINITY.matcher(currentToken).matches()) { - boolean negative = currentToken.startsWith("-"); + final boolean negative = currentToken.startsWith("-"); nextToken(); return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY; } @@ -634,7 +657,7 @@ public final class TextFormat { return Float.NaN; } try { - float result = Float.parseFloat(currentToken); + final float result = Float.parseFloat(currentToken); nextToken(); return result; } catch (NumberFormatException e) { @@ -672,7 +695,8 @@ public final class TextFormat { * {@link ParseException}. */ public ByteString consumeByteString() throws ParseException { - char quote = currentToken.length() > 0 ? currentToken.charAt(0) : '\0'; + final char quote = currentToken.length() > 0 ? currentToken.charAt(0) + : '\0'; if (quote != '\"' && quote != '\'') { throw parseException("Expected string."); } @@ -683,11 +707,12 @@ public final class TextFormat { } try { - String escaped = currentToken.substring(1, currentToken.length() - 1); - ByteString result = unescapeBytes(escaped); + final String escaped = + currentToken.substring(1, currentToken.length() - 1); + final ByteString result = unescapeBytes(escaped); nextToken(); return result; - } catch (InvalidEscapeSequence e) { + } catch (InvalidEscapeSequenceException e) { throw parseException(e.getMessage()); } } @@ -696,7 +721,7 @@ public final class TextFormat { * Returns a {@link ParseException} with the current line and column * numbers in the description, suitable for throwing. */ - public ParseException parseException(String description) { + public ParseException parseException(final String description) { // Note: People generally prefer one-based line and column numbers. return new ParseException( (line + 1) + ":" + (column + 1) + ": " + description); @@ -706,7 +731,8 @@ public final class TextFormat { * Returns a {@link ParseException} with the line and column numbers of * the previous token in the description, suitable for throwing. */ - public ParseException parseExceptionPreviousToken(String description) { + public ParseException parseExceptionPreviousToken( + final String description) { // Note: People generally prefer one-based line and column numbers. return new ParseException( (previousLine + 1) + ":" + (previousColumn + 1) + ": " + description); @@ -716,7 +742,8 @@ public final class TextFormat { * Constructs an appropriate {@link ParseException} for the given * {@code NumberFormatException} when trying to parse an integer. */ - private ParseException integerParseException(NumberFormatException e) { + private ParseException integerParseException( + final NumberFormatException e) { return parseException("Couldn't parse integer: " + e.getMessage()); } @@ -724,14 +751,16 @@ public final class TextFormat { * Constructs an appropriate {@link ParseException} for the given * {@code NumberFormatException} when trying to parse a float or double. */ - private ParseException floatParseException(NumberFormatException e) { + private ParseException floatParseException(final NumberFormatException e) { return parseException("Couldn't parse number: " + e.getMessage()); } } /** Thrown when parsing an invalid text format message. */ public static class ParseException extends IOException { - public ParseException(String message) { + private static final long serialVersionUID = 3196188060225107702L; + + public ParseException(final String message) { super(message); } } @@ -740,9 +769,9 @@ public final class TextFormat { * Parse a text-format message from {@code input} and merge the contents * into {@code builder}. */ - public static void merge(Readable input, - Message.Builder builder) - throws ParseException, IOException { + public static void merge(final Readable input, + final Message.Builder builder) + throws IOException { merge(input, ExtensionRegistry.getEmptyRegistry(), builder); } @@ -750,8 +779,8 @@ public final class TextFormat { * Parse a text-format message from {@code input} and merge the contents * into {@code builder}. */ - public static void merge(CharSequence input, - Message.Builder builder) + public static void merge(final CharSequence input, + final Message.Builder builder) throws ParseException { merge(input, ExtensionRegistry.getEmptyRegistry(), builder); } @@ -761,10 +790,10 @@ public final class TextFormat { * into {@code builder}. Extensions will be recognized if they are * registered in {@code extensionRegistry}. */ - public static void merge(Readable input, - ExtensionRegistry extensionRegistry, - Message.Builder builder) - throws ParseException, IOException { + public static void merge(final Readable input, + final ExtensionRegistry extensionRegistry, + final Message.Builder builder) + throws IOException { // Read the entire input to a String then parse that. // If StreamTokenizer were not quite so crippled, or if there were a kind @@ -780,12 +809,12 @@ public final class TextFormat { // TODO(chrisn): See if working around java.io.Reader#read(CharBuffer) // overhead is worthwhile - private static StringBuilder toStringBuilder(Readable input) + private static StringBuilder toStringBuilder(final Readable input) throws IOException { - StringBuilder text = new StringBuilder(); - CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE); + final StringBuilder text = new StringBuilder(); + final CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE); while (true) { - int n = input.read(buffer); + final int n = input.read(buffer); if (n == -1) { break; } @@ -800,11 +829,11 @@ public final class TextFormat { * into {@code builder}. Extensions will be recognized if they are * registered in {@code extensionRegistry}. */ - public static void merge(CharSequence input, - ExtensionRegistry extensionRegistry, - Message.Builder builder) + public static void merge(final CharSequence input, + final ExtensionRegistry extensionRegistry, + final Message.Builder builder) throws ParseException { - Tokenizer tokenizer = new Tokenizer(input); + final Tokenizer tokenizer = new Tokenizer(input); while (!tokenizer.atEnd()) { mergeField(tokenizer, extensionRegistry, builder); @@ -815,19 +844,20 @@ public final class TextFormat { * Parse a single field from {@code tokenizer} and merge it into * {@code builder}. */ - private static void mergeField(Tokenizer tokenizer, - ExtensionRegistry extensionRegistry, - Message.Builder builder) + private static void mergeField(final Tokenizer tokenizer, + final ExtensionRegistry extensionRegistry, + final Message.Builder builder) throws ParseException { FieldDescriptor field; - Descriptor type = builder.getDescriptorForType(); + final Descriptor type = builder.getDescriptorForType(); ExtensionRegistry.ExtensionInfo extension = null; if (tokenizer.tryConsume("[")) { // An extension. - StringBuilder name = new StringBuilder(tokenizer.consumeIdentifier()); + final StringBuilder name = + new StringBuilder(tokenizer.consumeIdentifier()); while (tokenizer.tryConsume(".")) { - name.append("."); + name.append('.'); name.append(tokenizer.consumeIdentifier()); } @@ -846,7 +876,7 @@ public final class TextFormat { field = extension.descriptor; } else { - String name = tokenizer.consumeIdentifier(); + final String name = tokenizer.consumeIdentifier(); field = type.findFieldByName(name); // Group names are expected to be capitalized as they appear in the @@ -855,7 +885,7 @@ public final class TextFormat { if (field == null) { // Explicitly specify US locale so that this code does not break when // executing in Turkey. - String lowerName = name.toLowerCase(Locale.US); + final String lowerName = name.toLowerCase(Locale.US); field = type.findFieldByName(lowerName); // If the case-insensitive match worked but the field is NOT a group, if (field != null && field.getType() != FieldDescriptor.Type.GROUP) { @@ -880,7 +910,7 @@ public final class TextFormat { if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { tokenizer.tryConsume(":"); // optional - String endToken; + final String endToken; if (tokenizer.tryConsume("<")) { endToken = ">"; } else { @@ -888,7 +918,7 @@ public final class TextFormat { endToken = "}"; } - Message.Builder subBuilder; + final Message.Builder subBuilder; if (extension == null) { subBuilder = builder.newBuilderForField(field); } else { @@ -951,19 +981,19 @@ public final class TextFormat { value = tokenizer.consumeByteString(); break; - case ENUM: { - EnumDescriptor enumType = field.getEnumType(); + case ENUM: + final EnumDescriptor enumType = field.getEnumType(); if (tokenizer.lookingAtInteger()) { - int number = tokenizer.consumeInt32(); + final int number = tokenizer.consumeInt32(); value = enumType.findValueByNumber(number); if (value == null) { throw tokenizer.parseExceptionPreviousToken( "Enum type \"" + enumType.getFullName() + - "\" has no value with number " + number + "."); + "\" has no value with number " + number + '.'); } } else { - String id = tokenizer.consumeIdentifier(); + final String id = tokenizer.consumeIdentifier(); value = enumType.findValueByName(id); if (value == null) { throw tokenizer.parseExceptionPreviousToken( @@ -973,7 +1003,6 @@ public final class TextFormat { } break; - } case MESSAGE: case GROUP: @@ -1002,10 +1031,10 @@ public final class TextFormat { * which no defined short-hand escape sequence is defined will be escaped * using 3-digit octal sequences. */ - static String escapeBytes(ByteString input) { - StringBuilder builder = new StringBuilder(input.size()); + static String escapeBytes(final ByteString input) { + final StringBuilder builder = new StringBuilder(input.size()); for (int i = 0; i < input.size(); i++) { - byte b = input.byteAt(i); + final byte b = input.byteAt(i); switch (b) { // Java does not recognize \a or \v, apparently. case 0x07: builder.append("\\a" ); break; @@ -1038,9 +1067,9 @@ public final class TextFormat { * {@link #escapeBytes(ByteString)}. Two-digit hex escapes (starting with * "\x") are also recognized. */ - static ByteString unescapeBytes(CharSequence input) - throws InvalidEscapeSequence { - byte[] result = new byte[input.length()]; + static ByteString unescapeBytes(final CharSequence input) + throws InvalidEscapeSequenceException { + final byte[] result = new byte[input.length()]; int pos = 0; for (int i = 0; i < input.length(); i++) { char c = input.charAt(i); @@ -1080,7 +1109,7 @@ public final class TextFormat { ++i; code = digitValue(input.charAt(i)); } else { - throw new InvalidEscapeSequence( + throw new InvalidEscapeSequenceException( "Invalid escape sequence: '\\x' with no digits"); } if (i + 1 < input.length() && isHex(input.charAt(i + 1))) { @@ -1091,12 +1120,12 @@ public final class TextFormat { break; default: - throw new InvalidEscapeSequence( - "Invalid escape sequence: '\\" + c + "'"); + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\" + c + '\''); } } } else { - throw new InvalidEscapeSequence( + throw new InvalidEscapeSequenceException( "Invalid escape sequence: '\\' at end of string."); } } else { @@ -1111,8 +1140,10 @@ public final class TextFormat { * Thrown by {@link TextFormat#unescapeBytes} and * {@link TextFormat#unescapeText} when an invalid escape sequence is seen. */ - static class InvalidEscapeSequence extends IOException { - public InvalidEscapeSequence(String description) { + static class InvalidEscapeSequenceException extends IOException { + private static final long serialVersionUID = -8164033650142593304L; + + InvalidEscapeSequenceException(final String description) { super(description); } } @@ -1122,7 +1153,7 @@ public final class TextFormat { * Non-ASCII characters are first encoded as UTF-8, then each byte is escaped * individually as a 3-digit octal escape. Yes, it's weird. */ - static String escapeText(String input) { + static String escapeText(final String input) { return escapeBytes(ByteString.copyFromUtf8(input)); } @@ -1130,17 +1161,18 @@ public final class TextFormat { * Un-escape a text string as escaped using {@link #escapeText(String)}. * Two-digit hex escapes (starting with "\x") are also recognized. */ - static String unescapeText(String input) throws InvalidEscapeSequence { + static String unescapeText(final String input) + throws InvalidEscapeSequenceException { return unescapeBytes(input).toStringUtf8(); } /** Is this an octal digit? */ - private static boolean isOctal(char c) { + private static boolean isOctal(final char c) { return '0' <= c && c <= '7'; } /** Is this a hex digit? */ - private static boolean isHex(char c) { + private static boolean isHex(final char c) { return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); @@ -1151,7 +1183,7 @@ public final class TextFormat { * numeric value. This is like {@code Character.digit()} but we don't accept * non-ASCII digits. */ - private static int digitValue(char c) { + private static int digitValue(final char c) { if ('0' <= c && c <= '9') { return c - '0'; } else if ('a' <= c && c <= 'z') { @@ -1166,7 +1198,7 @@ public final class TextFormat { * {@code Integer.parseInt()}, this function recognizes the prefixes "0x" * and "0" to signify hexidecimal and octal numbers, respectively. */ - static int parseInt32(String text) throws NumberFormatException { + static int parseInt32(final String text) throws NumberFormatException { return (int) parseInteger(text, true, false); } @@ -1177,7 +1209,7 @@ public final class TextFormat { * result is coerced to a (signed) {@code int} when returned since Java has * no unsigned integer type. */ - static int parseUInt32(String text) throws NumberFormatException { + static int parseUInt32(final String text) throws NumberFormatException { return (int) parseInteger(text, false, false); } @@ -1186,7 +1218,7 @@ public final class TextFormat { * {@code Integer.parseInt()}, this function recognizes the prefixes "0x" * and "0" to signify hexidecimal and octal numbers, respectively. */ - static long parseInt64(String text) throws NumberFormatException { + static long parseInt64(final String text) throws NumberFormatException { return parseInteger(text, true, true); } @@ -1197,13 +1229,13 @@ public final class TextFormat { * result is coerced to a (signed) {@code long} when returned since Java has * no unsigned long type. */ - static long parseUInt64(String text) throws NumberFormatException { + static long parseUInt64(final String text) throws NumberFormatException { return parseInteger(text, false, true); } - private static long parseInteger(String text, - boolean isSigned, - boolean isLong) + private static long parseInteger(final String text, + final boolean isSigned, + final boolean isLong) throws NumberFormatException { int pos = 0; @@ -1224,7 +1256,7 @@ public final class TextFormat { radix = 8; } - String numberText = text.substring(pos); + final String numberText = text.substring(pos); long result = 0; if (numberText.length() < 16) { diff --git a/java/src/main/java/com/google/protobuf/UninitializedMessageException.java b/java/src/main/java/com/google/protobuf/UninitializedMessageException.java index a1032caa..8743c120 100644 --- a/java/src/main/java/com/google/protobuf/UninitializedMessageException.java +++ b/java/src/main/java/com/google/protobuf/UninitializedMessageException.java @@ -30,12 +30,8 @@ package com.google.protobuf; -import com.google.protobuf.Descriptors.FieldDescriptor; - -import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; /** * Thrown when attempting to build a protocol message that is missing required @@ -51,11 +47,15 @@ import java.util.Map; * @author kenton@google.com Kenton Varda */ public class UninitializedMessageException extends RuntimeException { - public UninitializedMessageException(Message message) { - this(findMissingFields(message)); + private static final long serialVersionUID = -7466929953374883507L; + + public UninitializedMessageException(final MessageLite message) { + super("Message was missing required fields. (Lite runtime could not " + + "determine which fields were missing)."); + missingFields = null; } - private UninitializedMessageException(List missingFields) { + public UninitializedMessageException(final List missingFields) { super(buildDescription(missingFields)); this.missingFields = missingFields; } @@ -65,6 +65,8 @@ public class UninitializedMessageException extends RuntimeException { /** * Get a list of human-readable names of required fields missing from this * message. Each name is a full path to a field, e.g. "foo.bar[5].baz". + * Returns null if the lite runtime was used, since it lacks the ability to + * find missing fields. */ public List getMissingFields() { return Collections.unmodifiableList(missingFields); @@ -80,11 +82,11 @@ public class UninitializedMessageException extends RuntimeException { } /** Construct the description string for this exception. */ - private static String buildDescription(List missingFields) { - StringBuilder description = + private static String buildDescription(final List missingFields) { + final StringBuilder description = new StringBuilder("Message missing required fields: "); boolean first = true; - for (String field : missingFields) { + for (final String field : missingFields) { if (first) { first = false; } else { @@ -94,67 +96,4 @@ public class UninitializedMessageException extends RuntimeException { } return description.toString(); } - - /** - * Populates {@code this.missingFields} with the full "path" of each - * missing required field in the given message. - */ - private static List findMissingFields(Message message) { - List results = new ArrayList(); - findMissingFields(message, "", results); - return results; - } - - /** Recursive helper implementing {@link #findMissingFields(Message)}. */ - private static void findMissingFields(Message message, String prefix, - List results) { - for (FieldDescriptor field : message.getDescriptorForType().getFields()) { - if (field.isRequired() && !message.hasField(field)) { - results.add(prefix + field.getName()); - } - } - - for (Map.Entry entry : - message.getAllFields().entrySet()) { - FieldDescriptor field = entry.getKey(); - Object value = entry.getValue(); - - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - if (field.isRepeated()) { - int i = 0; - for (Object element : (List) value) { - findMissingFields((Message) element, - subMessagePrefix(prefix, field, i++), - results); - } - } else { - if (message.hasField(field)) { - findMissingFields((Message) value, - subMessagePrefix(prefix, field, -1), - results); - } - } - } - } - } - - private static String subMessagePrefix(String prefix, - FieldDescriptor field, - int index) { - StringBuilder result = new StringBuilder(prefix); - if (field.isExtension()) { - result.append('(') - .append(field.getFullName()) - .append(')'); - } else { - result.append(field.getName()); - } - if (index != -1) { - result.append('[') - .append(index) - .append(']'); - } - result.append('.'); - return result.toString(); - } } diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java index 77fef323..239c2aca 100644 --- a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java +++ b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java @@ -30,15 +30,17 @@ package com.google.protobuf; -import java.io.InputStream; +import com.google.protobuf.Internal.ThreadLocalQuickQueue; + import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.TreeMap; import java.util.List; import java.util.Map; +import java.util.TreeMap; /** * {@code UnknownFieldSet} is used to keep track of fields which were seen when @@ -48,56 +50,59 @@ import java.util.Map; * compiled before the new types were added. * *

Every {@link Message} contains an {@code UnknownFieldSet} (and every - * {@link Message.Builder} contains an {@link UnknownFieldSet.Builder}). + * {@link Message.Builder} contains an {@link Builder}). * *

Most users will never need to use this class. * * @author kenton@google.com Kenton Varda */ -public final class UnknownFieldSet { +public final class UnknownFieldSet implements MessageLite { private UnknownFieldSet() {} - /** Create a new {@link UnknownFieldSet.Builder}. */ + /** Create a new {@link Builder}. */ public static Builder newBuilder() { - return new Builder(); + return Builder.create(); } /** - * Create a new {@link UnknownFieldSet.Builder} and initialize it to be a copy + * Create a new {@link Builder} and initialize it to be a copy * of {@code copyFrom}. */ - public static Builder newBuilder(UnknownFieldSet copyFrom) { - return new Builder().mergeFrom(copyFrom); + public static Builder newBuilder(final UnknownFieldSet copyFrom) { + return newBuilder().mergeFrom(copyFrom); } /** Get an empty {@code UnknownFieldSet}. */ public static UnknownFieldSet getDefaultInstance() { return defaultInstance; } - private static UnknownFieldSet defaultInstance = + public UnknownFieldSet getDefaultInstanceForType() { + return defaultInstance; + } + private static final UnknownFieldSet defaultInstance = new UnknownFieldSet(Collections.emptyMap()); /** * Construct an {@code UnknownFieldSet} around the given map. The map is * expected to be immutable. */ - private UnknownFieldSet(Map fields) { + private UnknownFieldSet(final Map fields) { this.fields = fields; } private Map fields; @Override - public boolean equals(Object other) { + public boolean equals(final Object other) { if (this == other) { return true; } return (other instanceof UnknownFieldSet) && - this.fields.equals(((UnknownFieldSet) other).fields); + fields.equals(((UnknownFieldSet) other).fields); } @Override public int hashCode() { - return this.fields.hashCode(); + return fields.hashCode(); } /** Get a map of fields in the set by number. */ @@ -106,7 +111,7 @@ public final class UnknownFieldSet { } /** Check if the given field number is present in the set. */ - public boolean hasField(int number) { + public boolean hasField(final int number) { return fields.containsKey(number); } @@ -114,14 +119,14 @@ public final class UnknownFieldSet { * Get a field by number. Returns an empty field if not present. Never * returns {@code null}. */ - public Field getField(int number) { - Field result = fields.get(number); + public Field getField(final int number) { + final Field result = fields.get(number); return (result == null) ? Field.getDefaultInstance() : result; } /** Serializes the set and writes it to {@code output}. */ - public void writeTo(CodedOutputStream output) throws IOException { - for (Map.Entry entry : fields.entrySet()) { + public void writeTo(final CodedOutputStream output) throws IOException { + for (final Map.Entry entry : fields.entrySet()) { entry.getValue().writeTo(entry.getKey(), output); } } @@ -131,7 +136,8 @@ public final class UnknownFieldSet { * just a trivial wrapper around * {@link TextFormat#printToString(UnknownFieldSet)}. */ - public final String toString() { + @Override + public String toString() { return TextFormat.printToString(this); } @@ -139,13 +145,13 @@ public final class UnknownFieldSet { * Serializes the message to a {@code ByteString} and returns it. This is * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}. */ - public final ByteString toByteString() { + public ByteString toByteString() { try { - ByteString.CodedBuilder out = + final ByteString.CodedBuilder out = ByteString.newCodedBuilder(getSerializedSize()); writeTo(out.getCodedOutput()); return out.build(); - } catch (IOException e) { + } catch (final IOException e) { throw new RuntimeException( "Serializing to a ByteString threw an IOException (should " + "never happen).", e); @@ -156,14 +162,14 @@ public final class UnknownFieldSet { * Serializes the message to a {@code byte} array and returns it. This is * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}. */ - public final byte[] toByteArray() { + public byte[] toByteArray() { try { - byte[] result = new byte[getSerializedSize()]; - CodedOutputStream output = CodedOutputStream.newInstance(result); + final byte[] result = new byte[getSerializedSize()]; + final CodedOutputStream output = CodedOutputStream.newInstance(result); writeTo(output); output.checkNoSpaceLeft(); return result; - } catch (IOException e) { + } catch (final IOException e) { throw new RuntimeException( "Serializing to a byte array threw an IOException " + "(should never happen).", e); @@ -174,8 +180,15 @@ public final class UnknownFieldSet { * Serializes the message and writes it to {@code output}. This is just a * trivial wrapper around {@link #writeTo(CodedOutputStream)}. */ - public final void writeTo(OutputStream output) throws IOException { - CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); + public void writeTo(final OutputStream output) throws IOException { + final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); + writeTo(codedOutput); + codedOutput.flush(); + } + + public void writeDelimitedTo(OutputStream output) throws IOException { + final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); + codedOutput.writeRawVarint32(getSerializedSize()); writeTo(codedOutput); codedOutput.flush(); } @@ -183,7 +196,7 @@ public final class UnknownFieldSet { /** Get the number of bytes required to encode this set. */ public int getSerializedSize() { int result = 0; - for (Map.Entry entry : fields.entrySet()) { + for (final Map.Entry entry : fields.entrySet()) { result += entry.getValue().getSerializedSize(entry.getKey()); } return result; @@ -193,9 +206,9 @@ public final class UnknownFieldSet { * Serializes the set and writes it to {@code output} using * {@code MessageSet} wire format. */ - public void writeAsMessageSetTo(CodedOutputStream output) + public void writeAsMessageSetTo(final CodedOutputStream output) throws IOException { - for (Map.Entry entry : fields.entrySet()) { + for (final Map.Entry entry : fields.entrySet()) { entry.getValue().writeAsMessageSetExtensionTo( entry.getKey(), output); } @@ -207,37 +220,51 @@ public final class UnknownFieldSet { */ public int getSerializedSizeAsMessageSet() { int result = 0; - for (Map.Entry entry : fields.entrySet()) { + for (final Map.Entry entry : fields.entrySet()) { result += entry.getValue().getSerializedSizeAsMessageSetExtension( entry.getKey()); } return result; } + public boolean isInitialized() { + // UnknownFieldSets do not have required fields, so they are always + // initialized. + return true; + } + /** Parse an {@code UnknownFieldSet} from the given input stream. */ - static public UnknownFieldSet parseFrom(CodedInputStream input) + public static UnknownFieldSet parseFrom(final CodedInputStream input) throws IOException { return newBuilder().mergeFrom(input).build(); } /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */ - public static UnknownFieldSet parseFrom(ByteString data) + public static UnknownFieldSet parseFrom(final ByteString data) throws InvalidProtocolBufferException { return newBuilder().mergeFrom(data).build(); } /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */ - public static UnknownFieldSet parseFrom(byte[] data) + public static UnknownFieldSet parseFrom(final byte[] data) throws InvalidProtocolBufferException { return newBuilder().mergeFrom(data).build(); } /** Parse an {@code UnknownFieldSet} from {@code input} and return it. */ - public static UnknownFieldSet parseFrom(InputStream input) + public static UnknownFieldSet parseFrom(final InputStream input) throws IOException { return newBuilder().mergeFrom(input).build(); } + public Builder newBuilderForType() { + return newBuilder(); + } + + public Builder toBuilder() { + return newBuilder().mergeFrom(this); + } + /** * Builder for {@link UnknownFieldSet}s. * @@ -250,21 +277,35 @@ public final class UnknownFieldSet { * *

Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}. */ - public static final class Builder { + public static final class Builder implements MessageLite.Builder { + private static ThreadLocalQuickQueue builders = + new ThreadLocalQuickQueue(); + + // This constructor should never be called directly (except from 'create'). private Builder() {} - private Map fields = new TreeMap(); + + private Map fields; // Optimization: We keep around a builder for the last field that was // modified so that we can efficiently add to it multiple times in a // row (important when parsing an unknown repeated field). - int lastFieldNumber = 0; - Field.Builder lastField = null; + private int lastFieldNumber; + private Field.Builder lastField; + + private static Builder create() { + Builder builder = builders.get().poll(); + if (builder == null) { + builder = new Builder(); + } + builder.reinitialize(); + return builder; + } /** * Get a field builder for the given field number which includes any * values that already exist. */ - private Field.Builder getFieldBuilder(int number) { + private Field.Builder getFieldBuilder(final int number) { if (lastField != null) { if (number == lastFieldNumber) { return lastField; @@ -275,7 +316,7 @@ public final class UnknownFieldSet { if (number == 0) { return null; } else { - Field existing = fields.get(number); + final Field existing = fields.get(number); lastFieldNumber = number; lastField = Field.newBuilder(); if (existing != null) { @@ -289,26 +330,48 @@ public final class UnknownFieldSet { * Build the {@link UnknownFieldSet} and return it. * *

Once {@code build()} has been called, the {@code Builder} will no - * longer be usable. Calling any method after {@code build()} will throw - * {@code NullPointerException}. + * longer be usable. Calling any method after {@code build()} will result + * in undefined behavior and can cause a {@code NullPointerException} to be + * thrown. */ public UnknownFieldSet build() { getFieldBuilder(0); // Force lastField to be built. - UnknownFieldSet result; + final UnknownFieldSet result; if (fields.isEmpty()) { result = getDefaultInstance(); } else { result = new UnknownFieldSet(Collections.unmodifiableMap(fields)); } fields = null; + builders.get().offer(this); return result; } - /** Reset the builder to an empty set. */ - public Builder clear() { - fields = new TreeMap(); + public UnknownFieldSet buildPartial() { + // No required fields, so this is the same as build(). + return build(); + } + + @Override + public Builder clone() { + getFieldBuilder(0); // Force lastField to be built. + return UnknownFieldSet.newBuilder().mergeFrom( + new UnknownFieldSet(fields)); + } + + public UnknownFieldSet getDefaultInstanceForType() { + return UnknownFieldSet.getDefaultInstance(); + } + + private void reinitialize() { + fields = Collections.emptyMap(); lastFieldNumber = 0; lastField = null; + } + + /** Reset the builder to an empty set. */ + public Builder clear() { + reinitialize(); return this; } @@ -317,9 +380,9 @@ public final class UnknownFieldSet { * exists in both sets, {@code other}'s values for that field will be * appended to the values in this set. */ - public Builder mergeFrom(UnknownFieldSet other) { + public Builder mergeFrom(final UnknownFieldSet other) { if (other != getDefaultInstance()) { - for (Map.Entry entry : other.fields.entrySet()) { + for (final Map.Entry entry : other.fields.entrySet()) { mergeField(entry.getKey(), entry.getValue()); } } @@ -330,7 +393,7 @@ public final class UnknownFieldSet { * Add a field to the {@code UnknownFieldSet}. If a field with the same * number already exists, the two are merged. */ - public Builder mergeField(int number, Field field) { + public Builder mergeField(final int number, final Field field) { if (number == 0) { throw new IllegalArgumentException("Zero is not a valid field number."); } @@ -350,7 +413,7 @@ public final class UnknownFieldSet { * value. This is used in particular when an unknown enum value is * encountered. */ - public Builder mergeVarintField(int number, int value) { + public Builder mergeVarintField(final int number, final int value) { if (number == 0) { throw new IllegalArgumentException("Zero is not a valid field number."); } @@ -359,7 +422,7 @@ public final class UnknownFieldSet { } /** Check if the given field number is present in the set. */ - public boolean hasField(int number) { + public boolean hasField(final int number) { if (number == 0) { throw new IllegalArgumentException("Zero is not a valid field number."); } @@ -370,7 +433,7 @@ public final class UnknownFieldSet { * Add a field to the {@code UnknownFieldSet}. If a field with the same * number already exists, it is removed. */ - public Builder addField(int number, Field field) { + public Builder addField(final int number, final Field field) { if (number == 0) { throw new IllegalArgumentException("Zero is not a valid field number."); } @@ -379,6 +442,9 @@ public final class UnknownFieldSet { lastField = null; lastFieldNumber = 0; } + if (fields.isEmpty()) { + fields = new TreeMap(); + } fields.put(number, field); return this; } @@ -396,9 +462,9 @@ public final class UnknownFieldSet { * Parse an entire message from {@code input} and merge its fields into * this set. */ - public Builder mergeFrom(CodedInputStream input) throws IOException { + public Builder mergeFrom(final CodedInputStream input) throws IOException { while (true) { - int tag = input.readTag(); + final int tag = input.readTag(); if (tag == 0 || !mergeFieldFrom(tag, input)) { break; } @@ -411,9 +477,9 @@ public final class UnknownFieldSet { * @param tag The field's tag number, which was already parsed. * @return {@code false} if the tag is an engroup tag. */ - public boolean mergeFieldFrom(int tag, CodedInputStream input) + public boolean mergeFieldFrom(final int tag, final CodedInputStream input) throws IOException { - int number = WireFormat.getTagFieldNumber(tag); + final int number = WireFormat.getTagFieldNumber(tag); switch (WireFormat.getTagWireType(tag)) { case WireFormat.WIRETYPE_VARINT: getFieldBuilder(number).addVarint(input.readInt64()); @@ -424,12 +490,12 @@ public final class UnknownFieldSet { case WireFormat.WIRETYPE_LENGTH_DELIMITED: getFieldBuilder(number).addLengthDelimited(input.readBytes()); return true; - case WireFormat.WIRETYPE_START_GROUP: { - UnknownFieldSet.Builder subBuilder = UnknownFieldSet.newBuilder(); - input.readUnknownGroup(number, subBuilder); + case WireFormat.WIRETYPE_START_GROUP: + final Builder subBuilder = newBuilder(); + input.readGroup(number, subBuilder, + ExtensionRegistry.getEmptyRegistry()); getFieldBuilder(number).addGroup(subBuilder.build()); return true; - } case WireFormat.WIRETYPE_END_GROUP: return false; case WireFormat.WIRETYPE_FIXED32: @@ -445,16 +511,16 @@ public final class UnknownFieldSet { * set being built. This is just a small wrapper around * {@link #mergeFrom(CodedInputStream)}. */ - public Builder mergeFrom(ByteString data) + public Builder mergeFrom(final ByteString data) throws InvalidProtocolBufferException { try { - CodedInputStream input = data.newCodedInput(); + final CodedInputStream input = data.newCodedInput(); mergeFrom(input); input.checkLastTagWas(0); return this; - } catch (InvalidProtocolBufferException e) { + } catch (final InvalidProtocolBufferException e) { throw e; - } catch (IOException e) { + } catch (final IOException e) { throw new RuntimeException( "Reading from a ByteString threw an IOException (should " + "never happen).", e); @@ -466,16 +532,16 @@ public final class UnknownFieldSet { * set being built. This is just a small wrapper around * {@link #mergeFrom(CodedInputStream)}. */ - public Builder mergeFrom(byte[] data) + public Builder mergeFrom(final byte[] data) throws InvalidProtocolBufferException { try { - CodedInputStream input = CodedInputStream.newInstance(data); + final CodedInputStream input = CodedInputStream.newInstance(data); mergeFrom(input); input.checkLastTagWas(0); return this; - } catch (InvalidProtocolBufferException e) { + } catch (final InvalidProtocolBufferException e) { throw e; - } catch (IOException e) { + } catch (final IOException e) { throw new RuntimeException( "Reading from a byte array threw an IOException (should " + "never happen).", e); @@ -487,12 +553,88 @@ public final class UnknownFieldSet { * set being built. This is just a small wrapper around * {@link #mergeFrom(CodedInputStream)}. */ - public Builder mergeFrom(InputStream input) throws IOException { - CodedInputStream codedInput = CodedInputStream.newInstance(input); + public Builder mergeFrom(final InputStream input) throws IOException { + final CodedInputStream codedInput = CodedInputStream.newInstance(input); mergeFrom(codedInput); codedInput.checkLastTagWas(0); return this; } + + public Builder mergeDelimitedFrom(InputStream input) + throws IOException { + final int size = CodedInputStream.readRawVarint32(input); + final InputStream limitedInput = + new AbstractMessage.Builder.LimitedInputStream(input, size); + return mergeFrom(limitedInput, null); + } + + public Builder mergeDelimitedFrom( + InputStream input, + ExtensionRegistryLite extensionRegistry) throws IOException { + // UnknownFieldSet has no extensions. + return mergeFrom(input); + } + + public Builder mergeFrom( + CodedInputStream input, + ExtensionRegistryLite extensionRegistry) throws IOException { + // UnknownFieldSet has no extensions. + return mergeFrom(input); + } + + public Builder mergeFrom( + ByteString data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + // UnknownFieldSet has no extensions. + return mergeFrom(data); + } + + public Builder mergeFrom(byte[] data, int off, int len) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = + CodedInputStream.newInstance(data, off, len); + mergeFrom(input); + input.checkLastTagWas(0); + return this; + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "Reading from a byte array threw an IOException (should " + + "never happen).", e); + } + } + + public Builder mergeFrom( + byte[] data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + // UnknownFieldSet has no extensions. + return mergeFrom(data); + } + + public Builder mergeFrom( + byte[] data, int off, int len, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + // UnknownFieldSet has no extensions. + return mergeFrom(data, off, len); + } + + public Builder mergeFrom( + InputStream input, + ExtensionRegistryLite extensionRegistry) throws IOException { + // UnknownFieldSet has no extensions. + return mergeFrom(input); + } + + public boolean isInitialized() { + // UnknownFieldSets do not have required fields, so they are always + // initialized. + return true; + } } /** @@ -510,7 +652,7 @@ public final class UnknownFieldSet { * wire types. * *

{@code Field} is an immutable class. To construct one, you must use a - * {@link Field.Builder}. + * {@link Builder}. * * @see UnknownFieldSet */ @@ -519,22 +661,22 @@ public final class UnknownFieldSet { /** Construct a new {@link Builder}. */ public static Builder newBuilder() { - return new Builder(); + return Builder.create(); } /** * Construct a new {@link Builder} and initialize it to a copy of * {@code copyFrom}. */ - public static Builder newBuilder(Field copyFrom) { - return new Builder().mergeFrom(copyFrom); + public static Builder newBuilder(final Field copyFrom) { + return newBuilder().mergeFrom(copyFrom); } /** Get an empty {@code Field}. */ public static Field getDefaultInstance() { - return defaultInstance; + return fieldDefaultInstance; } - private static Field defaultInstance = newBuilder().build(); + private static final Field fieldDefaultInstance = newBuilder().build(); /** Get the list of varint values for this field. */ public List getVarintList() { return varint; } @@ -556,14 +698,14 @@ public final class UnknownFieldSet { public List getGroupList() { return group; } @Override - public boolean equals(Object other) { + public boolean equals(final Object other) { if (this == other) { return true; } if (!(other instanceof Field)) { return false; } - return Arrays.equals(this.getIdentityArray(), + return Arrays.equals(getIdentityArray(), ((Field) other).getIdentityArray()); } @@ -574,37 +716,37 @@ public final class UnknownFieldSet { /** * Returns the array of objects to be used to uniquely identify this - * {@link UnknownFieldSet.Field} instance. + * {@link Field} instance. */ private Object[] getIdentityArray() { return new Object[] { - this.varint, - this.fixed32, - this.fixed64, - this.lengthDelimited, - this.group}; + varint, + fixed32, + fixed64, + lengthDelimited, + group}; } /** * Serializes the field, including field number, and writes it to * {@code output}. */ - public void writeTo(int fieldNumber, CodedOutputStream output) + public void writeTo(final int fieldNumber, final CodedOutputStream output) throws IOException { - for (long value : varint) { + for (final long value : varint) { output.writeUInt64(fieldNumber, value); } - for (int value : fixed32) { + for (final int value : fixed32) { output.writeFixed32(fieldNumber, value); } - for (long value : fixed64) { + for (final long value : fixed64) { output.writeFixed64(fieldNumber, value); } - for (ByteString value : lengthDelimited) { + for (final ByteString value : lengthDelimited) { output.writeBytes(fieldNumber, value); } - for (UnknownFieldSet value : group) { - output.writeUnknownGroup(fieldNumber, value); + for (final UnknownFieldSet value : group) { + output.writeGroup(fieldNumber, value); } } @@ -612,22 +754,22 @@ public final class UnknownFieldSet { * Get the number of bytes required to encode this field, including field * number. */ - public int getSerializedSize(int fieldNumber) { + public int getSerializedSize(final int fieldNumber) { int result = 0; - for (long value : varint) { + for (final long value : varint) { result += CodedOutputStream.computeUInt64Size(fieldNumber, value); } - for (int value : fixed32) { + for (final int value : fixed32) { result += CodedOutputStream.computeFixed32Size(fieldNumber, value); } - for (long value : fixed64) { + for (final long value : fixed64) { result += CodedOutputStream.computeFixed64Size(fieldNumber, value); } - for (ByteString value : lengthDelimited) { + for (final ByteString value : lengthDelimited) { result += CodedOutputStream.computeBytesSize(fieldNumber, value); } - for (UnknownFieldSet value : group) { - result += CodedOutputStream.computeUnknownGroupSize(fieldNumber, value); + for (final UnknownFieldSet value : group) { + result += CodedOutputStream.computeGroupSize(fieldNumber, value); } return result; } @@ -637,10 +779,10 @@ public final class UnknownFieldSet { * {@code output}, using {@code MessageSet} wire format. */ public void writeAsMessageSetExtensionTo( - int fieldNumber, - CodedOutputStream output) + final int fieldNumber, + final CodedOutputStream output) throws IOException { - for (ByteString value : lengthDelimited) { + for (final ByteString value : lengthDelimited) { output.writeRawMessageSetExtension(fieldNumber, value); } } @@ -649,9 +791,9 @@ public final class UnknownFieldSet { * Get the number of bytes required to encode this field, including field * number, using {@code MessageSet} wire format. */ - public int getSerializedSizeAsMessageSetExtension(int fieldNumber) { + public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) { int result = 0; - for (ByteString value : lengthDelimited) { + for (final ByteString value : lengthDelimited) { result += CodedOutputStream.computeRawMessageSetExtensionSize( fieldNumber, value); } @@ -670,13 +812,29 @@ public final class UnknownFieldSet { *

Use {@link Field#newBuilder()} to construct a {@code Builder}. */ public static final class Builder { + private static ThreadLocalQuickQueue builders = + new ThreadLocalQuickQueue(); + + // This constructor should never be called directly (except from 'create'). private Builder() {} - private Field result = new Field(); + + private static Builder create() { + Builder builder = builders.get().poll(); + if (builder == null) { + builder = new Builder(); + } + + builder.result = new Field(); + return builder; + } + + private Field result; /** * Build the field. After {@code build()} has been called, the * {@code Builder} is no longer usable. Calling any other method will - * throw a {@code NullPointerException}. + * result in undefined behavior and can cause a + * {@code NullPointerException} to be thrown. */ public Field build() { if (result.varint == null) { @@ -706,8 +864,9 @@ public final class UnknownFieldSet { result.group = Collections.unmodifiableList(result.group); } - Field returnMe = result; + final Field returnMe = result; result = null; + builders.get().offer(this); return returnMe; } @@ -722,7 +881,7 @@ public final class UnknownFieldSet { * of values, {@code other}'s values are append to the ones in this * field. */ - public Builder mergeFrom(Field other) { + public Builder mergeFrom(final Field other) { if (!other.varint.isEmpty()) { if (result.varint == null) { result.varint = new ArrayList(); @@ -757,7 +916,7 @@ public final class UnknownFieldSet { } /** Add a varint value. */ - public Builder addVarint(long value) { + public Builder addVarint(final long value) { if (result.varint == null) { result.varint = new ArrayList(); } @@ -766,7 +925,7 @@ public final class UnknownFieldSet { } /** Add a fixed32 value. */ - public Builder addFixed32(int value) { + public Builder addFixed32(final int value) { if (result.fixed32 == null) { result.fixed32 = new ArrayList(); } @@ -775,7 +934,7 @@ public final class UnknownFieldSet { } /** Add a fixed64 value. */ - public Builder addFixed64(long value) { + public Builder addFixed64(final long value) { if (result.fixed64 == null) { result.fixed64 = new ArrayList(); } @@ -784,7 +943,7 @@ public final class UnknownFieldSet { } /** Add a length-delimited value. */ - public Builder addLengthDelimited(ByteString value) { + public Builder addLengthDelimited(final ByteString value) { if (result.lengthDelimited == null) { result.lengthDelimited = new ArrayList(); } @@ -793,7 +952,7 @@ public final class UnknownFieldSet { } /** Add an embedded group. */ - public Builder addGroup(UnknownFieldSet value) { + public Builder addGroup(final UnknownFieldSet value) { if (result.group == null) { result.group = new ArrayList(); } diff --git a/java/src/main/java/com/google/protobuf/WireFormat.java b/java/src/main/java/com/google/protobuf/WireFormat.java index 2faf2448..3b0bdcd0 100644 --- a/java/src/main/java/com/google/protobuf/WireFormat.java +++ b/java/src/main/java/com/google/protobuf/WireFormat.java @@ -56,54 +56,84 @@ public final class WireFormat { static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1; /** Given a tag value, determines the wire type (the lower 3 bits). */ - static int getTagWireType(int tag) { + static int getTagWireType(final int tag) { return tag & TAG_TYPE_MASK; } /** Given a tag value, determines the field number (the upper 29 bits). */ - public static int getTagFieldNumber(int tag) { + public static int getTagFieldNumber(final int tag) { return tag >>> TAG_TYPE_BITS; } /** Makes a tag value given a field number and wire type. */ - static int makeTag(int fieldNumber, int wireType) { + static int makeTag(final int fieldNumber, final int wireType) { return (fieldNumber << TAG_TYPE_BITS) | wireType; } - static int getWireFormatForFieldType(Descriptors.FieldDescriptor.Type type) { - switch (type) { - case DOUBLE : return WIRETYPE_FIXED64; - case FLOAT : return WIRETYPE_FIXED32; - case INT64 : return WIRETYPE_VARINT; - case UINT64 : return WIRETYPE_VARINT; - case INT32 : return WIRETYPE_VARINT; - case FIXED64 : return WIRETYPE_FIXED64; - case FIXED32 : return WIRETYPE_FIXED32; - case BOOL : return WIRETYPE_VARINT; - case STRING : return WIRETYPE_LENGTH_DELIMITED; - case GROUP : return WIRETYPE_START_GROUP; - case MESSAGE : return WIRETYPE_LENGTH_DELIMITED; - case BYTES : return WIRETYPE_LENGTH_DELIMITED; - case UINT32 : return WIRETYPE_VARINT; - case ENUM : return WIRETYPE_VARINT; - case SFIXED32: return WIRETYPE_FIXED32; - case SFIXED64: return WIRETYPE_FIXED64; - case SINT32 : return WIRETYPE_VARINT; - case SINT64 : return WIRETYPE_VARINT; + /** + * Lite equivalent to {@link Descriptors.FieldDescriptor.JavaType}. This is + * only here to support the lite runtime and should not be used by users. + */ + public enum JavaType { + INT(0), + LONG(0L), + FLOAT(0F), + DOUBLE(0D), + BOOLEAN(false), + STRING(""), + BYTE_STRING(ByteString.EMPTY), + ENUM(null), + MESSAGE(null); + + JavaType(final Object defaultDefault) { + this.defaultDefault = defaultDefault; + } + + /** + * The default default value for fields of this type, if it's a primitive + * type. + */ + Object getDefaultDefault() { + return defaultDefault; } - throw new RuntimeException( - "There is no way to get here, but the compiler thinks otherwise."); + private final Object defaultDefault; } - /** Given a field descriptor, returns the wire type. This differs from - * getWireFormatForFieldType for packed repeated fields. */ - static int getWireFormatForField(Descriptors.FieldDescriptor descriptor) { - if (descriptor.getOptions().getPacked()) { - return WIRETYPE_LENGTH_DELIMITED; - } else { - return getWireFormatForFieldType(descriptor.getType()); + /** + * Lite equivalent to {@link Descriptors.FieldDescriptor.Type}. This is + * only here to support the lite runtime and should not be used by users. + */ + public enum FieldType { + DOUBLE (JavaType.DOUBLE , WIRETYPE_FIXED64 ), + FLOAT (JavaType.FLOAT , WIRETYPE_FIXED32 ), + INT64 (JavaType.LONG , WIRETYPE_VARINT ), + UINT64 (JavaType.LONG , WIRETYPE_VARINT ), + INT32 (JavaType.INT , WIRETYPE_VARINT ), + FIXED64 (JavaType.LONG , WIRETYPE_FIXED64 ), + FIXED32 (JavaType.INT , WIRETYPE_FIXED32 ), + BOOL (JavaType.BOOLEAN , WIRETYPE_VARINT ), + STRING (JavaType.STRING , WIRETYPE_LENGTH_DELIMITED), + GROUP (JavaType.MESSAGE , WIRETYPE_START_GROUP ), + MESSAGE (JavaType.MESSAGE , WIRETYPE_LENGTH_DELIMITED), + BYTES (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED), + UINT32 (JavaType.INT , WIRETYPE_VARINT ), + ENUM (JavaType.ENUM , WIRETYPE_VARINT ), + SFIXED32(JavaType.INT , WIRETYPE_FIXED32 ), + SFIXED64(JavaType.LONG , WIRETYPE_FIXED64 ), + SINT32 (JavaType.INT , WIRETYPE_VARINT ), + SINT64 (JavaType.LONG , WIRETYPE_VARINT ); + + FieldType(final JavaType javaType, final int wireType) { + this.javaType = javaType; + this.wireType = wireType; } + + private final JavaType javaType; + private final int wireType; + + public JavaType getJavaType() { return javaType; } + public int getWireType() { return wireType; } } // Field numbers for feilds in MessageSet wire format. diff --git a/java/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/src/test/java/com/google/protobuf/DescriptorsTest.java index 84a75977..6fa56267 100644 --- a/java/src/test/java/com/google/protobuf/DescriptorsTest.java +++ b/java/src/test/java/com/google/protobuf/DescriptorsTest.java @@ -367,4 +367,34 @@ public class DescriptorsTest extends TestCase { assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2, method.getOptions().getExtension(UnittestCustomOptions.methodOpt1)); } + + /** + * Test that the FieldDescriptor.Type enum is the same as the + * WireFormat.FieldType enum. + */ + public void testFieldTypeTablesMatch() throws Exception { + FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values(); + WireFormat.FieldType[] values2 = WireFormat.FieldType.values(); + + assertEquals(values1.length, values2.length); + + for (int i = 0; i < values1.length; i++) { + assertEquals(values1[i].toString(), values2[i].toString()); + } + } + + /** + * Test that the FieldDescriptor.JavaType enum is the same as the + * WireFormat.JavaType enum. + */ + public void testJavaTypeTablesMatch() throws Exception { + FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values(); + WireFormat.JavaType[] values2 = WireFormat.JavaType.values(); + + assertEquals(values1.length, values2.length); + + for (int i = 0; i < values1.length; i++) { + assertEquals(values1[i].toString(), values2[i].toString()); + } + } } diff --git a/java/src/test/java/com/google/protobuf/DynamicMessageTest.java b/java/src/test/java/com/google/protobuf/DynamicMessageTest.java index 120b0f13..aabccda2 100644 --- a/java/src/test/java/com/google/protobuf/DynamicMessageTest.java +++ b/java/src/test/java/com/google/protobuf/DynamicMessageTest.java @@ -73,6 +73,18 @@ public class DynamicMessageTest extends TestCase { } } + public void testClearAfterBuildError() throws Exception { + Message.Builder builder = + DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); + builder.build(); + try { + builder.clear(); + fail("Should have thrown exception."); + } catch (IllegalStateException e) { + // Success. + } + } + public void testDynamicMessageSettersRejectNull() throws Exception { Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java index 58d82193..cdf60c5e 100644 --- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java +++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java @@ -43,6 +43,8 @@ import protobuf_unittest.MultipleFilesTestProto; import protobuf_unittest.MessageWithNoOuter; import protobuf_unittest.EnumWithNoOuter; import protobuf_unittest.ServiceWithNoOuter; +import com.google.protobuf.UnittestLite; +import com.google.protobuf.UnittestLite.TestAllExtensionsLite; import junit.framework.TestCase; import java.util.Arrays; @@ -82,6 +84,17 @@ public class GeneratedMessageTest extends TestCase { } } + public void testClearAfterBuildError() throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + builder.build(); + try { + builder.clear(); + fail("Should have thrown exception."); + } catch (IllegalStateException e) { + // Success. + } + } + public void testSettersRejectNull() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); try { @@ -338,6 +351,16 @@ public class GeneratedMessageTest extends TestCase { instanceof ProtocolMessageEnum); } + public void testEnumMap() throws Exception { + Internal.EnumLiteMap map = ForeignEnum.internalGetValueMap(); + + for (ForeignEnum value : ForeignEnum.values()) { + assertEquals(value, map.findValueByNumber(value.getNumber())); + } + + assertTrue(map.findValueByNumber(12345) == null); + } + // ================================================================= // Extensions. @@ -420,6 +443,12 @@ public class GeneratedMessageTest extends TestCase { .getExtensionCount(UnittestProto.repeatedInt32Extension)); } + public void testExtensionCopy() throws Exception { + TestAllExtensions original = TestUtil.getAllExtensionsSet(); + TestAllExtensions copy = TestAllExtensions.newBuilder(original).build(); + TestUtil.assertAllExtensionsSet(copy); + } + public void testExtensionMergeFrom() throws Exception { TestAllExtensions original = TestAllExtensions.newBuilder() @@ -431,6 +460,66 @@ public class GeneratedMessageTest extends TestCase { 1, (int) merged.getExtension(UnittestProto.optionalInt32Extension)); } + // ================================================================= + // Lite Extensions. + + // We test lite extensions directly because they have a separate + // implementation from full extensions. In contrast, we do not test + // lite fields directly since they are implemented exactly the same as + // regular fields. + + public void testLiteExtensionAccessors() throws Exception { + TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder(); + TestUtil.setAllExtensions(builder); + TestAllExtensionsLite message = builder.build(); + TestUtil.assertAllExtensionsSet(message); + } + + public void testLiteExtensionRepeatedSetters() throws Exception { + TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder(); + TestUtil.setAllExtensions(builder); + TestUtil.modifyRepeatedExtensions(builder); + TestAllExtensionsLite message = builder.build(); + TestUtil.assertRepeatedExtensionsModified(message); + } + + public void testLiteExtensionDefaults() throws Exception { + TestUtil.assertExtensionsClear(TestAllExtensionsLite.getDefaultInstance()); + TestUtil.assertExtensionsClear(TestAllExtensionsLite.newBuilder().build()); + } + + public void testClearLiteExtension() throws Exception { + // clearExtension() is not actually used in TestUtil, so try it manually. + assertFalse( + TestAllExtensionsLite.newBuilder() + .setExtension(UnittestLite.optionalInt32ExtensionLite, 1) + .clearExtension(UnittestLite.optionalInt32ExtensionLite) + .hasExtension(UnittestLite.optionalInt32ExtensionLite)); + assertEquals(0, + TestAllExtensionsLite.newBuilder() + .addExtension(UnittestLite.repeatedInt32ExtensionLite, 1) + .clearExtension(UnittestLite.repeatedInt32ExtensionLite) + .getExtensionCount(UnittestLite.repeatedInt32ExtensionLite)); + } + + public void testLiteExtensionCopy() throws Exception { + TestAllExtensionsLite original = TestUtil.getAllLiteExtensionsSet(); + TestAllExtensionsLite copy = + TestAllExtensionsLite.newBuilder(original).build(); + TestUtil.assertAllExtensionsSet(copy); + } + + public void testLiteExtensionMergeFrom() throws Exception { + TestAllExtensionsLite original = + TestAllExtensionsLite.newBuilder() + .setExtension(UnittestLite.optionalInt32ExtensionLite, 1).build(); + TestAllExtensionsLite merged = + TestAllExtensionsLite.newBuilder().mergeFrom(original).build(); + assertTrue(merged.hasExtension(UnittestLite.optionalInt32ExtensionLite)); + assertEquals( + 1, (int) merged.getExtension(UnittestLite.optionalInt32ExtensionLite)); + } + // ================================================================= // multiple_files_test diff --git a/java/src/test/java/com/google/protobuf/LiteTest.java b/java/src/test/java/com/google/protobuf/LiteTest.java new file mode 100644 index 00000000..9dd730c2 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/LiteTest.java @@ -0,0 +1,114 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +package com.google.protobuf; + +import com.google.protobuf.UnittestLite; +import com.google.protobuf.UnittestLite.TestAllTypesLite; +import com.google.protobuf.UnittestLite.TestAllExtensionsLite; +import com.google.protobuf.UnittestLite.TestNestedExtensionLite; + +import junit.framework.TestCase; + +/** + * Test lite runtime. + * + * @author kenton@google.com Kenton Varda + */ +public class LiteTest extends TestCase { + public void setUp() throws Exception { + // Test that nested extensions are initialized correctly even if the outer + // class has not been accessed directly. This was once a bug with lite + // messages. + // + // We put this in setUp() rather than in its own test method because we + // need to make sure it runs before any actual tests. + assertTrue(TestNestedExtensionLite.nestedExtension != null); + } + + public void testLite() throws Exception { + // Since lite messages are a subset of regular messages, we can mostly + // assume that the functionality of lite messages is already thoroughly + // tested by the regular tests. All this test really verifies is that + // a proto with optimize_for = LITE_RUNTIME compiles correctly when + // linked only against the lite library. That is all tested at compile + // time, leaving not much to do in this method. Let's just do some random + // stuff to make sure the lite message is actually here and usable. + + TestAllTypesLite message = + TestAllTypesLite.newBuilder() + .setOptionalInt32(123) + .addRepeatedString("hello") + .setOptionalNestedMessage( + TestAllTypesLite.NestedMessage.newBuilder().setBb(7)) + .build(); + + ByteString data = message.toByteString(); + + TestAllTypesLite message2 = TestAllTypesLite.parseFrom(data); + + assertEquals(123, message2.getOptionalInt32()); + assertEquals(1, message2.getRepeatedStringCount()); + assertEquals("hello", message2.getRepeatedString(0)); + assertEquals(7, message2.getOptionalNestedMessage().getBb()); + } + + public void testLiteExtensions() throws Exception { + // TODO(kenton): Unlike other features of the lite library, extensions are + // implemented completely differently from the regular library. We + // need to test them more thoroughly, once they are fully-implemented. + + TestAllExtensionsLite message = + TestAllExtensionsLite.newBuilder() + .setExtension(UnittestLite.optionalInt32ExtensionLite, 123) + .addExtension(UnittestLite.repeatedStringExtensionLite, "hello") + .setExtension(UnittestLite.optionalNestedEnumExtensionLite, + TestAllTypesLite.NestedEnum.BAZ) + .setExtension(UnittestLite.optionalNestedMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build()) + .build(); + + // Test copying a message, since coping extensions actually does use a + // different code path between lite and regular libraries, and as of this + // writing, parsing hasn't been implemented yet. + TestAllExtensionsLite message2 = message.toBuilder().build(); + + assertEquals(123, (int) message2.getExtension( + UnittestLite.optionalInt32ExtensionLite)); + assertEquals(1, message2.getExtensionCount( + UnittestLite.repeatedStringExtensionLite)); + assertEquals("hello", message2.getExtension( + UnittestLite.repeatedStringExtensionLite, 0)); + assertEquals(TestAllTypesLite.NestedEnum.BAZ, message2.getExtension( + UnittestLite.optionalNestedEnumExtensionLite)); + assertEquals(7, message2.getExtension( + UnittestLite.optionalNestedMessageExtensionLite).getBb()); + } +} diff --git a/java/src/test/java/com/google/protobuf/TestUtil.java b/java/src/test/java/com/google/protobuf/TestUtil.java index 2f47b714..805c42ae 100644 --- a/java/src/test/java/com/google/protobuf/TestUtil.java +++ b/java/src/test/java/com/google/protobuf/TestUtil.java @@ -31,6 +31,7 @@ package com.google.protobuf; import protobuf_unittest.UnittestProto; +import com.google.protobuf.UnittestLite; // The static imports are to avoid 100+ char lines. The following is roughly equivalent to // import static protobuf_unittest.UnittestProto.*; @@ -123,6 +124,95 @@ import static protobuf_unittest.UnittestProto.packedDoubleExtension; import static protobuf_unittest.UnittestProto.packedBoolExtension; import static protobuf_unittest.UnittestProto.packedEnumExtension; +import static com.google.protobuf.UnittestLite.defaultInt32ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultInt64ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultUint32ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultUint64ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultSint32ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultSint64ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultFixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultFixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultSfixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultSfixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.defaultFloatExtensionLite; +import static com.google.protobuf.UnittestLite.defaultDoubleExtensionLite; +import static com.google.protobuf.UnittestLite.defaultBoolExtensionLite; +import static com.google.protobuf.UnittestLite.defaultStringExtensionLite; +import static com.google.protobuf.UnittestLite.defaultBytesExtensionLite; +import static com.google.protobuf.UnittestLite.defaultNestedEnumExtensionLite; +import static com.google.protobuf.UnittestLite.defaultForeignEnumExtensionLite; +import static com.google.protobuf.UnittestLite.defaultImportEnumExtensionLite; +import static com.google.protobuf.UnittestLite.defaultStringPieceExtensionLite; +import static com.google.protobuf.UnittestLite.defaultCordExtensionLite; + +import static com.google.protobuf.UnittestLite.optionalInt32ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalInt64ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalUint32ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalUint64ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalSint32ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalSint64ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalFixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalFixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalSfixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalSfixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.optionalFloatExtensionLite; +import static com.google.protobuf.UnittestLite.optionalDoubleExtensionLite; +import static com.google.protobuf.UnittestLite.optionalBoolExtensionLite; +import static com.google.protobuf.UnittestLite.optionalStringExtensionLite; +import static com.google.protobuf.UnittestLite.optionalBytesExtensionLite; +import static com.google.protobuf.UnittestLite.optionalGroupExtensionLite; +import static com.google.protobuf.UnittestLite.optionalNestedMessageExtensionLite; +import static com.google.protobuf.UnittestLite.optionalForeignMessageExtensionLite; +import static com.google.protobuf.UnittestLite.optionalImportMessageExtensionLite; +import static com.google.protobuf.UnittestLite.optionalNestedEnumExtensionLite; +import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite; +import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite; +import static com.google.protobuf.UnittestLite.optionalStringPieceExtensionLite; +import static com.google.protobuf.UnittestLite.optionalCordExtensionLite; + +import static com.google.protobuf.UnittestLite.repeatedInt32ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedInt64ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedUint32ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedUint64ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedSint32ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedSint64ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedFixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedFixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedSfixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedSfixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedFloatExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedDoubleExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedBoolExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedStringExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedBytesExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedGroupExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedNestedMessageExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedForeignMessageExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedImportMessageExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedNestedEnumExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedForeignEnumExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedImportEnumExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedStringPieceExtensionLite; +import static com.google.protobuf.UnittestLite.repeatedCordExtensionLite; + +import static com.google.protobuf.UnittestLite.OptionalGroup_extension_lite; +import static com.google.protobuf.UnittestLite.RepeatedGroup_extension_lite; + +import static com.google.protobuf.UnittestLite.packedInt32ExtensionLite; +import static com.google.protobuf.UnittestLite.packedInt64ExtensionLite; +import static com.google.protobuf.UnittestLite.packedUint32ExtensionLite; +import static com.google.protobuf.UnittestLite.packedUint64ExtensionLite; +import static com.google.protobuf.UnittestLite.packedSint32ExtensionLite; +import static com.google.protobuf.UnittestLite.packedSint64ExtensionLite; +import static com.google.protobuf.UnittestLite.packedFixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.packedFixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.packedSfixed32ExtensionLite; +import static com.google.protobuf.UnittestLite.packedSfixed64ExtensionLite; +import static com.google.protobuf.UnittestLite.packedFloatExtensionLite; +import static com.google.protobuf.UnittestLite.packedDoubleExtensionLite; +import static com.google.protobuf.UnittestLite.packedBoolExtensionLite; +import static com.google.protobuf.UnittestLite.packedEnumExtensionLite; + import protobuf_unittest.UnittestProto.TestAllExtensions; import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestPackedExtensions; @@ -132,6 +222,14 @@ import protobuf_unittest.UnittestProto.ForeignEnum; import com.google.protobuf.test.UnittestImport.ImportMessage; import com.google.protobuf.test.UnittestImport.ImportEnum; +import com.google.protobuf.UnittestLite.TestAllTypesLite; +import com.google.protobuf.UnittestLite.TestAllExtensionsLite; +import com.google.protobuf.UnittestLite.TestPackedExtensionsLite; +import com.google.protobuf.UnittestLite.ForeignMessageLite; +import com.google.protobuf.UnittestLite.ForeignEnumLite; +import com.google.protobuf.UnittestImportLite.ImportMessageLite; +import com.google.protobuf.UnittestImportLite.ImportEnumLite; + import junit.framework.Assert; import java.io.File; @@ -179,6 +277,12 @@ class TestUtil { return builder.build(); } + public static TestAllExtensionsLite getAllLiteExtensionsSet() { + TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder(); + setAllExtensions(builder); + return builder.build(); + } + public static TestPackedTypes getPackedSet() { TestPackedTypes.Builder builder = TestPackedTypes.newBuilder(); setPackedFields(builder); @@ -191,6 +295,13 @@ class TestUtil { return builder.build(); } + public static TestPackedExtensionsLite getLitePackedExtensionsSet() { + TestPackedExtensionsLite.Builder builder = + TestPackedExtensionsLite.newBuilder(); + setPackedExtensions(builder); + return builder.build(); + } + /** * Set every field of {@code message} to the values expected by * {@code assertAllFieldsSet()}. @@ -809,6 +920,90 @@ class TestUtil { Assert.assertEquals("525", message.getRepeatedCord(1)); } + /** + * Set every field of {@code message} to a unique value. + */ + public static void setPackedFields(TestPackedTypes.Builder message) { + message.addPackedInt32 (601); + message.addPackedInt64 (602); + message.addPackedUint32 (603); + message.addPackedUint64 (604); + message.addPackedSint32 (605); + message.addPackedSint64 (606); + message.addPackedFixed32 (607); + message.addPackedFixed64 (608); + message.addPackedSfixed32(609); + message.addPackedSfixed64(610); + message.addPackedFloat (611); + message.addPackedDouble (612); + message.addPackedBool (true); + message.addPackedEnum (ForeignEnum.FOREIGN_BAR); + // Add a second one of each field. + message.addPackedInt32 (701); + message.addPackedInt64 (702); + message.addPackedUint32 (703); + message.addPackedUint64 (704); + message.addPackedSint32 (705); + message.addPackedSint64 (706); + message.addPackedFixed32 (707); + message.addPackedFixed64 (708); + message.addPackedSfixed32(709); + message.addPackedSfixed64(710); + message.addPackedFloat (711); + message.addPackedDouble (712); + message.addPackedBool (false); + message.addPackedEnum (ForeignEnum.FOREIGN_BAZ); + } + + /** + * Assert (using {@code junit.framework.Assert}} that all fields of + * {@code message} are set to the values assigned by {@code setPackedFields}. + */ + public static void assertPackedFieldsSet(TestPackedTypes message) { + Assert.assertEquals(2, message.getPackedInt32Count ()); + Assert.assertEquals(2, message.getPackedInt64Count ()); + Assert.assertEquals(2, message.getPackedUint32Count ()); + Assert.assertEquals(2, message.getPackedUint64Count ()); + Assert.assertEquals(2, message.getPackedSint32Count ()); + Assert.assertEquals(2, message.getPackedSint64Count ()); + Assert.assertEquals(2, message.getPackedFixed32Count ()); + Assert.assertEquals(2, message.getPackedFixed64Count ()); + Assert.assertEquals(2, message.getPackedSfixed32Count()); + Assert.assertEquals(2, message.getPackedSfixed64Count()); + Assert.assertEquals(2, message.getPackedFloatCount ()); + Assert.assertEquals(2, message.getPackedDoubleCount ()); + Assert.assertEquals(2, message.getPackedBoolCount ()); + Assert.assertEquals(2, message.getPackedEnumCount ()); + Assert.assertEquals(601 , message.getPackedInt32 (0)); + Assert.assertEquals(602 , message.getPackedInt64 (0)); + Assert.assertEquals(603 , message.getPackedUint32 (0)); + Assert.assertEquals(604 , message.getPackedUint64 (0)); + Assert.assertEquals(605 , message.getPackedSint32 (0)); + Assert.assertEquals(606 , message.getPackedSint64 (0)); + Assert.assertEquals(607 , message.getPackedFixed32 (0)); + Assert.assertEquals(608 , message.getPackedFixed64 (0)); + Assert.assertEquals(609 , message.getPackedSfixed32(0)); + Assert.assertEquals(610 , message.getPackedSfixed64(0)); + Assert.assertEquals(611 , message.getPackedFloat (0), 0.0); + Assert.assertEquals(612 , message.getPackedDouble (0), 0.0); + Assert.assertEquals(true , message.getPackedBool (0)); + Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getPackedEnum(0)); + Assert.assertEquals(701 , message.getPackedInt32 (1)); + Assert.assertEquals(702 , message.getPackedInt64 (1)); + Assert.assertEquals(703 , message.getPackedUint32 (1)); + Assert.assertEquals(704 , message.getPackedUint64 (1)); + Assert.assertEquals(705 , message.getPackedSint32 (1)); + Assert.assertEquals(706 , message.getPackedSint64 (1)); + Assert.assertEquals(707 , message.getPackedFixed32 (1)); + Assert.assertEquals(708 , message.getPackedFixed64 (1)); + Assert.assertEquals(709 , message.getPackedSfixed32(1)); + Assert.assertEquals(710 , message.getPackedSfixed64(1)); + Assert.assertEquals(711 , message.getPackedFloat (1), 0.0); + Assert.assertEquals(712 , message.getPackedDouble (1), 0.0); + Assert.assertEquals(false, message.getPackedBool (1)); + Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1)); + } + // =================================================================== // Like above, but for extensions @@ -846,6 +1041,18 @@ class TestUtil { private static void assertEqualsExactType(ImportEnum a, ImportEnum b) { Assert.assertEquals(a, b); } + private static void assertEqualsExactType(TestAllTypesLite.NestedEnum a, + TestAllTypesLite.NestedEnum b) { + Assert.assertEquals(a, b); + } + private static void assertEqualsExactType(ForeignEnumLite a, + ForeignEnumLite b) { + Assert.assertEquals(a, b); + } + private static void assertEqualsExactType(ImportEnumLite a, + ImportEnumLite b) { + Assert.assertEquals(a, b); + } /** * Get an unmodifiable {@link ExtensionRegistry} containing all the @@ -857,12 +1064,23 @@ class TestUtil { return registry.getUnmodifiable(); } + public static ExtensionRegistryLite getExtensionRegistryLite() { + ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); + registerAllExtensionsLite(registry); + return registry.getUnmodifiable(); + } + /** - * Register all of {@code TestAllExtensions}' extensions with the + * Register all of {@code TestAllExtensions}'s extensions with the * given {@link ExtensionRegistry}. */ public static void registerAllExtensions(ExtensionRegistry registry) { UnittestProto.registerAllExtensions(registry); + registerAllExtensionsLite(registry); + } + + public static void registerAllExtensionsLite(ExtensionRegistryLite registry) { + UnittestLite.registerAllExtensions(registry); } /** @@ -1509,90 +1727,6 @@ class TestUtil { assertEqualsExactType("525", message.getExtension(repeatedCordExtension, 1)); } - /** - * Set every field of {@code message} to a unique value. - */ - public static void setPackedFields(TestPackedTypes.Builder message) { - message.addPackedInt32 (601); - message.addPackedInt64 (602); - message.addPackedUint32 (603); - message.addPackedUint64 (604); - message.addPackedSint32 (605); - message.addPackedSint64 (606); - message.addPackedFixed32 (607); - message.addPackedFixed64 (608); - message.addPackedSfixed32(609); - message.addPackedSfixed64(610); - message.addPackedFloat (611); - message.addPackedDouble (612); - message.addPackedBool (true); - message.addPackedEnum (ForeignEnum.FOREIGN_BAR); - // Add a second one of each field. - message.addPackedInt32 (701); - message.addPackedInt64 (702); - message.addPackedUint32 (703); - message.addPackedUint64 (704); - message.addPackedSint32 (705); - message.addPackedSint64 (706); - message.addPackedFixed32 (707); - message.addPackedFixed64 (708); - message.addPackedSfixed32(709); - message.addPackedSfixed64(710); - message.addPackedFloat (711); - message.addPackedDouble (712); - message.addPackedBool (false); - message.addPackedEnum (ForeignEnum.FOREIGN_BAZ); - } - - /** - * Assert (using {@code junit.framework.Assert}} that all fields of - * {@code message} are set to the values assigned by {@code setPackedFields}. - */ - public static void assertPackedFieldsSet(TestPackedTypes message) { - Assert.assertEquals(2, message.getPackedInt32Count ()); - Assert.assertEquals(2, message.getPackedInt64Count ()); - Assert.assertEquals(2, message.getPackedUint32Count ()); - Assert.assertEquals(2, message.getPackedUint64Count ()); - Assert.assertEquals(2, message.getPackedSint32Count ()); - Assert.assertEquals(2, message.getPackedSint64Count ()); - Assert.assertEquals(2, message.getPackedFixed32Count ()); - Assert.assertEquals(2, message.getPackedFixed64Count ()); - Assert.assertEquals(2, message.getPackedSfixed32Count()); - Assert.assertEquals(2, message.getPackedSfixed64Count()); - Assert.assertEquals(2, message.getPackedFloatCount ()); - Assert.assertEquals(2, message.getPackedDoubleCount ()); - Assert.assertEquals(2, message.getPackedBoolCount ()); - Assert.assertEquals(2, message.getPackedEnumCount ()); - Assert.assertEquals(601 , message.getPackedInt32 (0)); - Assert.assertEquals(602 , message.getPackedInt64 (0)); - Assert.assertEquals(603 , message.getPackedUint32 (0)); - Assert.assertEquals(604 , message.getPackedUint64 (0)); - Assert.assertEquals(605 , message.getPackedSint32 (0)); - Assert.assertEquals(606 , message.getPackedSint64 (0)); - Assert.assertEquals(607 , message.getPackedFixed32 (0)); - Assert.assertEquals(608 , message.getPackedFixed64 (0)); - Assert.assertEquals(609 , message.getPackedSfixed32(0)); - Assert.assertEquals(610 , message.getPackedSfixed64(0)); - Assert.assertEquals(611 , message.getPackedFloat (0), 0.0); - Assert.assertEquals(612 , message.getPackedDouble (0), 0.0); - Assert.assertEquals(true , message.getPackedBool (0)); - Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getPackedEnum(0)); - Assert.assertEquals(701 , message.getPackedInt32 (1)); - Assert.assertEquals(702 , message.getPackedInt64 (1)); - Assert.assertEquals(703 , message.getPackedUint32 (1)); - Assert.assertEquals(704 , message.getPackedUint64 (1)); - Assert.assertEquals(705 , message.getPackedSint32 (1)); - Assert.assertEquals(706 , message.getPackedSint64 (1)); - Assert.assertEquals(707 , message.getPackedFixed32 (1)); - Assert.assertEquals(708 , message.getPackedFixed64 (1)); - Assert.assertEquals(709 , message.getPackedSfixed32(1)); - Assert.assertEquals(710 , message.getPackedSfixed64(1)); - Assert.assertEquals(711 , message.getPackedFloat (1), 0.0); - Assert.assertEquals(712 , message.getPackedDouble (1), 0.0); - Assert.assertEquals(false, message.getPackedBool (1)); - Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1)); - } - public static void setPackedExtensions(TestPackedExtensions.Builder message) { message.addExtension(packedInt32Extension , 601); message.addExtension(packedInt64Extension , 602L); @@ -1672,8 +1806,733 @@ class TestUtil { message.getExtension(packedEnumExtension, 1)); } - // =================================================================== + // Lite extensions + + /** + * Set every field of {@code message} to the values expected by + * {@code assertAllExtensionsSet()}. + */ + public static void setAllExtensions(TestAllExtensionsLite.Builder message) { + message.setExtension(optionalInt32ExtensionLite , 101); + message.setExtension(optionalInt64ExtensionLite , 102L); + message.setExtension(optionalUint32ExtensionLite , 103); + message.setExtension(optionalUint64ExtensionLite , 104L); + message.setExtension(optionalSint32ExtensionLite , 105); + message.setExtension(optionalSint64ExtensionLite , 106L); + message.setExtension(optionalFixed32ExtensionLite , 107); + message.setExtension(optionalFixed64ExtensionLite , 108L); + message.setExtension(optionalSfixed32ExtensionLite, 109); + message.setExtension(optionalSfixed64ExtensionLite, 110L); + message.setExtension(optionalFloatExtensionLite , 111F); + message.setExtension(optionalDoubleExtensionLite , 112D); + message.setExtension(optionalBoolExtensionLite , true); + message.setExtension(optionalStringExtensionLite , "115"); + message.setExtension(optionalBytesExtensionLite , toBytes("116")); + + message.setExtension(optionalGroupExtensionLite, + OptionalGroup_extension_lite.newBuilder().setA(117).build()); + message.setExtension(optionalNestedMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build()); + message.setExtension(optionalForeignMessageExtensionLite, + ForeignMessageLite.newBuilder().setC(119).build()); + message.setExtension(optionalImportMessageExtensionLite, + ImportMessageLite.newBuilder().setD(120).build()); + + message.setExtension(optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ); + message.setExtension(optionalForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ); + message.setExtension(optionalImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ); + + message.setExtension(optionalStringPieceExtensionLite, "124"); + message.setExtension(optionalCordExtensionLite, "125"); + + // ----------------------------------------------------------------- + + message.addExtension(repeatedInt32ExtensionLite , 201); + message.addExtension(repeatedInt64ExtensionLite , 202L); + message.addExtension(repeatedUint32ExtensionLite , 203); + message.addExtension(repeatedUint64ExtensionLite , 204L); + message.addExtension(repeatedSint32ExtensionLite , 205); + message.addExtension(repeatedSint64ExtensionLite , 206L); + message.addExtension(repeatedFixed32ExtensionLite , 207); + message.addExtension(repeatedFixed64ExtensionLite , 208L); + message.addExtension(repeatedSfixed32ExtensionLite, 209); + message.addExtension(repeatedSfixed64ExtensionLite, 210L); + message.addExtension(repeatedFloatExtensionLite , 211F); + message.addExtension(repeatedDoubleExtensionLite , 212D); + message.addExtension(repeatedBoolExtensionLite , true); + message.addExtension(repeatedStringExtensionLite , "215"); + message.addExtension(repeatedBytesExtensionLite , toBytes("216")); + + message.addExtension(repeatedGroupExtensionLite, + RepeatedGroup_extension_lite.newBuilder().setA(217).build()); + message.addExtension(repeatedNestedMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build()); + message.addExtension(repeatedForeignMessageExtensionLite, + ForeignMessageLite.newBuilder().setC(219).build()); + message.addExtension(repeatedImportMessageExtensionLite, + ImportMessageLite.newBuilder().setD(220).build()); + + message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAR); + message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR); + message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAR); + + message.addExtension(repeatedStringPieceExtensionLite, "224"); + message.addExtension(repeatedCordExtensionLite, "225"); + + // Add a second one of each field. + message.addExtension(repeatedInt32ExtensionLite , 301); + message.addExtension(repeatedInt64ExtensionLite , 302L); + message.addExtension(repeatedUint32ExtensionLite , 303); + message.addExtension(repeatedUint64ExtensionLite , 304L); + message.addExtension(repeatedSint32ExtensionLite , 305); + message.addExtension(repeatedSint64ExtensionLite , 306L); + message.addExtension(repeatedFixed32ExtensionLite , 307); + message.addExtension(repeatedFixed64ExtensionLite , 308L); + message.addExtension(repeatedSfixed32ExtensionLite, 309); + message.addExtension(repeatedSfixed64ExtensionLite, 310L); + message.addExtension(repeatedFloatExtensionLite , 311F); + message.addExtension(repeatedDoubleExtensionLite , 312D); + message.addExtension(repeatedBoolExtensionLite , false); + message.addExtension(repeatedStringExtensionLite , "315"); + message.addExtension(repeatedBytesExtensionLite , toBytes("316")); + + message.addExtension(repeatedGroupExtensionLite, + RepeatedGroup_extension_lite.newBuilder().setA(317).build()); + message.addExtension(repeatedNestedMessageExtensionLite, + TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build()); + message.addExtension(repeatedForeignMessageExtensionLite, + ForeignMessageLite.newBuilder().setC(319).build()); + message.addExtension(repeatedImportMessageExtensionLite, + ImportMessageLite.newBuilder().setD(320).build()); + + message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ); + message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ); + message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ); + + message.addExtension(repeatedStringPieceExtensionLite, "324"); + message.addExtension(repeatedCordExtensionLite, "325"); + + // ----------------------------------------------------------------- + + message.setExtension(defaultInt32ExtensionLite , 401); + message.setExtension(defaultInt64ExtensionLite , 402L); + message.setExtension(defaultUint32ExtensionLite , 403); + message.setExtension(defaultUint64ExtensionLite , 404L); + message.setExtension(defaultSint32ExtensionLite , 405); + message.setExtension(defaultSint64ExtensionLite , 406L); + message.setExtension(defaultFixed32ExtensionLite , 407); + message.setExtension(defaultFixed64ExtensionLite , 408L); + message.setExtension(defaultSfixed32ExtensionLite, 409); + message.setExtension(defaultSfixed64ExtensionLite, 410L); + message.setExtension(defaultFloatExtensionLite , 411F); + message.setExtension(defaultDoubleExtensionLite , 412D); + message.setExtension(defaultBoolExtensionLite , false); + message.setExtension(defaultStringExtensionLite , "415"); + message.setExtension(defaultBytesExtensionLite , toBytes("416")); + + message.setExtension(defaultNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.FOO); + message.setExtension(defaultForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_FOO); + message.setExtension(defaultImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_FOO); + + message.setExtension(defaultStringPieceExtensionLite, "424"); + message.setExtension(defaultCordExtensionLite, "425"); + } + + // ------------------------------------------------------------------- + + /** + * Modify the repeated extensions of {@code message} to contain the values + * expected by {@code assertRepeatedExtensionsModified()}. + */ + public static void modifyRepeatedExtensions( + TestAllExtensionsLite.Builder message) { + message.setExtension(repeatedInt32ExtensionLite , 1, 501); + message.setExtension(repeatedInt64ExtensionLite , 1, 502L); + message.setExtension(repeatedUint32ExtensionLite , 1, 503); + message.setExtension(repeatedUint64ExtensionLite , 1, 504L); + message.setExtension(repeatedSint32ExtensionLite , 1, 505); + message.setExtension(repeatedSint64ExtensionLite , 1, 506L); + message.setExtension(repeatedFixed32ExtensionLite , 1, 507); + message.setExtension(repeatedFixed64ExtensionLite , 1, 508L); + message.setExtension(repeatedSfixed32ExtensionLite, 1, 509); + message.setExtension(repeatedSfixed64ExtensionLite, 1, 510L); + message.setExtension(repeatedFloatExtensionLite , 1, 511F); + message.setExtension(repeatedDoubleExtensionLite , 1, 512D); + message.setExtension(repeatedBoolExtensionLite , 1, true); + message.setExtension(repeatedStringExtensionLite , 1, "515"); + message.setExtension(repeatedBytesExtensionLite , 1, toBytes("516")); + + message.setExtension(repeatedGroupExtensionLite, 1, + RepeatedGroup_extension_lite.newBuilder().setA(517).build()); + message.setExtension(repeatedNestedMessageExtensionLite, 1, + TestAllTypesLite.NestedMessage.newBuilder().setBb(518).build()); + message.setExtension(repeatedForeignMessageExtensionLite, 1, + ForeignMessageLite.newBuilder().setC(519).build()); + message.setExtension(repeatedImportMessageExtensionLite, 1, + ImportMessageLite.newBuilder().setD(520).build()); + + message.setExtension(repeatedNestedEnumExtensionLite , 1, TestAllTypesLite.NestedEnum.FOO); + message.setExtension(repeatedForeignEnumExtensionLite, 1, ForeignEnumLite.FOREIGN_LITE_FOO); + message.setExtension(repeatedImportEnumExtensionLite , 1, ImportEnumLite.IMPORT_LITE_FOO); + + message.setExtension(repeatedStringPieceExtensionLite, 1, "524"); + message.setExtension(repeatedCordExtensionLite, 1, "525"); + } + + // ------------------------------------------------------------------- + + /** + * Assert (using {@code junit.framework.Assert}} that all extensions of + * {@code message} are set to the values assigned by {@code setAllExtensions}. + */ + public static void assertAllExtensionsSet(TestAllExtensionsLite message) { + Assert.assertTrue(message.hasExtension(optionalInt32ExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalInt64ExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalUint32ExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalUint64ExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalSint32ExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalSint64ExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalFixed32ExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalFixed64ExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalSfixed32ExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalSfixed64ExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalFloatExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalDoubleExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalBoolExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalStringExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalBytesExtensionLite )); + + Assert.assertTrue(message.hasExtension(optionalGroupExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalNestedMessageExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalForeignMessageExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalImportMessageExtensionLite )); + + Assert.assertTrue(message.getExtension(optionalGroupExtensionLite ).hasA()); + Assert.assertTrue(message.getExtension(optionalNestedMessageExtensionLite ).hasBb()); + Assert.assertTrue(message.getExtension(optionalForeignMessageExtensionLite).hasC()); + Assert.assertTrue(message.getExtension(optionalImportMessageExtensionLite ).hasD()); + + Assert.assertTrue(message.hasExtension(optionalNestedEnumExtensionLite )); + Assert.assertTrue(message.hasExtension(optionalForeignEnumExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalImportEnumExtensionLite )); + + Assert.assertTrue(message.hasExtension(optionalStringPieceExtensionLite)); + Assert.assertTrue(message.hasExtension(optionalCordExtensionLite)); + + assertEqualsExactType(101 , message.getExtension(optionalInt32ExtensionLite )); + assertEqualsExactType(102L , message.getExtension(optionalInt64ExtensionLite )); + assertEqualsExactType(103 , message.getExtension(optionalUint32ExtensionLite )); + assertEqualsExactType(104L , message.getExtension(optionalUint64ExtensionLite )); + assertEqualsExactType(105 , message.getExtension(optionalSint32ExtensionLite )); + assertEqualsExactType(106L , message.getExtension(optionalSint64ExtensionLite )); + assertEqualsExactType(107 , message.getExtension(optionalFixed32ExtensionLite )); + assertEqualsExactType(108L , message.getExtension(optionalFixed64ExtensionLite )); + assertEqualsExactType(109 , message.getExtension(optionalSfixed32ExtensionLite)); + assertEqualsExactType(110L , message.getExtension(optionalSfixed64ExtensionLite)); + assertEqualsExactType(111F , message.getExtension(optionalFloatExtensionLite )); + assertEqualsExactType(112D , message.getExtension(optionalDoubleExtensionLite )); + assertEqualsExactType(true , message.getExtension(optionalBoolExtensionLite )); + assertEqualsExactType("115", message.getExtension(optionalStringExtensionLite )); + assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtensionLite)); + + assertEqualsExactType(117, message.getExtension(optionalGroupExtensionLite ).getA()); + assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtensionLite ).getBb()); + assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtensionLite).getC()); + assertEqualsExactType(120, message.getExtension(optionalImportMessageExtensionLite ).getD()); + + assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ, + message.getExtension(optionalNestedEnumExtensionLite)); + assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ, + message.getExtension(optionalForeignEnumExtensionLite)); + assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAZ, + message.getExtension(optionalImportEnumExtensionLite)); + + assertEqualsExactType("124", message.getExtension(optionalStringPieceExtensionLite)); + assertEqualsExactType("125", message.getExtension(optionalCordExtensionLite)); + + // ----------------------------------------------------------------- + + Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite )); + + Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite )); + + Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtensionLite)); + + assertEqualsExactType(201 , message.getExtension(repeatedInt32ExtensionLite , 0)); + assertEqualsExactType(202L , message.getExtension(repeatedInt64ExtensionLite , 0)); + assertEqualsExactType(203 , message.getExtension(repeatedUint32ExtensionLite , 0)); + assertEqualsExactType(204L , message.getExtension(repeatedUint64ExtensionLite , 0)); + assertEqualsExactType(205 , message.getExtension(repeatedSint32ExtensionLite , 0)); + assertEqualsExactType(206L , message.getExtension(repeatedSint64ExtensionLite , 0)); + assertEqualsExactType(207 , message.getExtension(repeatedFixed32ExtensionLite , 0)); + assertEqualsExactType(208L , message.getExtension(repeatedFixed64ExtensionLite , 0)); + assertEqualsExactType(209 , message.getExtension(repeatedSfixed32ExtensionLite, 0)); + assertEqualsExactType(210L , message.getExtension(repeatedSfixed64ExtensionLite, 0)); + assertEqualsExactType(211F , message.getExtension(repeatedFloatExtensionLite , 0)); + assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtensionLite , 0)); + assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 0)); + assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite , 0)); + assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtensionLite, 0)); + + assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite ,0).getA()); + assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb()); + assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC()); + assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD()); + + assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR, + message.getExtension(repeatedNestedEnumExtensionLite, 0)); + assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR, + message.getExtension(repeatedForeignEnumExtensionLite, 0)); + assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR, + message.getExtension(repeatedImportEnumExtensionLite, 0)); + + assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtensionLite, 0)); + assertEqualsExactType("225", message.getExtension(repeatedCordExtensionLite, 0)); + + assertEqualsExactType(301 , message.getExtension(repeatedInt32ExtensionLite , 1)); + assertEqualsExactType(302L , message.getExtension(repeatedInt64ExtensionLite , 1)); + assertEqualsExactType(303 , message.getExtension(repeatedUint32ExtensionLite , 1)); + assertEqualsExactType(304L , message.getExtension(repeatedUint64ExtensionLite , 1)); + assertEqualsExactType(305 , message.getExtension(repeatedSint32ExtensionLite , 1)); + assertEqualsExactType(306L , message.getExtension(repeatedSint64ExtensionLite , 1)); + assertEqualsExactType(307 , message.getExtension(repeatedFixed32ExtensionLite , 1)); + assertEqualsExactType(308L , message.getExtension(repeatedFixed64ExtensionLite , 1)); + assertEqualsExactType(309 , message.getExtension(repeatedSfixed32ExtensionLite, 1)); + assertEqualsExactType(310L , message.getExtension(repeatedSfixed64ExtensionLite, 1)); + assertEqualsExactType(311F , message.getExtension(repeatedFloatExtensionLite , 1)); + assertEqualsExactType(312D , message.getExtension(repeatedDoubleExtensionLite , 1)); + assertEqualsExactType(false, message.getExtension(repeatedBoolExtensionLite , 1)); + assertEqualsExactType("315", message.getExtension(repeatedStringExtensionLite , 1)); + assertEqualsExactType(toBytes("316"), message.getExtension(repeatedBytesExtensionLite, 1)); + + assertEqualsExactType(317, message.getExtension(repeatedGroupExtensionLite ,1).getA()); + assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb()); + assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtensionLite,1).getC()); + assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtensionLite ,1).getD()); + + assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ, + message.getExtension(repeatedNestedEnumExtensionLite, 1)); + assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ, + message.getExtension(repeatedForeignEnumExtensionLite, 1)); + assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAZ, + message.getExtension(repeatedImportEnumExtensionLite, 1)); + + assertEqualsExactType("324", message.getExtension(repeatedStringPieceExtensionLite, 1)); + assertEqualsExactType("325", message.getExtension(repeatedCordExtensionLite, 1)); + + // ----------------------------------------------------------------- + + Assert.assertTrue(message.hasExtension(defaultInt32ExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultInt64ExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultUint32ExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultUint64ExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultSint32ExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultSint64ExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultFixed32ExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultFixed64ExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultSfixed32ExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultSfixed64ExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultFloatExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultDoubleExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultBoolExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultStringExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultBytesExtensionLite )); + + Assert.assertTrue(message.hasExtension(defaultNestedEnumExtensionLite )); + Assert.assertTrue(message.hasExtension(defaultForeignEnumExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultImportEnumExtensionLite )); + + Assert.assertTrue(message.hasExtension(defaultStringPieceExtensionLite)); + Assert.assertTrue(message.hasExtension(defaultCordExtensionLite)); + + assertEqualsExactType(401 , message.getExtension(defaultInt32ExtensionLite )); + assertEqualsExactType(402L , message.getExtension(defaultInt64ExtensionLite )); + assertEqualsExactType(403 , message.getExtension(defaultUint32ExtensionLite )); + assertEqualsExactType(404L , message.getExtension(defaultUint64ExtensionLite )); + assertEqualsExactType(405 , message.getExtension(defaultSint32ExtensionLite )); + assertEqualsExactType(406L , message.getExtension(defaultSint64ExtensionLite )); + assertEqualsExactType(407 , message.getExtension(defaultFixed32ExtensionLite )); + assertEqualsExactType(408L , message.getExtension(defaultFixed64ExtensionLite )); + assertEqualsExactType(409 , message.getExtension(defaultSfixed32ExtensionLite)); + assertEqualsExactType(410L , message.getExtension(defaultSfixed64ExtensionLite)); + assertEqualsExactType(411F , message.getExtension(defaultFloatExtensionLite )); + assertEqualsExactType(412D , message.getExtension(defaultDoubleExtensionLite )); + assertEqualsExactType(false, message.getExtension(defaultBoolExtensionLite )); + assertEqualsExactType("415", message.getExtension(defaultStringExtensionLite )); + assertEqualsExactType(toBytes("416"), message.getExtension(defaultBytesExtensionLite)); + + assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO, + message.getExtension(defaultNestedEnumExtensionLite )); + assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO, + message.getExtension(defaultForeignEnumExtensionLite)); + assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO, + message.getExtension(defaultImportEnumExtensionLite)); + + assertEqualsExactType("424", message.getExtension(defaultStringPieceExtensionLite)); + assertEqualsExactType("425", message.getExtension(defaultCordExtensionLite)); + } + + // ------------------------------------------------------------------- + + /** + * Assert (using {@code junit.framework.Assert}} that all extensions of + * {@code message} are cleared, and that getting the extensions returns their + * default values. + */ + public static void assertExtensionsClear(TestAllExtensionsLite message) { + // hasBlah() should initially be false for all optional fields. + Assert.assertFalse(message.hasExtension(optionalInt32ExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalInt64ExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalUint32ExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalUint64ExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalSint32ExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalSint64ExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalFixed32ExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalFixed64ExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalSfixed32ExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalSfixed64ExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalFloatExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalDoubleExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalBoolExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalStringExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalBytesExtensionLite )); + + Assert.assertFalse(message.hasExtension(optionalGroupExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalNestedMessageExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalForeignMessageExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalImportMessageExtensionLite )); + + Assert.assertFalse(message.hasExtension(optionalNestedEnumExtensionLite )); + Assert.assertFalse(message.hasExtension(optionalForeignEnumExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalImportEnumExtensionLite )); + + Assert.assertFalse(message.hasExtension(optionalStringPieceExtensionLite)); + Assert.assertFalse(message.hasExtension(optionalCordExtensionLite)); + + // Optional fields without defaults are set to zero or something like it. + assertEqualsExactType(0 , message.getExtension(optionalInt32ExtensionLite )); + assertEqualsExactType(0L , message.getExtension(optionalInt64ExtensionLite )); + assertEqualsExactType(0 , message.getExtension(optionalUint32ExtensionLite )); + assertEqualsExactType(0L , message.getExtension(optionalUint64ExtensionLite )); + assertEqualsExactType(0 , message.getExtension(optionalSint32ExtensionLite )); + assertEqualsExactType(0L , message.getExtension(optionalSint64ExtensionLite )); + assertEqualsExactType(0 , message.getExtension(optionalFixed32ExtensionLite )); + assertEqualsExactType(0L , message.getExtension(optionalFixed64ExtensionLite )); + assertEqualsExactType(0 , message.getExtension(optionalSfixed32ExtensionLite)); + assertEqualsExactType(0L , message.getExtension(optionalSfixed64ExtensionLite)); + assertEqualsExactType(0F , message.getExtension(optionalFloatExtensionLite )); + assertEqualsExactType(0D , message.getExtension(optionalDoubleExtensionLite )); + assertEqualsExactType(false, message.getExtension(optionalBoolExtensionLite )); + assertEqualsExactType("" , message.getExtension(optionalStringExtensionLite )); + assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtensionLite)); + + // Embedded messages should also be clear. + Assert.assertFalse(message.getExtension(optionalGroupExtensionLite ).hasA()); + Assert.assertFalse(message.getExtension(optionalNestedMessageExtensionLite ).hasBb()); + Assert.assertFalse(message.getExtension(optionalForeignMessageExtensionLite).hasC()); + Assert.assertFalse(message.getExtension(optionalImportMessageExtensionLite ).hasD()); + + assertEqualsExactType(0, message.getExtension(optionalGroupExtensionLite ).getA()); + assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtensionLite ).getBb()); + assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtensionLite).getC()); + assertEqualsExactType(0, message.getExtension(optionalImportMessageExtensionLite ).getD()); + + // Enums without defaults are set to the first value in the enum. + assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO, + message.getExtension(optionalNestedEnumExtensionLite )); + assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO, + message.getExtension(optionalForeignEnumExtensionLite)); + assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO, + message.getExtension(optionalImportEnumExtensionLite)); + + assertEqualsExactType("", message.getExtension(optionalStringPieceExtensionLite)); + assertEqualsExactType("", message.getExtension(optionalCordExtensionLite)); + + // Repeated fields are empty. + Assert.assertEquals(0, message.getExtensionCount(repeatedInt32ExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedInt64ExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedUint32ExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedUint64ExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedSint32ExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedSint64ExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32ExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64ExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed32ExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed64ExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtensionLite )); + + Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtensionLite )); + Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtensionLite )); + + Assert.assertEquals(0, message.getExtensionCount(repeatedStringPieceExtensionLite)); + Assert.assertEquals(0, message.getExtensionCount(repeatedCordExtensionLite)); + + // hasBlah() should also be false for all default fields. + Assert.assertFalse(message.hasExtension(defaultInt32ExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultInt64ExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultUint32ExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultUint64ExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultSint32ExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultSint64ExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultFixed32ExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultFixed64ExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultSfixed32ExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultSfixed64ExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultFloatExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultDoubleExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultBoolExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultStringExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultBytesExtensionLite )); + + Assert.assertFalse(message.hasExtension(defaultNestedEnumExtensionLite )); + Assert.assertFalse(message.hasExtension(defaultForeignEnumExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultImportEnumExtensionLite )); + + Assert.assertFalse(message.hasExtension(defaultStringPieceExtensionLite)); + Assert.assertFalse(message.hasExtension(defaultCordExtensionLite)); + + // Fields with defaults have their default values (duh). + assertEqualsExactType( 41 , message.getExtension(defaultInt32ExtensionLite )); + assertEqualsExactType( 42L , message.getExtension(defaultInt64ExtensionLite )); + assertEqualsExactType( 43 , message.getExtension(defaultUint32ExtensionLite )); + assertEqualsExactType( 44L , message.getExtension(defaultUint64ExtensionLite )); + assertEqualsExactType(-45 , message.getExtension(defaultSint32ExtensionLite )); + assertEqualsExactType( 46L , message.getExtension(defaultSint64ExtensionLite )); + assertEqualsExactType( 47 , message.getExtension(defaultFixed32ExtensionLite )); + assertEqualsExactType( 48L , message.getExtension(defaultFixed64ExtensionLite )); + assertEqualsExactType( 49 , message.getExtension(defaultSfixed32ExtensionLite)); + assertEqualsExactType(-50L , message.getExtension(defaultSfixed64ExtensionLite)); + assertEqualsExactType( 51.5F , message.getExtension(defaultFloatExtensionLite )); + assertEqualsExactType( 52e3D , message.getExtension(defaultDoubleExtensionLite )); + assertEqualsExactType(true , message.getExtension(defaultBoolExtensionLite )); + assertEqualsExactType("hello", message.getExtension(defaultStringExtensionLite )); + assertEqualsExactType(toBytes("world"), message.getExtension(defaultBytesExtensionLite)); + + assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR, + message.getExtension(defaultNestedEnumExtensionLite )); + assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR, + message.getExtension(defaultForeignEnumExtensionLite)); + assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR, + message.getExtension(defaultImportEnumExtensionLite)); + + assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtensionLite)); + assertEqualsExactType("123", message.getExtension(defaultCordExtensionLite)); + } + + // ------------------------------------------------------------------- + + /** + * Assert (using {@code junit.framework.Assert}} that all extensions of + * {@code message} are set to the values assigned by {@code setAllExtensions} + * followed by {@code modifyRepeatedExtensions}. + */ + public static void assertRepeatedExtensionsModified( + TestAllExtensionsLite message) { + // ModifyRepeatedFields only sets the second repeated element of each + // field. In addition to verifying this, we also verify that the first + // element and size were *not* modified. + Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite )); + + Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite )); + + Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtensionLite)); + + assertEqualsExactType(201 , message.getExtension(repeatedInt32ExtensionLite , 0)); + assertEqualsExactType(202L , message.getExtension(repeatedInt64ExtensionLite , 0)); + assertEqualsExactType(203 , message.getExtension(repeatedUint32ExtensionLite , 0)); + assertEqualsExactType(204L , message.getExtension(repeatedUint64ExtensionLite , 0)); + assertEqualsExactType(205 , message.getExtension(repeatedSint32ExtensionLite , 0)); + assertEqualsExactType(206L , message.getExtension(repeatedSint64ExtensionLite , 0)); + assertEqualsExactType(207 , message.getExtension(repeatedFixed32ExtensionLite , 0)); + assertEqualsExactType(208L , message.getExtension(repeatedFixed64ExtensionLite , 0)); + assertEqualsExactType(209 , message.getExtension(repeatedSfixed32ExtensionLite, 0)); + assertEqualsExactType(210L , message.getExtension(repeatedSfixed64ExtensionLite, 0)); + assertEqualsExactType(211F , message.getExtension(repeatedFloatExtensionLite , 0)); + assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtensionLite , 0)); + assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 0)); + assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite , 0)); + assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtensionLite, 0)); + + assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite ,0).getA()); + assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb()); + assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC()); + assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD()); + + assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR, + message.getExtension(repeatedNestedEnumExtensionLite, 0)); + assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR, + message.getExtension(repeatedForeignEnumExtensionLite, 0)); + assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR, + message.getExtension(repeatedImportEnumExtensionLite, 0)); + + assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtensionLite, 0)); + assertEqualsExactType("225", message.getExtension(repeatedCordExtensionLite, 0)); + + // Actually verify the second (modified) elements now. + assertEqualsExactType(501 , message.getExtension(repeatedInt32ExtensionLite , 1)); + assertEqualsExactType(502L , message.getExtension(repeatedInt64ExtensionLite , 1)); + assertEqualsExactType(503 , message.getExtension(repeatedUint32ExtensionLite , 1)); + assertEqualsExactType(504L , message.getExtension(repeatedUint64ExtensionLite , 1)); + assertEqualsExactType(505 , message.getExtension(repeatedSint32ExtensionLite , 1)); + assertEqualsExactType(506L , message.getExtension(repeatedSint64ExtensionLite , 1)); + assertEqualsExactType(507 , message.getExtension(repeatedFixed32ExtensionLite , 1)); + assertEqualsExactType(508L , message.getExtension(repeatedFixed64ExtensionLite , 1)); + assertEqualsExactType(509 , message.getExtension(repeatedSfixed32ExtensionLite, 1)); + assertEqualsExactType(510L , message.getExtension(repeatedSfixed64ExtensionLite, 1)); + assertEqualsExactType(511F , message.getExtension(repeatedFloatExtensionLite , 1)); + assertEqualsExactType(512D , message.getExtension(repeatedDoubleExtensionLite , 1)); + assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 1)); + assertEqualsExactType("515", message.getExtension(repeatedStringExtensionLite , 1)); + assertEqualsExactType(toBytes("516"), message.getExtension(repeatedBytesExtensionLite, 1)); + + assertEqualsExactType(517, message.getExtension(repeatedGroupExtensionLite ,1).getA()); + assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb()); + assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtensionLite,1).getC()); + assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtensionLite ,1).getD()); + + assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO, + message.getExtension(repeatedNestedEnumExtensionLite, 1)); + assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO, + message.getExtension(repeatedForeignEnumExtensionLite, 1)); + assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO, + message.getExtension(repeatedImportEnumExtensionLite, 1)); + + assertEqualsExactType("524", message.getExtension(repeatedStringPieceExtensionLite, 1)); + assertEqualsExactType("525", message.getExtension(repeatedCordExtensionLite, 1)); + } + + public static void setPackedExtensions(TestPackedExtensionsLite.Builder message) { + message.addExtension(packedInt32ExtensionLite , 601); + message.addExtension(packedInt64ExtensionLite , 602L); + message.addExtension(packedUint32ExtensionLite , 603); + message.addExtension(packedUint64ExtensionLite , 604L); + message.addExtension(packedSint32ExtensionLite , 605); + message.addExtension(packedSint64ExtensionLite , 606L); + message.addExtension(packedFixed32ExtensionLite , 607); + message.addExtension(packedFixed64ExtensionLite , 608L); + message.addExtension(packedSfixed32ExtensionLite, 609); + message.addExtension(packedSfixed64ExtensionLite, 610L); + message.addExtension(packedFloatExtensionLite , 611F); + message.addExtension(packedDoubleExtensionLite , 612D); + message.addExtension(packedBoolExtensionLite , true); + message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR); + // Add a second one of each field. + message.addExtension(packedInt32ExtensionLite , 701); + message.addExtension(packedInt64ExtensionLite , 702L); + message.addExtension(packedUint32ExtensionLite , 703); + message.addExtension(packedUint64ExtensionLite , 704L); + message.addExtension(packedSint32ExtensionLite , 705); + message.addExtension(packedSint64ExtensionLite , 706L); + message.addExtension(packedFixed32ExtensionLite , 707); + message.addExtension(packedFixed64ExtensionLite , 708L); + message.addExtension(packedSfixed32ExtensionLite, 709); + message.addExtension(packedSfixed64ExtensionLite, 710L); + message.addExtension(packedFloatExtensionLite , 711F); + message.addExtension(packedDoubleExtensionLite , 712D); + message.addExtension(packedBoolExtensionLite , false); + message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ); + } + + public static void assertPackedExtensionsSet(TestPackedExtensionsLite message) { + Assert.assertEquals(2, message.getExtensionCount(packedInt32ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(packedInt64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(packedUint32ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(packedUint64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(packedSint32ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(packedSint64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(packedFixed32ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(packedFixed64ExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(packedSfixed32ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(packedSfixed64ExtensionLite)); + Assert.assertEquals(2, message.getExtensionCount(packedFloatExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(packedBoolExtensionLite )); + Assert.assertEquals(2, message.getExtensionCount(packedEnumExtensionLite)); + assertEqualsExactType(601 , message.getExtension(packedInt32ExtensionLite , 0)); + assertEqualsExactType(602L , message.getExtension(packedInt64ExtensionLite , 0)); + assertEqualsExactType(603 , message.getExtension(packedUint32ExtensionLite , 0)); + assertEqualsExactType(604L , message.getExtension(packedUint64ExtensionLite , 0)); + assertEqualsExactType(605 , message.getExtension(packedSint32ExtensionLite , 0)); + assertEqualsExactType(606L , message.getExtension(packedSint64ExtensionLite , 0)); + assertEqualsExactType(607 , message.getExtension(packedFixed32ExtensionLite , 0)); + assertEqualsExactType(608L , message.getExtension(packedFixed64ExtensionLite , 0)); + assertEqualsExactType(609 , message.getExtension(packedSfixed32ExtensionLite, 0)); + assertEqualsExactType(610L , message.getExtension(packedSfixed64ExtensionLite, 0)); + assertEqualsExactType(611F , message.getExtension(packedFloatExtensionLite , 0)); + assertEqualsExactType(612D , message.getExtension(packedDoubleExtensionLite , 0)); + assertEqualsExactType(true , message.getExtension(packedBoolExtensionLite , 0)); + assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR, + message.getExtension(packedEnumExtensionLite, 0)); + assertEqualsExactType(701 , message.getExtension(packedInt32ExtensionLite , 1)); + assertEqualsExactType(702L , message.getExtension(packedInt64ExtensionLite , 1)); + assertEqualsExactType(703 , message.getExtension(packedUint32ExtensionLite , 1)); + assertEqualsExactType(704L , message.getExtension(packedUint64ExtensionLite , 1)); + assertEqualsExactType(705 , message.getExtension(packedSint32ExtensionLite , 1)); + assertEqualsExactType(706L , message.getExtension(packedSint64ExtensionLite , 1)); + assertEqualsExactType(707 , message.getExtension(packedFixed32ExtensionLite , 1)); + assertEqualsExactType(708L , message.getExtension(packedFixed64ExtensionLite , 1)); + assertEqualsExactType(709 , message.getExtension(packedSfixed32ExtensionLite, 1)); + assertEqualsExactType(710L , message.getExtension(packedSfixed64ExtensionLite, 1)); + assertEqualsExactType(711F , message.getExtension(packedFloatExtensionLite , 1)); + assertEqualsExactType(712D , message.getExtension(packedDoubleExtensionLite , 1)); + assertEqualsExactType(false, message.getExtension(packedBoolExtensionLite , 1)); + assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ, + message.getExtension(packedEnumExtensionLite, 1)); + } + + // ================================================================= /** * Performs the same things that the methods of {@code TestUtil} do, but diff --git a/java/src/test/java/com/google/protobuf/TextFormatTest.java b/java/src/test/java/com/google/protobuf/TextFormatTest.java index ec4910a3..1d73165e 100644 --- a/java/src/test/java/com/google/protobuf/TextFormatTest.java +++ b/java/src/test/java/com/google/protobuf/TextFormatTest.java @@ -30,9 +30,12 @@ package com.google.protobuf; +import com.google.protobuf.Descriptors.FieldDescriptor; +import protobuf_unittest.UnittestProto.OneString; import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestAllExtensions; import protobuf_unittest.UnittestProto.TestEmptyMessage; +import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage; import protobuf_unittest.UnittestMset.TestMessageSet; import protobuf_unittest.UnittestMset.TestMessageSetExtension1; import protobuf_unittest.UnittestMset.TestMessageSetExtension2; @@ -173,6 +176,22 @@ public class TextFormatTest extends TestCase { TextFormat.printToString(message)); } + public void testPrintField() throws Exception { + final FieldDescriptor dataField = + OneString.getDescriptor().findFieldByName("data"); + assertEquals( + "data: \"test data\"\n", + TextFormat.printFieldToString(dataField, "test data")); + + final FieldDescriptor optionalField = + TestAllTypes.getDescriptor().findFieldByName("optional_nested_message"); + final Object value = NestedMessage.newBuilder().setBb(42).build(); + + assertEquals( + "optional_nested_message {\n bb: 42\n}\n", + TextFormat.printFieldToString(optionalField, value)); + } + /** * Helper to construct a ByteString from a String containing only 8-bit * characters. The characters are converted directly to bytes, *not* @@ -450,21 +469,21 @@ public class TextFormatTest extends TestCase { try { TextFormat.unescapeText("\\x"); fail("Should have thrown an exception."); - } catch (TextFormat.InvalidEscapeSequence e) { + } catch (TextFormat.InvalidEscapeSequenceException e) { // success } try { TextFormat.unescapeText("\\z"); fail("Should have thrown an exception."); - } catch (TextFormat.InvalidEscapeSequence e) { + } catch (TextFormat.InvalidEscapeSequenceException e) { // success } try { TextFormat.unescapeText("\\"); fail("Should have thrown an exception."); - } catch (TextFormat.InvalidEscapeSequence e) { + } catch (TextFormat.InvalidEscapeSequenceException e) { // success } } diff --git a/java/src/test/java/com/google/protobuf/WireFormatTest.java b/java/src/test/java/com/google/protobuf/WireFormatTest.java index 4afefdb6..bd1c6db1 100644 --- a/java/src/test/java/com/google/protobuf/WireFormatTest.java +++ b/java/src/test/java/com/google/protobuf/WireFormatTest.java @@ -45,6 +45,8 @@ import protobuf_unittest.UnittestMset.TestMessageSet; import protobuf_unittest.UnittestMset.RawMessageSet; import protobuf_unittest.UnittestMset.TestMessageSetExtension1; import protobuf_unittest.UnittestMset.TestMessageSetExtension2; +import com.google.protobuf.UnittestLite.TestAllExtensionsLite; +import com.google.protobuf.UnittestLite.TestPackedExtensionsLite; /** * Tests related to parsing and serialization. @@ -100,6 +102,32 @@ public class WireFormatTest extends TestCase { assertEquals(rawBytes, rawBytes2); } + public void testSerializeExtensionsLite() throws Exception { + // TestAllTypes and TestAllExtensions should have compatible wire formats, + // so if we serialize a TestAllExtensions then parse it as TestAllTypes + // it should work. + + TestAllExtensionsLite message = TestUtil.getAllLiteExtensionsSet(); + ByteString rawBytes = message.toByteString(); + assertEquals(rawBytes.size(), message.getSerializedSize()); + + TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes); + + TestUtil.assertAllFieldsSet(message2); + } + + public void testSerializePackedExtensionsLite() throws Exception { + // TestPackedTypes and TestPackedExtensions should have compatible wire + // formats; check that they serialize to the same string. + TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet(); + ByteString rawBytes = message.toByteString(); + + TestPackedTypes message2 = TestUtil.getPackedSet(); + ByteString rawBytes2 = message2.toByteString(); + + assertEquals(rawBytes, rawBytes2); + } + public void testParseExtensions() throws Exception { // TestAllTypes and TestAllExtensions should have compatible wire formats, // so if we serialize a TestAllTypes then parse it as TestAllExtensions @@ -129,6 +157,43 @@ public class WireFormatTest extends TestCase { TestUtil.assertPackedExtensionsSet(message2); } + public void testParseExtensionsLite() throws Exception { + // TestAllTypes and TestAllExtensions should have compatible wire formats, + // so if we serialize a TestAllTypes then parse it as TestAllExtensions + // it should work. + + TestAllTypes message = TestUtil.getAllSet(); + ByteString rawBytes = message.toByteString(); + + ExtensionRegistryLite registry_lite = TestUtil.getExtensionRegistryLite(); + + TestAllExtensionsLite message2 = + TestAllExtensionsLite.parseFrom(rawBytes, registry_lite); + + TestUtil.assertAllExtensionsSet(message2); + + // Try again using a full extension registry. + ExtensionRegistry registry = TestUtil.getExtensionRegistry(); + + TestAllExtensionsLite message3 = + TestAllExtensionsLite.parseFrom(rawBytes, registry); + + TestUtil.assertAllExtensionsSet(message3); + } + + public void testParsePackedExtensionsLite() throws Exception { + // Ensure that packed extensions can be properly parsed. + TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet(); + ByteString rawBytes = message.toByteString(); + + ExtensionRegistryLite registry = TestUtil.getExtensionRegistryLite(); + + TestPackedExtensionsLite message2 = + TestPackedExtensionsLite.parseFrom(rawBytes, registry); + + TestUtil.assertPackedExtensionsSet(message2); + } + public void testExtensionsSerializedSize() throws Exception { assertEquals(TestUtil.getAllSet().getSerializedSize(), TestUtil.getAllExtensionsSet().getSerializedSize()); diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py index fa1e3402..d8a825df 100755 --- a/python/google/protobuf/internal/containers.py +++ b/python/google/protobuf/internal/containers.py @@ -112,9 +112,11 @@ class RepeatedScalarFieldContainer(BaseContainer): return orig_empty = len(self._values) == 0 + new_values = [] for elem in elem_seq: self._type_checker.CheckValue(elem) - self._values.extend(elem_seq) + new_values.append(elem) + self._values.extend(new_values) self._message_listener.ByteSizeDirty() if orig_empty: self._message_listener.TransitionToNonempty() @@ -139,9 +141,11 @@ class RepeatedScalarFieldContainer(BaseContainer): def __setslice__(self, start, stop, values): """Sets the subset of items from between the specified indices.""" + new_values = [] for value in values: self._type_checker.CheckValue(value) - self._values[start:stop] = list(values) + new_values.append(value) + self._values[start:stop] = new_values self._message_listener.ByteSizeDirty() def __delitem__(self, key): diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py index 0bee6101..83d6fe0c 100755 --- a/python/google/protobuf/internal/decoder.py +++ b/python/google/protobuf/internal/decoder.py @@ -135,12 +135,12 @@ class Decoder(object): def ReadFloat(self): """Reads and returns a 4-byte floating-point number.""" serialized = self._stream.ReadBytes(4) - return struct.unpack('f', serialized)[0] + return struct.unpack(wire_format.FORMAT_FLOAT_LITTLE_ENDIAN, serialized)[0] def ReadDouble(self): """Reads and returns an 8-byte floating-point number.""" serialized = self._stream.ReadBytes(8) - return struct.unpack('d', serialized)[0] + return struct.unpack(wire_format.FORMAT_DOUBLE_LITTLE_ENDIAN, serialized)[0] def ReadBool(self): """Reads and returns a bool.""" diff --git a/python/google/protobuf/internal/decoder_test.py b/python/google/protobuf/internal/decoder_test.py index 9bae888c..98e46472 100755 --- a/python/google/protobuf/internal/decoder_test.py +++ b/python/google/protobuf/internal/decoder_test.py @@ -36,12 +36,12 @@ __author__ = 'robinson@google.com (Will Robinson)' import struct import unittest -from google.protobuf.internal import wire_format -from google.protobuf.internal import encoder from google.protobuf.internal import decoder -import logging +from google.protobuf.internal import encoder from google.protobuf.internal import input_stream +from google.protobuf.internal import wire_format from google.protobuf import message +import logging import mox @@ -110,6 +110,10 @@ class DecoderTest(unittest.TestCase): self.mox.VerifyAll() self.mox.ResetAll() + VAL = 1.125 # Perfectly representable as a float (no rounding error). + LITTLE_FLOAT_VAL = '\x00\x00\x90?' + LITTLE_DOUBLE_VAL = '\x00\x00\x00\x00\x00\x00\xf2?' + def testReadScalars(self): test_string = 'I can feel myself getting sutpider.' scalar_tests = [ @@ -125,10 +129,10 @@ class DecoderTest(unittest.TestCase): 'ReadLittleEndian32', long(0xffffffff)], ['sfixed64', decoder.Decoder.ReadSFixed64, long(-1), 'ReadLittleEndian64', 0xffffffffffffffff], - ['float', decoder.Decoder.ReadFloat, 0.0, - 'ReadBytes', struct.pack('f', 0.0), 4], - ['double', decoder.Decoder.ReadDouble, 0.0, - 'ReadBytes', struct.pack('d', 0.0), 8], + ['float', decoder.Decoder.ReadFloat, self.VAL, + 'ReadBytes', self.LITTLE_FLOAT_VAL, 4], + ['double', decoder.Decoder.ReadDouble, self.VAL, + 'ReadBytes', self.LITTLE_DOUBLE_VAL, 8], ['bool', decoder.Decoder.ReadBool, True, 'ReadVarUInt32', 1], ['enum', decoder.Decoder.ReadEnum, 23, 'ReadVarUInt32', 23], ['string', decoder.Decoder.ReadString, diff --git a/python/google/protobuf/internal/encoder.py b/python/google/protobuf/internal/encoder.py index eed8c8bd..3ec3b2b1 100755 --- a/python/google/protobuf/internal/encoder.py +++ b/python/google/protobuf/internal/encoder.py @@ -123,11 +123,13 @@ class Encoder(object): def AppendFloatNoTag(self, value): """Appends a floating-point number to our buffer.""" - self._stream.AppendRawBytes(struct.pack('f', value)) + self._stream.AppendRawBytes( + struct.pack(wire_format.FORMAT_FLOAT_LITTLE_ENDIAN, value)) def AppendDoubleNoTag(self, value): """Appends a double-precision floating-point number to our buffer.""" - self._stream.AppendRawBytes(struct.pack('d', value)) + self._stream.AppendRawBytes( + struct.pack(wire_format.FORMAT_DOUBLE_LITTLE_ENDIAN, value)) def AppendBoolNoTag(self, value): """Appends a boolean to our buffer.""" diff --git a/python/google/protobuf/internal/encoder_test.py b/python/google/protobuf/internal/encoder_test.py index 83a21c39..bf75ea80 100755 --- a/python/google/protobuf/internal/encoder_test.py +++ b/python/google/protobuf/internal/encoder_test.py @@ -123,6 +123,10 @@ class EncoderTest(unittest.TestCase): self.mox.VerifyAll() self.mox.ResetAll() + VAL = 1.125 # Perfectly representable as a float (no rounding error). + LITTLE_FLOAT_VAL = '\x00\x00\x90?' + LITTLE_DOUBLE_VAL = '\x00\x00\x00\x00\x00\x00\xf2?' + def testAppendScalars(self): utf8_bytes = '\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82' utf8_string = unicode(utf8_bytes, 'utf-8') @@ -144,9 +148,9 @@ class EncoderTest(unittest.TestCase): ['sfixed64', self.encoder.AppendSFixed64, 'AppendLittleEndian64', wire_format.WIRETYPE_FIXED64, -1, 0xffffffffffffffff], ['float', self.encoder.AppendFloat, 'AppendRawBytes', - wire_format.WIRETYPE_FIXED32, 0.0, struct.pack('f', 0.0)], + wire_format.WIRETYPE_FIXED32, self.VAL, self.LITTLE_FLOAT_VAL], ['double', self.encoder.AppendDouble, 'AppendRawBytes', - wire_format.WIRETYPE_FIXED64, 0.0, struct.pack('d', 0.0)], + wire_format.WIRETYPE_FIXED64, self.VAL, self.LITTLE_DOUBLE_VAL], ['bool', self.encoder.AppendBool, 'AppendVarint32', wire_format.WIRETYPE_VARINT, False], ['enum', self.encoder.AppendEnum, 'AppendVarint32', @@ -185,9 +189,9 @@ class EncoderTest(unittest.TestCase): ['sfixed64', self.encoder.AppendSFixed64NoTag, 'AppendLittleEndian64', None, 0], ['float', self.encoder.AppendFloatNoTag, - 'AppendRawBytes', None, 0.0, struct.pack('f', 0.0)], + 'AppendRawBytes', None, self.VAL, self.LITTLE_FLOAT_VAL], ['double', self.encoder.AppendDoubleNoTag, - 'AppendRawBytes', None, 0.0, struct.pack('d', 0.0)], + 'AppendRawBytes', None, self.VAL, self.LITTLE_DOUBLE_VAL], ['bool', self.encoder.AppendBoolNoTag, 'AppendVarint32', None, 0], ['enum', self.encoder.AppendEnumNoTag, 'AppendVarint32', None, 0], ['sint32', self.encoder.AppendSInt32NoTag, diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py new file mode 100755 index 00000000..df344cf0 --- /dev/null +++ b/python/google/protobuf/internal/message_test.py @@ -0,0 +1,53 @@ +#! /usr/bin/python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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. + +"""Tests python protocol buffers against the golden message.""" + +__author__ = 'gps@google.com (Gregory P. Smith)' + +import unittest +from google.protobuf import unittest_import_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf.internal import test_util + + +class MessageTest(test_util.GoldenMessageTestCase): + + def testGoldenMessage(self): + golden_data = test_util.GoldenFile('golden_message').read() + golden_message = unittest_pb2.TestAllTypes() + golden_message.ParseFromString(golden_data) + self.ExpectAllFieldsSet(golden_message) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py index e2da769a..86101774 100755 --- a/python/google/protobuf/internal/reflection_test.py +++ b/python/google/protobuf/internal/reflection_test.py @@ -232,13 +232,14 @@ class ReflectionTest(unittest.TestCase): proto.repeated_string.extend(['foo', 'bar']) proto.repeated_string.extend([]) proto.repeated_string.append('baz') + proto.repeated_string.extend(str(x) for x in xrange(2)) proto.optional_int32 = 21 self.assertEqual( [ (proto.DESCRIPTOR.fields_by_name['optional_int32' ], 21), (proto.DESCRIPTOR.fields_by_name['repeated_int32' ], [5, 11]), (proto.DESCRIPTOR.fields_by_name['repeated_fixed32'], [1]), (proto.DESCRIPTOR.fields_by_name['repeated_string' ], - ['foo', 'bar', 'baz']) ], + ['foo', 'bar', 'baz', '0', '1']) ], proto.ListFields()) def testSingularListExtensions(self): @@ -447,6 +448,10 @@ class ReflectionTest(unittest.TestCase): self.assertEqual([25, 20, 15], proto.repeated_int32[1:4]) self.assertEqual([5, 25, 20, 15, 30], proto.repeated_int32[:]) + # Test slice assignment with an iterator + proto.repeated_int32[1:4] = (i for i in xrange(3)) + self.assertEqual([5, 0, 1, 2, 30], proto.repeated_int32) + # Test slice assignment. proto.repeated_int32[1:4] = [35, 40, 45] self.assertEqual([5, 35, 40, 45, 30], proto.repeated_int32) @@ -1739,13 +1744,14 @@ class SerializationTest(unittest.TestCase): self.assertEqual(2, proto2.b) self.assertEqual(3, proto2.c) - def testSerializedAllPackedFields(self): + def testSerializeAllPackedFields(self): first_proto = unittest_pb2.TestPackedTypes() second_proto = unittest_pb2.TestPackedTypes() test_util.SetAllPackedFields(first_proto) serialized = first_proto.SerializeToString() self.assertEqual(first_proto.ByteSize(), len(serialized)) - second_proto.MergeFromString(serialized) + bytes_read = second_proto.MergeFromString(serialized) + self.assertEqual(second_proto.ByteSize(), bytes_read) self.assertEqual(first_proto, second_proto) def testSerializeAllPackedExtensions(self): @@ -1753,7 +1759,8 @@ class SerializationTest(unittest.TestCase): second_proto = unittest_pb2.TestPackedExtensions() test_util.SetAllPackedExtensions(first_proto) serialized = first_proto.SerializeToString() - second_proto.MergeFromString(serialized) + bytes_read = second_proto.MergeFromString(serialized) + self.assertEqual(second_proto.ByteSize(), bytes_read) self.assertEqual(first_proto, second_proto) def testMergePackedFromStringWhenSomeFieldsAlreadySet(self): @@ -1838,6 +1845,79 @@ class SerializationTest(unittest.TestCase): self.assertEqual(unittest_pb2.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 51) + def testInitKwargs(self): + proto = unittest_pb2.TestAllTypes( + optional_int32=1, + optional_string='foo', + optional_bool=True, + optional_bytes='bar', + optional_nested_message=unittest_pb2.TestAllTypes.NestedMessage(bb=1), + optional_foreign_message=unittest_pb2.ForeignMessage(c=1), + optional_nested_enum=unittest_pb2.TestAllTypes.FOO, + optional_foreign_enum=unittest_pb2.FOREIGN_FOO, + repeated_int32=[1, 2, 3]) + self.assertTrue(proto.IsInitialized()) + self.assertTrue(proto.HasField('optional_int32')) + self.assertTrue(proto.HasField('optional_string')) + self.assertTrue(proto.HasField('optional_bool')) + self.assertTrue(proto.HasField('optional_bytes')) + self.assertTrue(proto.HasField('optional_nested_message')) + self.assertTrue(proto.HasField('optional_foreign_message')) + self.assertTrue(proto.HasField('optional_nested_enum')) + self.assertTrue(proto.HasField('optional_foreign_enum')) + self.assertEqual(1, proto.optional_int32) + self.assertEqual('foo', proto.optional_string) + self.assertEqual(True, proto.optional_bool) + self.assertEqual('bar', proto.optional_bytes) + self.assertEqual(1, proto.optional_nested_message.bb) + self.assertEqual(1, proto.optional_foreign_message.c) + self.assertEqual(unittest_pb2.TestAllTypes.FOO, + proto.optional_nested_enum) + self.assertEqual(unittest_pb2.FOREIGN_FOO, proto.optional_foreign_enum) + self.assertEqual([1, 2, 3], proto.repeated_int32) + + def testInitArgsUnknownFieldName(self): + def InitalizeEmptyMessageWithExtraKeywordArg(): + unused_proto = unittest_pb2.TestEmptyMessage(unknown='unknown') + self._CheckRaises(ValueError, + InitalizeEmptyMessageWithExtraKeywordArg, + 'Protocol message has no "unknown" field.') + + def testInitRequiredKwargs(self): + proto = unittest_pb2.TestRequired(a=1, b=1, c=1) + self.assertTrue(proto.IsInitialized()) + self.assertTrue(proto.HasField('a')) + self.assertTrue(proto.HasField('b')) + self.assertTrue(proto.HasField('c')) + self.assertTrue(not proto.HasField('dummy2')) + self.assertEqual(1, proto.a) + self.assertEqual(1, proto.b) + self.assertEqual(1, proto.c) + + def testInitRequiredForeignKwargs(self): + proto = unittest_pb2.TestRequiredForeign( + optional_message=unittest_pb2.TestRequired(a=1, b=1, c=1)) + self.assertTrue(proto.IsInitialized()) + self.assertTrue(proto.HasField('optional_message')) + self.assertTrue(proto.optional_message.IsInitialized()) + self.assertTrue(proto.optional_message.HasField('a')) + self.assertTrue(proto.optional_message.HasField('b')) + self.assertTrue(proto.optional_message.HasField('c')) + self.assertTrue(not proto.optional_message.HasField('dummy2')) + self.assertEqual(unittest_pb2.TestRequired(a=1, b=1, c=1), + proto.optional_message) + self.assertEqual(1, proto.optional_message.a) + self.assertEqual(1, proto.optional_message.b) + self.assertEqual(1, proto.optional_message.c) + + def testInitRepeatedKwargs(self): + proto = unittest_pb2.TestAllTypes(repeated_int32=[1, 2, 3]) + self.assertTrue(proto.IsInitialized()) + self.assertEqual(1, proto.repeated_int32[0]) + self.assertEqual(2, proto.repeated_int32[1]) + self.assertEqual(3, proto.repeated_int32[2]) + + class OptionsTest(unittest.TestCase): def testMessageOptions(self): diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py index 2d50bc4a..1a0da552 100755 --- a/python/google/protobuf/internal/test_util.py +++ b/python/google/protobuf/internal/test_util.py @@ -38,6 +38,7 @@ __author__ = 'robinson@google.com (Will Robinson)' import os.path +import unittest from google.protobuf import unittest_import_pb2 from google.protobuf import unittest_pb2 @@ -351,6 +352,200 @@ def ExpectAllFieldsAndExtensionsInOrder(serialized): if expected != serialized: raise ValueError('Expected %r, found %r' % (expected, serialized)) + +class GoldenMessageTestCase(unittest.TestCase): + """This adds methods to TestCase useful for verifying our Golden Message.""" + + def ExpectAllFieldsSet(self, message): + """Check all fields for correct values have after Set*Fields() is called.""" + self.assertTrue(message.HasField('optional_int32')) + self.assertTrue(message.HasField('optional_int64')) + self.assertTrue(message.HasField('optional_uint32')) + self.assertTrue(message.HasField('optional_uint64')) + self.assertTrue(message.HasField('optional_sint32')) + self.assertTrue(message.HasField('optional_sint64')) + self.assertTrue(message.HasField('optional_fixed32')) + self.assertTrue(message.HasField('optional_fixed64')) + self.assertTrue(message.HasField('optional_sfixed32')) + self.assertTrue(message.HasField('optional_sfixed64')) + self.assertTrue(message.HasField('optional_float')) + self.assertTrue(message.HasField('optional_double')) + self.assertTrue(message.HasField('optional_bool')) + self.assertTrue(message.HasField('optional_string')) + self.assertTrue(message.HasField('optional_bytes')) + + self.assertTrue(message.HasField('optionalgroup')) + self.assertTrue(message.HasField('optional_nested_message')) + self.assertTrue(message.HasField('optional_foreign_message')) + self.assertTrue(message.HasField('optional_import_message')) + + self.assertTrue(message.optionalgroup.HasField('a')) + self.assertTrue(message.optional_nested_message.HasField('bb')) + self.assertTrue(message.optional_foreign_message.HasField('c')) + self.assertTrue(message.optional_import_message.HasField('d')) + + self.assertTrue(message.HasField('optional_nested_enum')) + self.assertTrue(message.HasField('optional_foreign_enum')) + self.assertTrue(message.HasField('optional_import_enum')) + + self.assertTrue(message.HasField('optional_string_piece')) + self.assertTrue(message.HasField('optional_cord')) + + self.assertEqual(101, message.optional_int32) + self.assertEqual(102, message.optional_int64) + self.assertEqual(103, message.optional_uint32) + self.assertEqual(104, message.optional_uint64) + self.assertEqual(105, message.optional_sint32) + self.assertEqual(106, message.optional_sint64) + self.assertEqual(107, message.optional_fixed32) + self.assertEqual(108, message.optional_fixed64) + self.assertEqual(109, message.optional_sfixed32) + self.assertEqual(110, message.optional_sfixed64) + self.assertEqual(111, message.optional_float) + self.assertEqual(112, message.optional_double) + self.assertEqual(True, message.optional_bool) + self.assertEqual('115', message.optional_string) + self.assertEqual('116', message.optional_bytes) + + self.assertEqual(117, message.optionalgroup.a); + self.assertEqual(118, message.optional_nested_message.bb) + self.assertEqual(119, message.optional_foreign_message.c) + self.assertEqual(120, message.optional_import_message.d) + + self.assertEqual(unittest_pb2.TestAllTypes.BAZ, + message.optional_nested_enum) + self.assertEqual(unittest_pb2.FOREIGN_BAZ, message.optional_foreign_enum) + self.assertEqual(unittest_import_pb2.IMPORT_BAZ, + message.optional_import_enum) + + # ----------------------------------------------------------------- + + self.assertEqual(2, len(message.repeated_int32)) + self.assertEqual(2, len(message.repeated_int64)) + self.assertEqual(2, len(message.repeated_uint32)) + self.assertEqual(2, len(message.repeated_uint64)) + self.assertEqual(2, len(message.repeated_sint32)) + self.assertEqual(2, len(message.repeated_sint64)) + self.assertEqual(2, len(message.repeated_fixed32)) + self.assertEqual(2, len(message.repeated_fixed64)) + self.assertEqual(2, len(message.repeated_sfixed32)) + self.assertEqual(2, len(message.repeated_sfixed64)) + self.assertEqual(2, len(message.repeated_float)) + self.assertEqual(2, len(message.repeated_double)) + self.assertEqual(2, len(message.repeated_bool)) + self.assertEqual(2, len(message.repeated_string)) + self.assertEqual(2, len(message.repeated_bytes)) + + self.assertEqual(2, len(message.repeatedgroup)) + self.assertEqual(2, len(message.repeated_nested_message)) + self.assertEqual(2, len(message.repeated_foreign_message)) + self.assertEqual(2, len(message.repeated_import_message)) + self.assertEqual(2, len(message.repeated_nested_enum)) + self.assertEqual(2, len(message.repeated_foreign_enum)) + self.assertEqual(2, len(message.repeated_import_enum)) + + self.assertEqual(2, len(message.repeated_string_piece)) + self.assertEqual(2, len(message.repeated_cord)) + + self.assertEqual(201, message.repeated_int32[0]) + self.assertEqual(202, message.repeated_int64[0]) + self.assertEqual(203, message.repeated_uint32[0]) + self.assertEqual(204, message.repeated_uint64[0]) + self.assertEqual(205, message.repeated_sint32[0]) + self.assertEqual(206, message.repeated_sint64[0]) + self.assertEqual(207, message.repeated_fixed32[0]) + self.assertEqual(208, message.repeated_fixed64[0]) + self.assertEqual(209, message.repeated_sfixed32[0]) + self.assertEqual(210, message.repeated_sfixed64[0]) + self.assertEqual(211, message.repeated_float[0]) + self.assertEqual(212, message.repeated_double[0]) + self.assertEqual(True, message.repeated_bool[0]) + self.assertEqual('215', message.repeated_string[0]) + self.assertEqual('216', message.repeated_bytes[0]) + + self.assertEqual(217, message.repeatedgroup[0].a) + self.assertEqual(218, message.repeated_nested_message[0].bb) + self.assertEqual(219, message.repeated_foreign_message[0].c) + self.assertEqual(220, message.repeated_import_message[0].d) + + self.assertEqual(unittest_pb2.TestAllTypes.BAR, + message.repeated_nested_enum[0]) + self.assertEqual(unittest_pb2.FOREIGN_BAR, + message.repeated_foreign_enum[0]) + self.assertEqual(unittest_import_pb2.IMPORT_BAR, + message.repeated_import_enum[0]) + + self.assertEqual(301, message.repeated_int32[1]) + self.assertEqual(302, message.repeated_int64[1]) + self.assertEqual(303, message.repeated_uint32[1]) + self.assertEqual(304, message.repeated_uint64[1]) + self.assertEqual(305, message.repeated_sint32[1]) + self.assertEqual(306, message.repeated_sint64[1]) + self.assertEqual(307, message.repeated_fixed32[1]) + self.assertEqual(308, message.repeated_fixed64[1]) + self.assertEqual(309, message.repeated_sfixed32[1]) + self.assertEqual(310, message.repeated_sfixed64[1]) + self.assertEqual(311, message.repeated_float[1]) + self.assertEqual(312, message.repeated_double[1]) + self.assertEqual(False, message.repeated_bool[1]) + self.assertEqual('315', message.repeated_string[1]) + self.assertEqual('316', message.repeated_bytes[1]) + + self.assertEqual(317, message.repeatedgroup[1].a) + self.assertEqual(318, message.repeated_nested_message[1].bb) + self.assertEqual(319, message.repeated_foreign_message[1].c) + self.assertEqual(320, message.repeated_import_message[1].d) + + self.assertEqual(unittest_pb2.TestAllTypes.BAZ, + message.repeated_nested_enum[1]) + self.assertEqual(unittest_pb2.FOREIGN_BAZ, + message.repeated_foreign_enum[1]) + self.assertEqual(unittest_import_pb2.IMPORT_BAZ, + message.repeated_import_enum[1]) + + # ----------------------------------------------------------------- + + self.assertTrue(message.HasField('default_int32')) + self.assertTrue(message.HasField('default_int64')) + self.assertTrue(message.HasField('default_uint32')) + self.assertTrue(message.HasField('default_uint64')) + self.assertTrue(message.HasField('default_sint32')) + self.assertTrue(message.HasField('default_sint64')) + self.assertTrue(message.HasField('default_fixed32')) + self.assertTrue(message.HasField('default_fixed64')) + self.assertTrue(message.HasField('default_sfixed32')) + self.assertTrue(message.HasField('default_sfixed64')) + self.assertTrue(message.HasField('default_float')) + self.assertTrue(message.HasField('default_double')) + self.assertTrue(message.HasField('default_bool')) + self.assertTrue(message.HasField('default_string')) + self.assertTrue(message.HasField('default_bytes')) + + self.assertTrue(message.HasField('default_nested_enum')) + self.assertTrue(message.HasField('default_foreign_enum')) + self.assertTrue(message.HasField('default_import_enum')) + + self.assertEqual(401, message.default_int32) + self.assertEqual(402, message.default_int64) + self.assertEqual(403, message.default_uint32) + self.assertEqual(404, message.default_uint64) + self.assertEqual(405, message.default_sint32) + self.assertEqual(406, message.default_sint64) + self.assertEqual(407, message.default_fixed32) + self.assertEqual(408, message.default_fixed64) + self.assertEqual(409, message.default_sfixed32) + self.assertEqual(410, message.default_sfixed64) + self.assertEqual(411, message.default_float) + self.assertEqual(412, message.default_double) + self.assertEqual(False, message.default_bool) + self.assertEqual('415', message.default_string) + self.assertEqual('416', message.default_bytes) + + self.assertEqual(unittest_pb2.TestAllTypes.FOO, message.default_nested_enum) + self.assertEqual(unittest_pb2.FOREIGN_FOO, message.default_foreign_enum) + self.assertEqual(unittest_import_pb2.IMPORT_FOO, + message.default_import_enum) + def GoldenFile(filename): """Finds the given golden file and returns a file object representing it.""" @@ -359,7 +554,8 @@ def GoldenFile(filename): while os.path.exists(path): if os.path.exists(os.path.join(path, 'src/google/protobuf')): # Found it. Load the golden file from the testdata directory. - return file(os.path.join(path, 'src/google/protobuf/testdata', filename)) + full_path = os.path.join(path, 'src/google/protobuf/testdata', filename) + return open(full_path, 'rb') path = os.path.join(path, '..') raise RuntimeError( diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py index 871590e7..0cf27186 100755 --- a/python/google/protobuf/internal/text_format_test.py +++ b/python/google/protobuf/internal/text_format_test.py @@ -42,11 +42,16 @@ from google.protobuf.internal import test_util from google.protobuf import unittest_pb2 from google.protobuf import unittest_mset_pb2 -class TextFormatTest(unittest.TestCase): - def CompareToGoldenFile(self, text, golden_filename): + +class TextFormatTest(test_util.GoldenMessageTestCase): + def ReadGolden(self, golden_filename): f = test_util.GoldenFile(golden_filename) golden_lines = f.readlines() f.close() + return golden_lines + + def CompareToGoldenFile(self, text, golden_filename): + golden_lines = self.ReadGolden(golden_filename) self.CompareToGoldenLines(text, golden_lines) def CompareToGoldenText(self, text, golden_text): @@ -117,6 +122,276 @@ class TextFormatTest(unittest.TestCase): return text.replace('e+0','e+').replace('e+0','e+') \ .replace('e-0','e-').replace('e-0','e-') + def testMergeGolden(self): + golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt')) + parsed_message = unittest_pb2.TestAllTypes() + text_format.Merge(golden_text, parsed_message) + + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.assertEquals(message, parsed_message) + + def testMergeGoldenExtensions(self): + golden_text = '\n'.join(self.ReadGolden( + 'text_format_unittest_extensions_data.txt')) + parsed_message = unittest_pb2.TestAllExtensions() + text_format.Merge(golden_text, parsed_message) + + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + self.assertEquals(message, parsed_message) + + def testMergeAllFields(self): + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + ascii_text = text_format.MessageToString(message) + + parsed_message = unittest_pb2.TestAllTypes() + text_format.Merge(ascii_text, parsed_message) + self.assertEqual(message, parsed_message) + self.ExpectAllFieldsSet(message) + + def testMergeAllExtensions(self): + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + ascii_text = text_format.MessageToString(message) + + parsed_message = unittest_pb2.TestAllExtensions() + text_format.Merge(ascii_text, parsed_message) + self.assertEqual(message, parsed_message) + + def testMergeMessageSet(self): + message = unittest_pb2.TestAllTypes() + text = ('repeated_uint64: 1\n' + 'repeated_uint64: 2\n') + text_format.Merge(text, message) + self.assertEqual(1, message.repeated_uint64[0]) + self.assertEqual(2, message.repeated_uint64[1]) + + message = unittest_mset_pb2.TestMessageSetContainer() + text = ('message_set {\n' + ' [protobuf_unittest.TestMessageSetExtension1] {\n' + ' i: 23\n' + ' }\n' + ' [protobuf_unittest.TestMessageSetExtension2] {\n' + ' str: \"foo\"\n' + ' }\n' + '}\n') + text_format.Merge(text, message) + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + self.assertEquals(23, message.message_set.Extensions[ext1].i) + self.assertEquals('foo', message.message_set.Extensions[ext2].str) + + def testMergeExotic(self): + message = unittest_pb2.TestAllTypes() + text = ('repeated_int64: -9223372036854775808\n' + 'repeated_uint64: 18446744073709551615\n' + 'repeated_double: 123.456\n' + 'repeated_double: 1.23e+22\n' + 'repeated_double: 1.23e-18\n' + 'repeated_string: \n' + '\"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\\"\"\n') + text_format.Merge(text, message) + + self.assertEqual(-9223372036854775808, message.repeated_int64[0]) + self.assertEqual(18446744073709551615, message.repeated_uint64[0]) + self.assertEqual(123.456, message.repeated_double[0]) + self.assertEqual(1.23e22, message.repeated_double[1]) + self.assertEqual(1.23e-18, message.repeated_double[2]) + self.assertEqual( + '\000\001\a\b\f\n\r\t\v\\\'\"', message.repeated_string[0]) + + def testMergeUnknownField(self): + message = unittest_pb2.TestAllTypes() + text = 'unknown_field: 8\n' + self.assertRaisesWithMessage( + text_format.ParseError, + ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named ' + '"unknown_field".'), + text_format.Merge, text, message) + + def testMergeBadExtension(self): + message = unittest_pb2.TestAllTypes() + text = '[unknown_extension]: 8\n' + self.assertRaisesWithMessage( + text_format.ParseError, + '1:2 : Extension "unknown_extension" not registered.', + text_format.Merge, text, message) + + def testMergeGroupNotClosed(self): + message = unittest_pb2.TestAllTypes() + text = 'RepeatedGroup: <' + self.assertRaisesWithMessage( + text_format.ParseError, '1:16 : Expected ">".', + text_format.Merge, text, message) + + text = 'RepeatedGroup: {' + self.assertRaisesWithMessage( + text_format.ParseError, '1:16 : Expected "}".', + text_format.Merge, text, message) + + def testMergeBadEnumValue(self): + message = unittest_pb2.TestAllTypes() + text = 'optional_nested_enum: BARR' + self.assertRaisesWithMessage( + text_format.ParseError, + ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" ' + 'has no value named BARR.'), + text_format.Merge, text, message) + + message = unittest_pb2.TestAllTypes() + text = 'optional_nested_enum: 100' + self.assertRaisesWithMessage( + text_format.ParseError, + ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" ' + 'has no value with number 100.'), + text_format.Merge, text, message) + + def assertRaisesWithMessage(self, e_class, e, func, *args, **kwargs): + """Same as assertRaises, but also compares the exception message.""" + if hasattr(e_class, '__name__'): + exc_name = e_class.__name__ + else: + exc_name = str(e_class) + + try: + func(*args, **kwargs) + except e_class, expr: + if str(expr) != e: + msg = '%s raised, but with wrong message: "%s" instead of "%s"' + raise self.failureException(msg % (exc_name, + str(expr).encode('string_escape'), + e.encode('string_escape'))) + return + else: + raise self.failureException('%s not raised' % exc_name) + + +class TokenizerTest(unittest.TestCase): + + def testSimpleTokenCases(self): + text = ('identifier1:"string1"\n \n\n' + 'identifier2 : \n \n123 \n identifier3 :\'string\'\n' + 'identifiER_4 : 1.1e+2 ID5:-0.23 ID6:\'aaaa\\\'bbbb\'\n' + 'ID7 : "aa\\"bb"\n\n\n\n ID8: {A:inf B:-inf C:true D:false}\n' + 'ID9: 22 ID10: -111111111111111111 ID11: -22\n' + 'ID12: 2222222222222222222') + tokenizer = text_format._Tokenizer(text) + methods = [(tokenizer.ConsumeIdentifier, 'identifier1'), + ':', + (tokenizer.ConsumeString, 'string1'), + (tokenizer.ConsumeIdentifier, 'identifier2'), + ':', + (tokenizer.ConsumeInt32, 123), + (tokenizer.ConsumeIdentifier, 'identifier3'), + ':', + (tokenizer.ConsumeString, 'string'), + (tokenizer.ConsumeIdentifier, 'identifiER_4'), + ':', + (tokenizer.ConsumeFloat, 1.1e+2), + (tokenizer.ConsumeIdentifier, 'ID5'), + ':', + (tokenizer.ConsumeFloat, -0.23), + (tokenizer.ConsumeIdentifier, 'ID6'), + ':', + (tokenizer.ConsumeString, 'aaaa\'bbbb'), + (tokenizer.ConsumeIdentifier, 'ID7'), + ':', + (tokenizer.ConsumeString, 'aa\"bb'), + (tokenizer.ConsumeIdentifier, 'ID8'), + ':', + '{', + (tokenizer.ConsumeIdentifier, 'A'), + ':', + (tokenizer.ConsumeFloat, float('inf')), + (tokenizer.ConsumeIdentifier, 'B'), + ':', + (tokenizer.ConsumeFloat, float('-inf')), + (tokenizer.ConsumeIdentifier, 'C'), + ':', + (tokenizer.ConsumeBool, True), + (tokenizer.ConsumeIdentifier, 'D'), + ':', + (tokenizer.ConsumeBool, False), + '}', + (tokenizer.ConsumeIdentifier, 'ID9'), + ':', + (tokenizer.ConsumeUint32, 22), + (tokenizer.ConsumeIdentifier, 'ID10'), + ':', + (tokenizer.ConsumeInt64, -111111111111111111), + (tokenizer.ConsumeIdentifier, 'ID11'), + ':', + (tokenizer.ConsumeInt32, -22), + (tokenizer.ConsumeIdentifier, 'ID12'), + ':', + (tokenizer.ConsumeUint64, 2222222222222222222)] + + i = 0 + while not tokenizer.AtEnd(): + m = methods[i] + if type(m) == str: + token = tokenizer.token + self.assertEqual(token, m) + tokenizer.NextToken() + else: + self.assertEqual(m[1], m[0]()) + i += 1 + + def testConsumeIntegers(self): + # This test only tests the failures in the integer parsing methods as well + # as the '0' special cases. + int64_max = (1 << 63) - 1 + uint32_max = (1 << 32) - 1 + text = '-1 %d %d' % (uint32_max + 1, int64_max + 1) + tokenizer = text_format._Tokenizer(text) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint32) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint64) + self.assertEqual(-1, tokenizer.ConsumeInt32()) + + self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint32) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeInt32) + self.assertEqual(uint32_max + 1, tokenizer.ConsumeInt64()) + + self.assertRaises(text_format.ParseError, tokenizer.ConsumeInt64) + self.assertEqual(int64_max + 1, tokenizer.ConsumeUint64()) + self.assertTrue(tokenizer.AtEnd()) + + text = '-0 -0 0 0' + tokenizer = text_format._Tokenizer(text) + self.assertEqual(0, tokenizer.ConsumeUint32()) + self.assertEqual(0, tokenizer.ConsumeUint64()) + self.assertEqual(0, tokenizer.ConsumeUint32()) + self.assertEqual(0, tokenizer.ConsumeUint64()) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeByteString(self): + text = '"string1\'' + tokenizer = text_format._Tokenizer(text) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + text = 'string1"' + tokenizer = text_format._Tokenizer(text) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + text = '\n"\\xt"' + tokenizer = text_format._Tokenizer(text) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + text = '\n"\\"' + tokenizer = text_format._Tokenizer(text) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + text = '\n"\\x"' + tokenizer = text_format._Tokenizer(text) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + def testConsumeBool(self): + text = 'not-a-bool' + tokenizer = text_format._Tokenizer(text) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeBool) + + if __name__ == '__main__': unittest.main() - diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py index c009627f..a3bc57ff 100755 --- a/python/google/protobuf/internal/type_checkers.py +++ b/python/google/protobuf/internal/type_checkers.py @@ -122,8 +122,10 @@ class UnicodeValueChecker(object): try: unicode(proposed_value, 'ascii') except UnicodeDecodeError: - raise ValueError('%.1024r isn\'t in 7-bit ASCII encoding.' - % (proposed_value)) + raise ValueError('%.1024r has type str, but isn\'t in 7-bit ASCII ' + 'encoding. Non-ASCII strings must be converted to ' + 'unicode objects before being added.' % + (proposed_value)) class Int32ValueChecker(IntValueChecker): diff --git a/python/google/protobuf/internal/wire_format.py b/python/google/protobuf/internal/wire_format.py index 950267f9..da6464de 100755 --- a/python/google/protobuf/internal/wire_format.py +++ b/python/google/protobuf/internal/wire_format.py @@ -64,6 +64,8 @@ UINT64_MAX = (1 << 64) - 1 # "struct" format strings that will encode/decode the specified formats. FORMAT_UINT32_LITTLE_ENDIAN = '= '0' and c <= '9') or c == '-' or c == '+' + + def ConsumeIdentifier(self): + """Consumes protocol message field identifier. + + Returns: + Identifier string. + + Raises: + ParseError: If an identifier couldn't be consumed. + """ + result = self.token + if not re.match(self._IDENTIFIER, result): + raise self._ParseError('Expected identifier.') + self.NextToken() + return result + + def ConsumeInt32(self): + """Consumes a signed 32bit integer number. + + Returns: + The integer parsed. + + Raises: + ParseError: If a signed 32bit integer couldn't be consumed. + """ + try: + result = self._ParseInteger(self.token, is_signed=True, is_long=False) + except ValueError, e: + raise self._IntegerParseError(e) + self.NextToken() + return result + + def ConsumeUint32(self): + """Consumes an unsigned 32bit integer number. + + Returns: + The integer parsed. + + Raises: + ParseError: If an unsigned 32bit integer couldn't be consumed. + """ + try: + result = self._ParseInteger(self.token, is_signed=False, is_long=False) + except ValueError, e: + raise self._IntegerParseError(e) + self.NextToken() + return result + + def ConsumeInt64(self): + """Consumes a signed 64bit integer number. + + Returns: + The integer parsed. + + Raises: + ParseError: If a signed 64bit integer couldn't be consumed. + """ + try: + result = self._ParseInteger(self.token, is_signed=True, is_long=True) + except ValueError, e: + raise self._IntegerParseError(e) + self.NextToken() + return result + + def ConsumeUint64(self): + """Consumes an unsigned 64bit integer number. + + Returns: + The integer parsed. + + Raises: + ParseError: If an unsigned 64bit integer couldn't be consumed. + """ + try: + result = self._ParseInteger(self.token, is_signed=False, is_long=True) + except ValueError, e: + raise self._IntegerParseError(e) + self.NextToken() + return result + + def ConsumeFloat(self): + """Consumes an floating point number. + + Returns: + The number parsed. + + Raises: + ParseError: If a floating point number couldn't be consumed. + """ + text = self.token + if re.match(self._FLOAT_INFINITY, text): + self.NextToken() + if text.startswith('-'): + return float('-inf') + return float('inf') + + if re.match(self._FLOAT_NAN, text): + self.NextToken() + return float('nan') + + try: + result = float(text) + except ValueError, e: + raise self._FloatParseError(e) + self.NextToken() + return result + + def ConsumeBool(self): + """Consumes a boolean value. + + Returns: + The bool parsed. + + Raises: + ParseError: If a boolean value couldn't be consumed. + """ + if self.token == 'true': + self.NextToken() + return True + elif self.token == 'false': + self.NextToken() + return False + else: + raise self._ParseError('Expected "true" or "false".') + + def ConsumeString(self): + """Consumes a string value. + + Returns: + The string parsed. + + Raises: + ParseError: If a string value couldn't be consumed. + """ + return unicode(self.ConsumeByteString(), 'utf-8') + + def ConsumeByteString(self): + """Consumes a byte array value. + + Returns: + The array parsed (as a string). + + Raises: + ParseError: If a byte array value couldn't be consumed. + """ + text = self.token + if len(text) < 1 or text[0] not in ('\'', '"'): + raise self._ParseError('Exptected string.') + + if len(text) < 2 or text[-1] != text[0]: + raise self._ParseError('String missing ending quote.') + + try: + result = _CUnescape(text[1:-1]) + except ValueError, e: + raise self._ParseError(str(e)) + self.NextToken() + return result + + def _ParseInteger(self, text, is_signed=False, is_long=False): + """Parses an integer. + + Args: + text: The text to parse. + is_signed: True if a signed integer must be parsed. + is_long: True if a long integer must be parsed. + + Returns: + The integer value. + + Raises: + ValueError: Thrown Iff the text is not a valid integer. + """ + pos = 0 + if text.startswith('-'): + pos += 1 + + base = 10 + if text.startswith('0x', pos) or text.startswith('0X', pos): + base = 16 + elif text.startswith('0', pos): + base = 8 + + # Do the actual parsing. Exception handling is propagated to caller. + result = int(text, base) + + # Check if the integer is sane. Exceptions handled by callers. + checker = self._INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)] + checker.CheckValue(result) + return result + + def ParseErrorPreviousToken(self, message): + """Creates and *returns* a ParseError for the previously read token. + + Args: + message: A message to set for the exception. + + Returns: + A ParseError instance. + """ + return ParseError('%d:%d : %s' % ( + self._previous_line + 1, self._previous_column + 1, message)) + + def _ParseError(self, message): + """Creates and *returns* a ParseError for the current token.""" + return ParseError('%d:%d : %s' % ( + self._line + 1, self._column + 1, message)) + + def _IntegerParseError(self, e): + return self._ParseError('Couldn\'t parse integer: ' + str(e)) + + def _FloatParseError(self, e): + return self._ParseError('Couldn\'t parse number: ' + str(e)) + + def NextToken(self): + """Reads the next meaningful token.""" + self._previous_line = self._line + self._previous_column = self._column + if self.AtEnd(): + self.token = '' + return + self._column += len(self.token) + + # Make sure there is data to work on. + self._PopLine() + + match = re.match(self._TOKEN, self._current_line) + if match: + token = match.group(0) + self._current_line = self._current_line[len(token):] + self.token = token + else: + self.token = self._current_line[0] + self._current_line = self._current_line[1:] + self._SkipWhitespace() + + # text.encode('string_escape') does not seem to satisfy our needs as it # encodes unprintable characters using two-digit hex escapes whereas our # C++ unescaping function allows hex escapes to be any length. So, @@ -123,3 +636,15 @@ def _CEscape(text): if o >= 127 or o < 32: return "\\%03o" % o # necessary escapes return c return "".join([escape(c) for c in text]) + + +_CUNESCAPE_HEX = re.compile('\\\\x([0-9a-fA-F]{2}|[0-9a-f-A-F])') + + +def _CUnescape(text): + def ReplaceHex(m): + return chr(int(m.group(0)[2:], 16)) + # This is required because the 'string_escape' encoding doesn't + # allow single-digit hex escapes (like '\xf'). + result = _CUNESCAPE_HEX.sub(ReplaceHex, text) + return result.decode('string_escape') diff --git a/src/Makefile.am b/src/Makefile.am index 3e32c25e..e4a30ab2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,21 +43,25 @@ nobase_include_HEADERS = \ google/protobuf/descriptor_database.h \ google/protobuf/dynamic_message.h \ google/protobuf/extension_set.h \ + google/protobuf/generated_message_util.h \ google/protobuf/generated_message_reflection.h \ google/protobuf/message.h \ + google/protobuf/message_lite.h \ google/protobuf/reflection_ops.h \ google/protobuf/repeated_field.h \ google/protobuf/service.h \ google/protobuf/text_format.h \ google/protobuf/unknown_field_set.h \ google/protobuf/wire_format.h \ - google/protobuf/wire_format_inl.h \ + google/protobuf/wire_format_lite.h \ + google/protobuf/wire_format_lite_inl.h \ google/protobuf/io/coded_stream.h \ $(GZHEADERS) \ google/protobuf/io/printer.h \ google/protobuf/io/tokenizer.h \ google/protobuf/io/zero_copy_stream.h \ google/protobuf/io/zero_copy_stream_impl.h \ + google/protobuf/io/zero_copy_stream_impl_lite.h \ google/protobuf/compiler/code_generator.h \ google/protobuf/compiler/command_line_interface.h \ google/protobuf/compiler/importer.h \ @@ -68,6 +72,8 @@ nobase_include_HEADERS = \ lib_LTLIBRARIES = libprotobuf.la libprotoc.la +# TODO(kenton): Separate lite and full libraries. Also make sure lite_unittest +# only links against the lite lib. libprotobuf_la_LIBADD = $(PTHREAD_LIBS) libprotobuf_la_LDFLAGS = -version-info 3:0:0 libprotobuf_la_SOURCES = \ @@ -89,20 +95,25 @@ libprotobuf_la_SOURCES = \ google/protobuf/descriptor_database.cc \ google/protobuf/dynamic_message.cc \ google/protobuf/extension_set.cc \ + google/protobuf/extension_set_heavy.cc \ + google/protobuf/generated_message_util.cc \ google/protobuf/generated_message_reflection.cc \ google/protobuf/message.cc \ + google/protobuf/message_lite.cc \ google/protobuf/reflection_ops.cc \ google/protobuf/repeated_field.cc \ google/protobuf/service.cc \ google/protobuf/text_format.cc \ google/protobuf/unknown_field_set.cc \ google/protobuf/wire_format.cc \ + google/protobuf/wire_format_lite.cc \ google/protobuf/io/coded_stream.cc \ google/protobuf/io/gzip_stream.cc \ google/protobuf/io/printer.cc \ google/protobuf/io/tokenizer.cc \ google/protobuf/io/zero_copy_stream.cc \ google/protobuf/io/zero_copy_stream_impl.cc \ + google/protobuf/io/zero_copy_stream_impl_lite.cc \ google/protobuf/compiler/importer.cc \ google/protobuf/compiler/parser.cc @@ -171,6 +182,9 @@ protoc_inputs = \ google/protobuf/unittest_optimize_for.proto \ google/protobuf/unittest_embed_optimize_for.proto \ google/protobuf/unittest_custom_options.proto \ + google/protobuf/unittest_lite.proto \ + google/protobuf/unittest_import_lite.proto \ + google/protobuf/unittest_lite_imports_nonlite.proto \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto EXTRA_DIST = \ @@ -186,7 +200,14 @@ EXTRA_DIST = \ google/protobuf/io/package_info.h \ google/protobuf/compiler/package_info.h +protoc_lite_outputs = \ + google/protobuf/unittest_lite.pb.cc \ + google/protobuf/unittest_lite.pb.h \ + google/protobuf/unittest_import_lite.pb.cc \ + google/protobuf/unittest_import_lite.pb.h + protoc_outputs = \ + $(protoc_lite_outputs) \ google/protobuf/unittest.pb.cc \ google/protobuf/unittest.pb.h \ google/protobuf/unittest_empty.pb.cc \ @@ -201,6 +222,8 @@ protoc_outputs = \ google/protobuf/unittest_embed_optimize_for.pb.h \ google/protobuf/unittest_custom_options.pb.cc \ google/protobuf/unittest_custom_options.pb.h \ + google/protobuf/unittest_lite_imports_nonlite.pb.cc \ + google/protobuf/unittest_lite_imports_nonlite.pb.h \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h @@ -240,7 +263,7 @@ COMMON_TEST_SOURCES = \ google/protobuf/testing/file.cc \ google/protobuf/testing/file.h -check_PROGRAMS = protobuf-test protobuf-lazy-descriptor-test $(GZCHECKPROGRAMS) +check_PROGRAMS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test $(GZCHECKPROGRAMS) protobuf_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \ $(top_builddir)/gtest/lib/libgtest.la \ $(top_builddir)/gtest/lib/libgtest_main.la @@ -290,6 +313,14 @@ protobuf_lazy_descriptor_test_SOURCES = \ $(COMMON_TEST_SOURCES) nodist_protobuf_lazy_descriptor_test_SOURCES = $(protoc_outputs) +# Build lite_unittest separately, since it doesn't use gtest. +protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la +protobuf_lite_test_SOURCES = \ + google/protobuf/lite_unittest.cc \ + google/protobuf/test_util_lite.cc \ + google/protobuf/test_util_lite.h +nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs) + if HAVE_ZLIB zcgzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la zcgzip_SOURCES = google/protobuf/testing/zcgzip.cc @@ -298,4 +329,4 @@ zcgunzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la zcgunzip_SOURCES = google/protobuf/testing/zcgunzip.cc endif -TESTS = protobuf-test protobuf-lazy-descriptor-test $(GZTESTS) +TESTS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test $(GZTESTS) diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc index 149d34af..0def84d8 100644 --- a/src/google/protobuf/compiler/code_generator.cc +++ b/src/google/protobuf/compiler/code_generator.cc @@ -34,6 +34,8 @@ #include +#include + namespace google { namespace protobuf { namespace compiler { @@ -41,6 +43,26 @@ namespace compiler { CodeGenerator::~CodeGenerator() {} OutputDirectory::~OutputDirectory() {} +// Parses a set of comma-delimited name/value pairs. +void ParseGeneratorParameter(const string& text, + vector >* output) { + vector parts; + SplitStringUsing(text, ",", &parts); + + for (int i = 0; i < parts.size(); i++) { + string::size_type equals_pos = parts[i].find_first_of('='); + pair value; + if (equals_pos == string::npos) { + value.first = parts[i]; + value.second = ""; + } else { + value.first = parts[i].substr(0, equals_pos); + value.second = parts[i].substr(equals_pos + 1); + } + output->push_back(value); + } +} + } // namespace compiler } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h index d22974e9..8a7081f7 100644 --- a/src/google/protobuf/compiler/code_generator.h +++ b/src/google/protobuf/compiler/code_generator.h @@ -40,6 +40,8 @@ #include #include +#include +#include namespace google { namespace protobuf { @@ -105,6 +107,15 @@ class LIBPROTOC_EXPORT OutputDirectory { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OutputDirectory); }; +// Several code generators treat the parameter argument as holding a +// list of options separated by commas. This helper function parses +// a set of comma-delimited name/value pairs: e.g., +// "foo=bar,baz,qux=corge" +// parses to the pairs: +// ("foo", "bar"), ("baz", ""), ("qux", "corge") +extern void ParseGeneratorParameter(const string&, + vector >*); + } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc index 875cbef8..90e9172a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -95,24 +95,39 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { } printer->Print(vars, - "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n" "$dllexport$bool $classname$_IsValid(int value);\n" "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n" "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n" "\n"); - // The _Name and _Parse methods - printer->Print(vars, - "inline const ::std::string& $classname$_Name($classname$ value) {\n" - " return ::google::protobuf::internal::NameOfEnum(\n" - " $classname$_descriptor(), value);\n" - "}\n"); - printer->Print(vars, - "inline bool $classname$_Parse(\n" - " const ::std::string& name, $classname$* value) {\n" - " return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n" - " $classname$_descriptor(), name, value);\n" - "}\n"); + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print(vars, + "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n"); + // The _Name and _Parse methods + printer->Print(vars, + "inline const ::std::string& $classname$_Name($classname$ value) {\n" + " return ::google::protobuf::internal::NameOfEnum(\n" + " $classname$_descriptor(), value);\n" + "}\n"); + printer->Print(vars, + "inline bool $classname$_Parse(\n" + " const ::std::string& name, $classname$* value) {\n" + " return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n" + " $classname$_descriptor(), name, value);\n" + "}\n"); + } +} + +void EnumGenerator:: +GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print( + "template <>\n" + "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n" + " return $classname$_descriptor();\n" + "}\n", + "classname", ClassName(descriptor_, true)); + } } void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { @@ -128,24 +143,28 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { } printer->Print(vars, - "static inline const ::google::protobuf::EnumDescriptor*\n" - "$nested_name$_descriptor() {\n" - " return $classname$_descriptor();\n" - "}\n" "static inline bool $nested_name$_IsValid(int value) {\n" " return $classname$_IsValid(value);\n" "}\n" - "static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n" - " return $classname$_Name(value);\n" - "}\n" - "static inline bool $nested_name$_Parse(const ::std::string& name,\n" - " $nested_name$* value) {\n" - " return $classname$_Parse(name, value);\n" - "}\n" "static const $nested_name$ $nested_name$_MIN =\n" " $classname$_$nested_name$_MIN;\n" "static const $nested_name$ $nested_name$_MAX =\n" " $classname$_$nested_name$_MAX;\n"); + + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print(vars, + "static inline const ::google::protobuf::EnumDescriptor*\n" + "$nested_name$_descriptor() {\n" + " return $classname$_descriptor();\n" + "}\n" + "static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n" + " return $classname$_Name(value);\n" + "}\n" + "static inline bool $nested_name$_Parse(const ::std::string& name,\n" + " $nested_name$* value) {\n" + " return $classname$_Parse(name, value);\n" + "}\n"); + } } void EnumGenerator::GenerateDescriptorInitializer( @@ -168,11 +187,15 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) { map vars; vars["classname"] = classname_; + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print(vars, + "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n" + " protobuf_AssignDescriptorsOnce();\n" + " return $classname$_descriptor_;\n" + "}\n"); + } + printer->Print(vars, - "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n" - " protobuf_AssignDescriptorsOnce();\n" - " return $classname$_descriptor_;\n" - "}\n" "bool $classname$_IsValid(int value) {\n" " switch(value) {\n"); diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h index 9f2e5fee..58f7721e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum.h @@ -63,6 +63,10 @@ class EnumGenerator { // nested enums. void GenerateDefinition(io::Printer* printer); + // Generate specialization of GetEnumDescriptor(). + // Precondition: in ::google::protobuf namespace. + void GenerateGetEnumDescriptorSpecializations(io::Printer* printer); + // For enums nested within a message, generate code to import all the enum's // symbols (e.g. the enum type name, all its values, etc.) into the class's // namespace. This should be placed inside the class definition in the diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index b90eb372..7ca11c8c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include namespace google { @@ -43,24 +43,14 @@ namespace protobuf { namespace compiler { namespace cpp { -using internal::WireFormat; - namespace { -// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of -// repeat code between this and the other field types. void SetEnumVariables(const FieldDescriptor* descriptor, map* variables) { + SetCommonFieldVariables(descriptor, variables); const EnumValueDescriptor* default_value = descriptor->default_value_enum(); - - (*variables)["name"] = FieldName(descriptor); (*variables)["type"] = ClassName(descriptor->enum_type(), true); (*variables)["default"] = SimpleItoa(default_value->number()); - (*variables)["index"] = SimpleItoa(descriptor->index()); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["classname"] = ClassName(FieldScope(descriptor), false); - (*variables)["tag_size"] = SimpleItoa( - WireFormat::TagSize(descriptor->number(), descriptor->type())); } } // namespace @@ -83,8 +73,8 @@ GeneratePrivateMembers(io::Printer* printer) const { void EnumFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline $type$ $name$() const;\n" - "inline void set_$name$($type$ value);\n"); + "inline $type$ $name$() const$deprecation$;\n" + "inline void set_$name$($type$ value)$deprecation$;\n"); } void EnumFieldGenerator:: @@ -124,33 +114,37 @@ void EnumFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { printer->Print(variables_, "int value;\n" - "DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n" + "DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n" "if ($type$_IsValid(value)) {\n" - " set_$name$(static_cast< $type$ >(value));\n" - "} else {\n" - " mutable_unknown_fields()->AddVarint($number$, value);\n" + " set_$name$(static_cast< $type$ >(value));\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print(variables_, + "} else {\n" + " mutable_unknown_fields()->AddVarint($number$, value);\n"); + } + printer->Print(variables_, "}\n"); } void EnumFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::WriteEnum(" - "$number$, this->$name$(), output);\n"); + "::google::protobuf::internal::WireFormatLite::WriteEnum(\n" + " $number$, this->$name$(), output);\n"); } void EnumFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(" - "$number$, this->$name$(), target);\n"); + "target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n" + " $number$, this->$name$(), target);\n"); } void EnumFieldGenerator:: GenerateByteSize(io::Printer* printer) const { printer->Print(variables_, "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormat::EnumSize(this->$name$());\n"); + " ::google::protobuf::internal::WireFormatLite::EnumSize(this->$name$());\n"); } // =================================================================== @@ -167,8 +161,7 @@ void RepeatedEnumFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, "::google::protobuf::RepeatedField $name$_;\n"); - if (descriptor_->options().packed() && - descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) { printer->Print(variables_, "mutable int _$name$_cached_byte_size_;\n"); } @@ -177,11 +170,11 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedEnumFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline const ::google::protobuf::RepeatedField& $name$() const;\n" - "inline ::google::protobuf::RepeatedField* mutable_$name$();\n" - "inline $type$ $name$(int index) const;\n" - "inline void set_$name$(int index, $type$ value);\n" - "inline void add_$name$($type$ value);\n"); + "inline const ::google::protobuf::RepeatedField& $name$() const$deprecation$;\n" + "inline ::google::protobuf::RepeatedField* mutable_$name$()$deprecation$;\n" + "inline $type$ $name$(int index) const$deprecation$;\n" + "inline void set_$name$(int index, $type$ value)$deprecation$;\n" + "inline void add_$name$($type$ value)$deprecation$;\n"); } void RepeatedEnumFieldGenerator:: @@ -238,7 +231,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { "input->PushLimit(length);\n" "while (input->BytesUntilLimit() > 0) {\n" " int value;\n" - " DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n" + " DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n" " if ($type$_IsValid(value)) {\n" " add_$name$(static_cast< $type$ >(value));\n" " }\n" @@ -247,11 +240,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { } else { printer->Print(variables_, "int value;\n" - "DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n" + "DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n" "if ($type$_IsValid(value)) {\n" - " add_$name$(static_cast< $type$ >(value));\n" - "} else {\n" - " mutable_unknown_fields()->AddVarint($number$, value);\n" + " add_$name$(static_cast< $type$ >(value));\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print(variables_, + "} else {\n" + " mutable_unknown_fields()->AddVarint($number$, value);\n"); + } + printer->Print(variables_, "}\n"); } } @@ -262,10 +259,10 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { // Write the tag and the size. printer->Print(variables_, "if (this->$name$_size() > 0) {\n" - " ::google::protobuf::internal::WireFormat::WriteTag(" - "$number$, " - "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, " - "output);\n" + " ::google::protobuf::internal::WireFormatLite::WriteTag(\n" + " $number$,\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" + " output);\n" " output->WriteVarint32(_$name$_cached_byte_size_);\n" "}\n"); } @@ -273,12 +270,12 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { "for (int i = 0; i < this->$name$_size(); i++) {\n"); if (descriptor_->options().packed()) { printer->Print(variables_, - " ::google::protobuf::internal::WireFormat::WriteEnumNoTag(" - "this->$name$(i), output);\n"); + " ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n" + " this->$name$(i), output);\n"); } else { printer->Print(variables_, - " ::google::protobuf::internal::WireFormat::WriteEnum(" - "$number$, this->$name$(i), output);\n"); + " ::google::protobuf::internal::WireFormatLite::WriteEnum(\n" + " $number$, this->$name$(i), output);\n"); } printer->Print("}\n"); } @@ -289,24 +286,24 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { // Write the tag and the size. printer->Print(variables_, "if (this->$name$_size() > 0) {\n" - " target = ::google::protobuf::internal::WireFormat::WriteTagToArray(" - "$number$, " - "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, " - "target);\n" + " target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n" + " $number$,\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" + " target);\n" " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(" - "_$name$_cached_byte_size_, target);\n" + " _$name$_cached_byte_size_, target);\n" "}\n"); } printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n"); if (descriptor_->options().packed()) { printer->Print(variables_, - " target = ::google::protobuf::internal::WireFormat::WriteEnumNoTagToArray(" - "this->$name$(i), target);\n"); + " target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n" + " this->$name$(i), target);\n"); } else { printer->Print(variables_, - " target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(" - "$number$, this->$name$(i), target);\n"); + " target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n" + " $number$, this->$name$(i), target);\n"); } printer->Print("}\n"); } @@ -319,15 +316,15 @@ GenerateByteSize(io::Printer* printer) const { printer->Indent(); printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n" - " data_size += ::google::protobuf::internal::WireFormat::EnumSize(\n" + " data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n" " this->$name$(i));\n" "}\n"); if (descriptor_->options().packed()) { printer->Print(variables_, "if (data_size > 0) {\n" - " total_size += $tag_size$ + " - "::google::protobuf::internal::WireFormat::Int32Size(data_size);\n" + " total_size += $tag_size$ +\n" + " ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n" "}\n" "_$name$_cached_byte_size_ = data_size;\n" "total_size += data_size;\n"); diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc index cd4806ba..7208ed3a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_extension.cc +++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc @@ -133,6 +133,7 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) { vars["global_name"] = global_name; printer->Print(vars, "const ::std::string $global_name$_default($default$);\n"); + // Update the default to refer to the string global. vars["default"] = global_name + "_default"; } diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc index 47daac7a..c546e964 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_field.cc @@ -33,18 +33,37 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include +#include #include #include #include #include #include +#include #include +#include namespace google { namespace protobuf { namespace compiler { namespace cpp { +using internal::WireFormat; + +void SetCommonFieldVariables(const FieldDescriptor* descriptor, + map* variables) { + (*variables)["name"] = FieldName(descriptor); + (*variables)["index"] = SimpleItoa(descriptor->index()); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["classname"] = ClassName(FieldScope(descriptor), false); + (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type()); + + (*variables)["tag_size"] = SimpleItoa( + WireFormat::TagSize(descriptor->number(), descriptor->type())); + (*variables)["deprecation"] = descriptor->options().deprecated() + ? " DEPRECATED_PROTOBUF_FIELD" : ""; +} + FieldGenerator::~FieldGenerator() {} FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h index 7e7c7f83..00ec2c7c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_field.h @@ -35,6 +35,9 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__ +#include +#include + #include #include @@ -49,6 +52,13 @@ namespace protobuf { namespace compiler { namespace cpp { +// Helper function: set variables in the map that are the same for all +// field code generators. +// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size', +// 'deprecation']. +void SetCommonFieldVariables(const FieldDescriptor* descriptor, + map* variables); + class FieldGenerator { public: FieldGenerator() {} diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index f056ed57..51859bb3 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -125,13 +125,18 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { // OK, it's now safe to #include other files. printer->Print( - "#include \n" + "#include \n" "#include \n" "#include \n"); - if (file_->service_count() > 0) { + if (HasDescriptorMethods(file_)) { printer->Print( - "#include \n"); + "#include \n"); + + if (file_->service_count() > 0) { + printer->Print( + "#include \n"); + } } for (int i = 0; i < file_->dependency_count(); i++) { @@ -193,19 +198,21 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { printer->Print(kThickSeparator); printer->Print("\n"); - // Generate service definitions. - for (int i = 0; i < file_->service_count(); i++) { - if (i > 0) { - printer->Print("\n"); - printer->Print(kThinSeparator); - printer->Print("\n"); + if (HasDescriptorMethods(file_)) { + // Generate service definitions. + for (int i = 0; i < file_->service_count(); i++) { + if (i > 0) { + printer->Print("\n"); + printer->Print(kThinSeparator); + printer->Print("\n"); + } + service_generators_[i]->GenerateDeclarations(printer); } - service_generators_[i]->GenerateDeclarations(printer); - } - printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); + printer->Print("\n"); + printer->Print(kThickSeparator); + printer->Print("\n"); + } // Declare extension identifiers. for (int i = 0; i < file_->extension_count(); i++) { @@ -228,6 +235,30 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { // Close up namespace. GenerateNamespaceClosers(printer); + // Emit GetEnumDescriptor specializations into google::protobuf namespace: + if (HasDescriptorMethods(file_)) { + // The SWIG conditional is to avoid a null-pointer dereference + // (bug 1984964) in swig-1.3.21 resulting from the following syntax: + // namespace X { void Y(); } + // which appears in GetEnumDescriptor() specializations. + printer->Print( + "\n" + "#ifndef SWIG\n" + "namespace google {\nnamespace protobuf {\n" + "\n"); + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } + printer->Print( + "\n" + "} // namespace google\n} // namespace protobuf\n" + "#endif // SWIG\n" + "\n"); + } + printer->Print( "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n", "filename_identifier", filename_identifier); @@ -237,40 +268,52 @@ void FileGenerator::GenerateSource(io::Printer* printer) { printer->Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" "\n" + // The generated code calls accessors that might be deprecated. We don't + // want the compiler to warn in generated code. + "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n" "#include \"$basename$.pb.h\"\n" + "#include \n" - "#include \n" "#include \n" - "#include \n" - "#include \n", + "#include \n", "basename", StripProto(file_->name())); + if (HasDescriptorMethods(file_)) { + printer->Print( + "#include \n" + "#include \n" + "#include \n"); + } + GenerateNamespaceOpeners(printer); - printer->Print( - "\n" - "namespace {\n" - "\n"); - for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateDescriptorDeclarations(printer); - } - for (int i = 0; i < file_->enum_type_count(); i++) { + if (HasDescriptorMethods(file_)) { printer->Print( - "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n", - "name", ClassName(file_->enum_type(i), false)); - } - for (int i = 0; i < file_->service_count(); i++) { + "\n" + "namespace {\n" + "\n"); + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateDescriptorDeclarations(printer); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + printer->Print( + "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n", + "name", ClassName(file_->enum_type(i), false)); + } + for (int i = 0; i < file_->service_count(); i++) { + printer->Print( + "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n", + "name", file_->service(i)->name()); + } + printer->Print( - "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n", - "name", file_->service(i)->name()); + "\n" + "} // namespace\n" + "\n"); } - printer->Print( - "\n" - "} // namespace\n" - "\n"); - - // Define our externally-visible BuildDescriptors() function. + // Define our externally-visible BuildDescriptors() function. (For the lite + // library, all this does is initialize default instances.) GenerateBuildDescriptors(printer); // Generate enums. @@ -286,12 +329,14 @@ void FileGenerator::GenerateSource(io::Printer* printer) { message_generators_[i]->GenerateClassMethods(printer); } - // Generate services. - for (int i = 0; i < file_->service_count(); i++) { - if (i == 0) printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); - service_generators_[i]->GenerateImplementation(printer); + if (HasDescriptorMethods(file_)) { + // Generate services. + for (int i = 0; i < file_->service_count(); i++) { + if (i == 0) printer->Print("\n"); + printer->Print(kThickSeparator); + printer->Print("\n"); + service_generators_[i]->GenerateImplementation(printer); + } } // Define extensions. @@ -317,80 +362,84 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { // anyone calls descriptor() or GetReflection() on one of the types defined // in the file. - printer->Print( - "\n" - "void $assigndescriptorsname$() {\n", - "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name())); - printer->Indent(); - - // Make sure the file has found its way into the pool. If a descriptor - // is requested *during* static init then AddDescriptors() may not have - // been called yet, so we call it manually. Note that it's fine if - // AddDescriptors() is called multiple times. - printer->Print( - "$adddescriptorsname$();\n", - "adddescriptorsname", GlobalAddDescriptorsName(file_->name())); + // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors() + // and we only use AddDescriptors() to allocate default instances. + if (HasDescriptorMethods(file_)) { + printer->Print( + "\n" + "void $assigndescriptorsname$() {\n", + "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name())); + printer->Indent(); + + // Make sure the file has found its way into the pool. If a descriptor + // is requested *during* static init then AddDescriptors() may not have + // been called yet, so we call it manually. Note that it's fine if + // AddDescriptors() is called multiple times. + printer->Print( + "$adddescriptorsname$();\n", + "adddescriptorsname", GlobalAddDescriptorsName(file_->name())); - // Get the file's descriptor from the pool. - printer->Print( - "const ::google::protobuf::FileDescriptor* file =\n" - " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n" - " \"$filename$\");\n" - // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file" - // being unused when compiling an empty .proto file. - "GOOGLE_CHECK(file != NULL);\n", - "filename", file_->name()); - - // Go through all the stuff defined in this file and generated code to - // assign the global descriptor pointers based on the file descriptor. - for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateDescriptorInitializer(printer, i); - } - for (int i = 0; i < file_->enum_type_count(); i++) { - enum_generators_[i]->GenerateDescriptorInitializer(printer, i); - } - for (int i = 0; i < file_->service_count(); i++) { - service_generators_[i]->GenerateDescriptorInitializer(printer, i); - } + // Get the file's descriptor from the pool. + printer->Print( + "const ::google::protobuf::FileDescriptor* file =\n" + " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n" + " \"$filename$\");\n" + // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file" + // being unused when compiling an empty .proto file. + "GOOGLE_CHECK(file != NULL);\n", + "filename", file_->name()); + + // Go through all the stuff defined in this file and generated code to + // assign the global descriptor pointers based on the file descriptor. + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateDescriptorInitializer(printer, i); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_[i]->GenerateDescriptorInitializer(printer, i); + } + for (int i = 0; i < file_->service_count(); i++) { + service_generators_[i]->GenerateDescriptorInitializer(printer, i); + } - printer->Outdent(); - printer->Print( - "}\n" - "\n"); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); - // ----------------------------------------------------------------- + // --------------------------------------------------------------- - // protobuf_AssignDescriptorsOnce(): The first time it is called, calls - // AssignDescriptors(). All later times, waits for the first call to - // complete and then returns. - printer->Print( - "namespace {\n" - "\n" - "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n" - "inline void protobuf_AssignDescriptorsOnce() {\n" - " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n" - " &$assigndescriptorsname$);\n" - "}\n" - "\n", - "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name())); + // protobuf_AssignDescriptorsOnce(): The first time it is called, calls + // AssignDescriptors(). All later times, waits for the first call to + // complete and then returns. + printer->Print( + "namespace {\n" + "\n" + "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n" + "inline void protobuf_AssignDescriptorsOnce() {\n" + " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n" + " &$assigndescriptorsname$);\n" + "}\n" + "\n", + "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name())); + + // protobuf_RegisterTypes(): Calls + // MessageFactory::InternalRegisterGeneratedType() for each message type. + printer->Print( + "void protobuf_RegisterTypes(const ::std::string&) {\n" + " protobuf_AssignDescriptorsOnce();\n"); + printer->Indent(); - // protobuf_RegisterTypes(): Calls - // MessageFactory::InternalRegisterGeneratedType() for each message type. - printer->Print( - "void protobuf_RegisterTypes() {\n" - " protobuf_AssignDescriptorsOnce();\n"); - printer->Indent(); + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateTypeRegistrations(printer); + } - for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateTypeRegistrations(printer); + printer->Outdent(); + printer->Print( + "}\n" + "\n" + "} // namespace\n"); } - printer->Outdent(); - printer->Print( - "}\n" - "\n" - "} // namespace\n"); - // ----------------------------------------------------------------- // ShutdownFile(): Deletes descriptors, default instances, etc. on shutdown. @@ -442,32 +491,34 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { "name", GlobalAddDescriptorsName(dependency->name())); } - // Embed the descriptor. We simply serialize the entire FileDescriptorProto - // and embed it as a string literal, which is parsed and built into real - // descriptors at initialization time. - FileDescriptorProto file_proto; - file_->CopyTo(&file_proto); - string file_data; - file_proto.SerializeToString(&file_data); + if (HasDescriptorMethods(file_)) { + // Embed the descriptor. We simply serialize the entire FileDescriptorProto + // and embed it as a string literal, which is parsed and built into real + // descriptors at initialization time. + FileDescriptorProto file_proto; + file_->CopyTo(&file_proto); + string file_data; + file_proto.SerializeToString(&file_data); - printer->Print( - "::google::protobuf::DescriptorPool::InternalAddGeneratedFile("); + printer->Print( + "::google::protobuf::DescriptorPool::InternalAddGeneratedFile("); - // Only write 40 bytes per line. - static const int kBytesPerLine = 40; - for (int i = 0; i < file_data.size(); i += kBytesPerLine) { - printer->Print("\n \"$data$\"", - "data", CEscape(file_data.substr(i, kBytesPerLine))); - } - printer->Print( - ", $size$);\n", - "size", SimpleItoa(file_data.size())); + // Only write 40 bytes per line. + static const int kBytesPerLine = 40; + for (int i = 0; i < file_data.size(); i += kBytesPerLine) { + printer->Print("\n \"$data$\"", + "data", CEscape(file_data.substr(i, kBytesPerLine))); + } + printer->Print( + ", $size$);\n", + "size", SimpleItoa(file_data.size())); - // Call MessageFactory::InternalRegisterGeneratedFile(). - printer->Print( - "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n" - " \"$filename$\", &protobuf_RegisterTypes);\n", - "filename", file_->name()); + // Call MessageFactory::InternalRegisterGeneratedFile(). + printer->Print( + "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n" + " \"$filename$\", &protobuf_RegisterTypes);\n", + "filename", file_->name()); + } // Allocate and initialize default instances. This can't be done lazily // since default instances are returned by simple accessors and are used with diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc index f3515255..d67d3504 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.cc +++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc @@ -42,39 +42,12 @@ #include #include #include -#include namespace google { namespace protobuf { namespace compiler { namespace cpp { -namespace { - -// Parses a set of comma-delimited name/value pairs, e.g.: -// "foo=bar,baz,qux=corge" -// parses to the pairs: -// ("foo", "bar"), ("baz", ""), ("qux", "corge") -void ParseOptions(const string& text, vector >* output) { - vector parts; - SplitStringUsing(text, ",", &parts); - - for (int i = 0; i < parts.size(); i++) { - string::size_type equals_pos = parts[i].find_first_of('='); - pair value; - if (equals_pos == string::npos) { - value.first = parts[i]; - value.second = ""; - } else { - value.first = parts[i].substr(0, equals_pos); - value.second = parts[i].substr(equals_pos + 1); - } - output->push_back(value); - } -} - -} // namespace - CppGenerator::CppGenerator() {} CppGenerator::~CppGenerator() {} @@ -83,7 +56,7 @@ bool CppGenerator::Generate(const FileDescriptor* file, OutputDirectory* output_directory, string* error) const { vector > options; - ParseOptions(parameter, &options); + ParseGeneratorParameter(parameter, &options); // ----------------------------------------------------------------- // parse generator options diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 595aeaeb..723a8b45 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -152,7 +152,18 @@ string FieldName(const FieldDescriptor* field) { string FieldConstantName(const FieldDescriptor *field) { string field_name = UnderscoresToCamelCase(field->name(), true); - return "k" + field_name + "FieldNumber"; + string result = "k" + field_name + "FieldNumber"; + + if (!field->is_extension() && + field->containing_type()->FindFieldByCamelcaseName( + field->camelcase_name()) != field) { + // This field's camelcase name is not unique. As a hack, add the field + // number to the constant name. This makes the constant rather useless, + // but what can we do? + result += "_" + SimpleItoa(field->number()); + } + + return result; } string StripProto(const string& filename) { diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index 55fd7e29..83e12501 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -37,6 +37,7 @@ #include #include +#include namespace google { namespace protobuf { @@ -105,6 +106,34 @@ string GlobalAssignDescriptorsName(const string& filename); // Return the name of the ShutdownFile() function for a given file. string GlobalShutdownFileName(const string& filename); +// Do message classes in this file keep track of unknown fields? +inline const bool HasUnknownFields(const FileDescriptor *file) { + return file->options().optimize_for() != FileOptions::LITE_RUNTIME; +} + +// Does this file have generated parsing, serialization, and other +// standard methods for which reflection-based fallback implementations exist? +inline const bool HasGeneratedMethods(const FileDescriptor *file) { + return file->options().optimize_for() != FileOptions::CODE_SIZE; +} + +// Do message classes in this file have descriptor and refelction methods? +inline const bool HasDescriptorMethods(const FileDescriptor *file) { + return file->options().optimize_for() != FileOptions::LITE_RUNTIME; +} + +// Should string fields in this file verify that their contents are UTF-8? +inline const bool HasUtf8Verification(const FileDescriptor* file) { + return file->options().optimize_for() != FileOptions::LITE_RUNTIME; +} + +// Should we generate a separate, super-optimized code path for serializing to +// flat arrays? We don't do this in Lite mode because we'd rather reduce code +// size. +inline const bool HasFastArraySerialization(const FileDescriptor* file) { + return file->options().optimize_for() == FileOptions::SPEED; +} + } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 9852ee91..ae243dd9 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -34,14 +34,17 @@ #include #include +#include +#include #include +#include #include #include #include #include #include #include -#include +#include #include namespace google { @@ -50,6 +53,7 @@ namespace compiler { namespace cpp { using internal::WireFormat; +using internal::WireFormatLite; namespace { @@ -195,6 +199,16 @@ GenerateEnumDefinitions(io::Printer* printer) { } } +void MessageGenerator:: +GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } +} + void MessageGenerator:: GenerateFieldAccessorDeclarations(io::Printer* printer) { for (int i = 0; i < descriptor_->field_count(); i++) { @@ -203,17 +217,16 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { PrintFieldComment(printer, field); map vars; - vars["name"] = FieldName(field); + SetCommonFieldVariables(field, &vars); vars["constant_name"] = FieldConstantName(field); - vars["number"] = SimpleItoa(field->number()); if (field->is_repeated()) { - printer->Print(vars, "inline int $name$_size() const;\n"); + printer->Print(vars, "inline int $name$_size() const$deprecation$;\n"); } else { - printer->Print(vars, "inline bool has_$name$() const;\n"); + printer->Print(vars, "inline bool has_$name$() const$deprecation$;\n"); } - printer->Print(vars, "inline void clear_$name$();\n"); + printer->Print(vars, "inline void clear_$name$()$deprecation$;\n"); printer->Print(vars, "static const int $constant_name$ = $number$;\n"); // Generate type-specific accessor declarations. @@ -241,9 +254,7 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { PrintFieldComment(printer, field); map vars; - vars["name"] = FieldName(field); - vars["index"] = SimpleItoa(field->index()); - vars["classname"] = classname_; + SetCommonFieldVariables(field, &vars); // Generate has_$name$() or $name$_size(). if (field->is_repeated()) { @@ -297,9 +308,11 @@ GenerateClassDefinition(io::Printer* printer) { } else { vars["dllexport"] = dllexport_decl_ + " "; } + vars["superclass"] = HasDescriptorMethods(descriptor_->file()) ? + "Message" : "MessageLite"; printer->Print(vars, - "class $dllexport$$classname$ : public ::google::protobuf::Message {\n" + "class $dllexport$$classname$ : public ::google::protobuf::$superclass$ {\n" " public:\n"); printer->Indent(); @@ -313,16 +326,28 @@ GenerateClassDefinition(io::Printer* printer) { " CopyFrom(from);\n" " return *this;\n" "}\n" - "\n" - "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n" - " return _unknown_fields_;\n" - "}\n" - "\n" - "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n" - " return &_unknown_fields_;\n" - "}\n" - "\n" - "static const ::google::protobuf::Descriptor* descriptor();\n" + "\n"); + + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n" + " return _unknown_fields_;\n" + "}\n" + "\n" + "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n" + " return &_unknown_fields_;\n" + "}\n" + "\n"); + } + + // Only generate this member if it's not disabled. + if (HasDescriptorMethods(descriptor_->file()) && + !descriptor_->options().no_standard_descriptor_accessor()) { + printer->Print(vars, + "static const ::google::protobuf::Descriptor* descriptor();\n"); + } + + printer->Print(vars, "static const $classname$& default_instance();\n" "void Swap($classname$* other);\n" "\n" @@ -330,28 +355,29 @@ GenerateClassDefinition(io::Printer* printer) { "\n" "$classname$* New() const;\n"); - if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + if (HasGeneratedMethods(descriptor_->file())) { + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print(vars, + "void CopyFrom(const ::google::protobuf::Message& from);\n" + "void MergeFrom(const ::google::protobuf::Message& from);\n"); + } else { + printer->Print(vars, + "void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);\n"); + } + printer->Print(vars, - "void CopyFrom(const ::google::protobuf::Message& from);\n" - "void MergeFrom(const ::google::protobuf::Message& from);\n" "void CopyFrom(const $classname$& from);\n" "void MergeFrom(const $classname$& from);\n" "void Clear();\n" - "bool IsInitialized() const;\n"); - - if (!descriptor_->options().message_set_wire_format()) { - // For message_set_wire_format, we don't generate parsing or - // serialization code even if optimize_for = SPEED, since MessageSet - // encoding is somewhat more complicated than normal extension encoding - // and we'd like to avoid having to implement it in multiple places. - // WireFormat's implementation is probably good enough. - printer->Print(vars, - "\n" - "int ByteSize() const;\n" - "bool MergePartialFromCodedStream(\n" - " ::google::protobuf::io::CodedInputStream* input);\n" - "void SerializeWithCachedSizes(\n" - " ::google::protobuf::io::CodedOutputStream* output) const;\n" + "bool IsInitialized() const;\n" + "\n" + "int ByteSize() const;\n" + "bool MergePartialFromCodedStream(\n" + " ::google::protobuf::io::CodedInputStream* input);\n" + "void SerializeWithCachedSizes(\n" + " ::google::protobuf::io::CodedOutputStream* output) const;\n"); + if (HasFastArraySerialization(descriptor_->file())) { + printer->Print( "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n"); } } @@ -363,10 +389,19 @@ GenerateClassDefinition(io::Printer* printer) { "void SharedDtor();\n" "void SetCachedSize(int size) const { _cached_size_ = size; }\n" "public:\n" - "\n" - "const ::google::protobuf::Descriptor* GetDescriptor() const;\n" - "const ::google::protobuf::Reflection* GetReflection() const;\n" - "\n" + "\n"); + + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print( + "::google::protobuf::Metadata GetMetadata() const;\n" + "\n"); + } else { + printer->Print( + "::std::string GetTypeName() const;\n" + "\n"); + } + + printer->Print( "// nested types ----------------------------------------------------\n" "\n"); @@ -411,9 +446,13 @@ GenerateClassDefinition(io::Printer* printer) { "::google::protobuf::internal::ExtensionSet _extensions_;\n"); } + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + "::google::protobuf::UnknownFieldSet _unknown_fields_;\n"); + } + // TODO(kenton): Make _cached_size_ an atomic when C++ supports it. printer->Print( - "::google::protobuf::UnknownFieldSet _unknown_fields_;\n" "mutable int _cached_size_;\n" "\n"); for (int i = 0; i < descriptor_->field_count(); i++) { @@ -431,7 +470,8 @@ GenerateClassDefinition(io::Printer* printer) { GlobalAddDescriptorsName(descriptor_->file()->name())); printer->Print( "friend void $assigndescriptorsname$();\n" - "friend void $shutdownfilename$();\n", + "friend void $shutdownfilename$();\n" + "\n", "assigndescriptorsname", GlobalAssignDescriptorsName(descriptor_->file()->name()), "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name())); @@ -605,10 +645,15 @@ GenerateDefaultInstanceInitializer(io::Printer* printer) { void MessageGenerator:: GenerateShutdownCode(io::Printer* printer) { printer->Print( - "delete $classname$::default_instance_;\n" - "delete $classname$_reflection_;\n", + "delete $classname$::default_instance_;\n", "classname", classname_); + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print( + "delete $classname$_reflection_;\n", + "classname", classname_); + } + // Handle nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { nested_generators_[i]->GenerateShutdownCode(printer); @@ -655,29 +700,24 @@ GenerateClassMethods(io::Printer* printer) { GenerateStructors(printer); printer->Print("\n"); - if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + if (HasGeneratedMethods(descriptor_->file())) { GenerateClear(printer); printer->Print("\n"); - if (!descriptor_->options().message_set_wire_format()) { - // For message_set_wire_format, we don't generate parsing or - // serialization code even if optimize_for = SPEED, since MessageSet - // encoding is somewhat more complicated than normal extension encoding - // and we'd like to avoid having to implement it in multiple places. - // WireFormat's implementation is probably good enough. - GenerateMergeFromCodedStream(printer); - printer->Print("\n"); + GenerateMergeFromCodedStream(printer); + printer->Print("\n"); - GenerateSerializeWithCachedSizes(printer); - printer->Print("\n"); + GenerateSerializeWithCachedSizes(printer); + printer->Print("\n"); + if (HasFastArraySerialization(descriptor_->file())) { GenerateSerializeWithCachedSizesToArray(printer); printer->Print("\n"); - - GenerateByteSize(printer); - printer->Print("\n"); } + GenerateByteSize(printer); + printer->Print("\n"); + GenerateMergeFrom(printer); printer->Print("\n"); @@ -691,16 +731,26 @@ GenerateClassMethods(io::Printer* printer) { GenerateSwap(printer); printer->Print("\n"); - printer->Print( - "const ::google::protobuf::Descriptor* $classname$::GetDescriptor() const {\n" - " return descriptor();\n" - "}\n" - "\n" - "const ::google::protobuf::Reflection* $classname$::GetReflection() const {\n" - " protobuf_AssignDescriptorsOnce();\n" - " return $classname$_reflection_;\n" - "}\n", - "classname", classname_); + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print( + "::google::protobuf::Metadata $classname$::GetMetadata() const {\n" + " protobuf_AssignDescriptorsOnce();\n" + " ::google::protobuf::Metadata metadata;\n" + " metadata.descriptor = $classname$_descriptor_;\n" + " metadata.reflection = $classname$_reflection_;\n" + " return metadata;\n" + "}\n" + "\n", + "classname", classname_); + } else { + printer->Print( + "::std::string $classname$::GetTypeName() const {\n" + " return \"$type_name$\";\n" + "}\n" + "\n", + "classname", classname_, + "type_name", descriptor_->full_name()); + } } void MessageGenerator:: @@ -723,18 +773,6 @@ GenerateOffsets(io::Printer* printer) { printer->Print("};\n"); } -void MessageGenerator:: -GenerateInitializerList(io::Printer* printer) { - printer->Indent(); - printer->Indent(); - - printer->Print( - "::google::protobuf::Message()"); - - printer->Outdent(); - printer->Outdent(); -} - void MessageGenerator:: GenerateSharedConstructorCode(io::Printer* printer) { printer->Print( @@ -797,17 +835,14 @@ void MessageGenerator:: GenerateStructors(io::Printer* printer) { // Generate the default constructor. printer->Print( - "$classname$::$classname$()\n" - " : ", - "classname", classname_); - GenerateInitializerList(printer); - printer->Print(" {\n" + "$classname$::$classname$() {\n" " SharedCtor();\n" - "}\n"); + "}\n", + "classname", classname_); printer->Print( "\n" - "void $classname$::InitAsDefaultInstance() {", + "void $classname$::InitAsDefaultInstance() {\n", "classname", classname_); // The default instance needs all of its embedded message pointers @@ -833,15 +868,12 @@ GenerateStructors(io::Printer* printer) { // Generate the copy constructor. printer->Print( - "$classname$::$classname$(const $classname$& from)\n" - " : ", - "classname", classname_); - GenerateInitializerList(printer); - printer->Print(" {\n" + "$classname$::$classname$(const $classname$& from) {\n" " SharedCtor();\n" " MergeFrom(from);\n" "}\n" - "\n"); + "\n", + "classname", classname_); // Generate the shared constructor code. GenerateSharedConstructorCode(printer); @@ -857,12 +889,21 @@ GenerateStructors(io::Printer* printer) { // Generate the shared destructor code. GenerateSharedDestructorCode(printer); + // Only generate this member if it's not disabled. + if (HasDescriptorMethods(descriptor_->file()) && + !descriptor_->options().no_standard_descriptor_accessor()) { + printer->Print( + "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n" + " protobuf_AssignDescriptorsOnce();\n" + " return $classname$_descriptor_;\n" + "}\n" + "\n", + "classname", classname_, + "adddescriptorsname", + GlobalAddDescriptorsName(descriptor_->file()->name())); + } + printer->Print( - "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n" - " protobuf_AssignDescriptorsOnce();\n" - " return $classname$_descriptor_;\n" - "}\n" - "\n" "const $classname$& $classname$::default_instance() {\n" " if (default_instance_ == NULL) $adddescriptorsname$();" " return *default_instance_;\n" @@ -951,8 +992,12 @@ GenerateClear(io::Printer* printer) { } printer->Print( - "::memset(_has_bits_, 0, sizeof(_has_bits_));\n" - "mutable_unknown_fields()->Clear();\n"); + "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); + + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + "mutable_unknown_fields()->Clear();\n"); + } printer->Outdent(); printer->Print("}\n"); @@ -967,7 +1012,7 @@ GenerateSwap(io::Printer* printer) { printer->Print("if (other != this) {\n"); printer->Indent(); - if ( descriptor_->file()->options().optimize_for() == FileOptions::SPEED ) { + if (HasGeneratedMethods(descriptor_->file())) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); field_generators_.get(field).GenerateSwappingCode(printer); @@ -978,7 +1023,9 @@ GenerateSwap(io::Printer* printer) { "i", SimpleItoa(i)); } - printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n"); + } printer->Print("std::swap(_cached_size_, other->_cached_size_);\n"); if (descriptor_->extension_range_count() > 0) { printer->Print("_extensions_.Swap(&other->_extensions_);\n"); @@ -987,7 +1034,6 @@ GenerateSwap(io::Printer* printer) { printer->Print("GetReflection()->Swap(this, other);"); } - printer->Outdent(); printer->Print("}\n"); printer->Outdent(); @@ -996,31 +1042,42 @@ GenerateSwap(io::Printer* printer) { void MessageGenerator:: GenerateMergeFrom(io::Printer* printer) { - // Generate the generalized MergeFrom (aka that which takes in the Message - // base class as a parameter). - printer->Print( - "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n" - " GOOGLE_CHECK_NE(&from, this);\n", - "classname", classname_); - printer->Indent(); + if (HasDescriptorMethods(descriptor_->file())) { + // Generate the generalized MergeFrom (aka that which takes in the Message + // base class as a parameter). + printer->Print( + "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n" + " GOOGLE_CHECK_NE(&from, this);\n", + "classname", classname_); + printer->Indent(); - // Cast the message to the proper type. If we find that the message is - // *not* of the proper type, we can still call Merge via the reflection - // system, as the GOOGLE_CHECK above ensured that we have the same descriptor - // for each message. - printer->Print( - "const $classname$* source =\n" - " ::google::protobuf::internal::dynamic_cast_if_available(\n" - " &from);\n" - "if (source == NULL) {\n" - " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n" - "} else {\n" - " MergeFrom(*source);\n" - "}\n", - "classname", classname_); + // Cast the message to the proper type. If we find that the message is + // *not* of the proper type, we can still call Merge via the reflection + // system, as the GOOGLE_CHECK above ensured that we have the same descriptor + // for each message. + printer->Print( + "const $classname$* source =\n" + " ::google::protobuf::internal::dynamic_cast_if_available(\n" + " &from);\n" + "if (source == NULL) {\n" + " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n" + "} else {\n" + " MergeFrom(*source);\n" + "}\n", + "classname", classname_); - printer->Outdent(); - printer->Print("}\n\n"); + printer->Outdent(); + printer->Print("}\n\n"); + } else { + // Generate CheckTypeAndMergeFrom(). + printer->Print( + "void $classname$::CheckTypeAndMergeFrom(\n" + " const ::google::protobuf::MessageLite& from) {\n" + " MergeFrom(*::google::protobuf::down_cast(&from));\n" + "}\n" + "\n", + "classname", classname_); + } // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast. printer->Print( @@ -1082,8 +1139,10 @@ GenerateMergeFrom(io::Printer* printer) { printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); } - printer->Print( - "mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + "mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"); + } printer->Outdent(); printer->Print("}\n"); @@ -1091,20 +1150,22 @@ GenerateMergeFrom(io::Printer* printer) { void MessageGenerator:: GenerateCopyFrom(io::Printer* printer) { - // Generate the generalized CopyFrom (aka that which takes in the Message - // base class as a parameter). - printer->Print( - "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n", - "classname", classname_); - printer->Indent(); + if (HasDescriptorMethods(descriptor_->file())) { + // Generate the generalized CopyFrom (aka that which takes in the Message + // base class as a parameter). + printer->Print( + "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n", + "classname", classname_); + printer->Indent(); - printer->Print( - "if (&from == this) return;\n" - "Clear();\n" - "MergeFrom(from);\n"); + printer->Print( + "if (&from == this) return;\n" + "Clear();\n" + "MergeFrom(from);\n"); - printer->Outdent(); - printer->Print("}\n\n"); + printer->Outdent(); + printer->Print("}\n\n"); + } // Generate the class-specific CopyFrom. printer->Print( @@ -1123,6 +1184,18 @@ GenerateCopyFrom(io::Printer* printer) { void MessageGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "bool $classname$::MergePartialFromCodedStream(\n" + " ::google::protobuf::io::CodedInputStream* input) {\n" + " return _extensions_.ParseMessageSet(input, default_instance_,\n" + " mutable_unknown_fields());\n" + "}\n", + "classname", classname_); + return; + } + printer->Print( "bool $classname$::MergePartialFromCodedStream(\n" " ::google::protobuf::io::CodedInputStream* input) {\n" @@ -1144,7 +1217,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // creates a jump table that is 8x larger and sparser, and meanwhile the // if()s are highly predictable. printer->Print( - "switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {\n"); + "switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {\n"); printer->Indent(); @@ -1158,8 +1231,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Print( "case $number$: {\n" - " if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=\n" - " ::google::protobuf::internal::WireFormat::WIRETYPE_$wiretype$) {\n" + " if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_$wiretype$) {\n" " goto handle_uninterpreted;\n" " }\n", "number", SimpleItoa(field->number()), @@ -1214,8 +1287,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // Is this an end-group tag? If so, this must be the end of the message. printer->Print( - "if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==\n" - " ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {\n" + "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n" " return true;\n" "}\n"); @@ -1228,10 +1301,10 @@ GenerateMergeFromCodedStream(io::Printer* printer) { descriptor_->extension_range(i); if (i > 0) printer->Print(" ||\n "); - uint32 start_tag = WireFormat::MakeTag( - range->start, static_cast(0)); - uint32 end_tag = WireFormat::MakeTag( - range->end, static_cast(0)); + uint32 start_tag = WireFormatLite::MakeTag( + range->start, static_cast(0)); + uint32 end_tag = WireFormatLite::MakeTag( + range->end, static_cast(0)); if (range->end > FieldDescriptor::kMaxNumber) { printer->Print( @@ -1244,17 +1317,29 @@ GenerateMergeFromCodedStream(io::Printer* printer) { "end", SimpleItoa(end_tag)); } } - printer->Print(") {\n" - " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" - " mutable_unknown_fields()));\n" + printer->Print(") {\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" + " mutable_unknown_fields()));\n"); + } else { + printer->Print( + " DO_(_extensions_.ParseField(tag, input, default_instance_));\n"); + } + printer->Print( " continue;\n" "}\n"); } // We really don't recognize this tag. Skip it. - printer->Print( - "DO_(::google::protobuf::internal::WireFormat::SkipField(\n" - " input, tag, mutable_unknown_fields()));\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + "DO_(::google::protobuf::internal::WireFormat::SkipField(\n" + " input, tag, mutable_unknown_fields()));\n"); + } else { + printer->Print( + "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n"); + } if (descriptor_->field_count() > 0) { printer->Print("break;\n"); @@ -1319,21 +1404,41 @@ void MessageGenerator::GenerateSerializeOneExtensionRange( void MessageGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "void $classname$::SerializeWithCachedSizes(\n" + " ::google::protobuf::io::CodedOutputStream* output) const {\n" + " _extensions_.SerializeMessageSetWithCachedSizes(output);\n", + "classname", classname_); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + " ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n" + " unknown_fields(), output);\n"); + } + printer->Print( + "}\n"); + return; + } + printer->Print( "void $classname$::SerializeWithCachedSizes(\n" " ::google::protobuf::io::CodedOutputStream* output) const {\n", "classname", classname_); printer->Indent(); - printer->Print( - "::google::protobuf::uint8* raw_buffer = " - "output->GetDirectBufferForNBytesAndAdvance(_cached_size_);\n" - "if (raw_buffer != NULL) {\n" - " $classname$::SerializeWithCachedSizesToArray(raw_buffer);\n" - " return;\n" - "}\n" - "\n", - "classname", classname_); + if (HasFastArraySerialization(descriptor_->file())) { + printer->Print( + "::google::protobuf::uint8* raw_buffer = " + "output->GetDirectBufferForNBytesAndAdvance(_cached_size_);\n" + "if (raw_buffer != NULL) {\n" + " $classname$::SerializeWithCachedSizesToArray(raw_buffer);\n" + " return;\n" + "}\n" + "\n", + "classname", classname_); + } + GenerateSerializeWithCachedSizesBody(printer, false); printer->Outdent(); @@ -1343,6 +1448,26 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) { void MessageGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n" + " ::google::protobuf::uint8* target) const {\n" + " target =\n" + " _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n", + "classname", classname_); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + " target = ::google::protobuf::internal::WireFormat::\n" + " SerializeUnknownMessageSetItemsToArray(\n" + " unknown_fields(), target);\n"); + } + printer->Print( + " return target;\n" + "}\n"); + return; + } + printer->Print( "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n" " ::google::protobuf::uint8* target) const {\n", @@ -1389,26 +1514,46 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { } } - printer->Print("if (!unknown_fields().empty()) {\n"); - printer->Indent(); - if (to_array) { - printer->Print( - "target = " - "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n" - " unknown_fields(), target);\n"); - } else { + if (HasUnknownFields(descriptor_->file())) { + printer->Print("if (!unknown_fields().empty()) {\n"); + printer->Indent(); + if (to_array) { + printer->Print( + "target = " + "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n" + " unknown_fields(), target);\n"); + } else { + printer->Print( + "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n" + " unknown_fields(), output);\n"); + } + printer->Outdent(); + printer->Print( - "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n" - " unknown_fields(), output);\n"); + "}\n"); } - printer->Outdent(); - - printer->Print( - "}\n"); } void MessageGenerator:: GenerateByteSize(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "int $classname$::ByteSize() const {\n" + " int total_size = _extensions_.MessageSetByteSize();\n", + "classname", classname_); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + " total_size += ::google::protobuf::internal::WireFormat::\n" + " ComputeUnknownMessageSetItemsSize(unknown_fields());\n"); + } + printer->Print( + " _cached_size_ = total_size;\n" + " return total_size;\n" + "}\n"); + return; + } + printer->Print( "int $classname$::ByteSize() const {\n", "classname", classname_); @@ -1478,14 +1623,16 @@ GenerateByteSize(io::Printer* printer) { "\n"); } - printer->Print("if (!unknown_fields().empty()) {\n"); - printer->Indent(); - printer->Print( - "total_size +=\n" - " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n" - " unknown_fields());\n"); - printer->Outdent(); - printer->Print("}\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print("if (!unknown_fields().empty()) {\n"); + printer->Indent(); + printer->Print( + "total_size +=\n" + " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n" + " unknown_fields());\n"); + printer->Outdent(); + printer->Print("}\n"); + } // We update _cached_size_ even though this is a const method. In theory, // this is not thread-compatible, because concurrent writes have undefined diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index 105574a7..f1c57141 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -69,6 +69,10 @@ class MessageGenerator { // definitions because those classes use the enums definitions). void GenerateEnumDefinitions(io::Printer* printer); + // Generate specializations of GetEnumDescriptor(). + // Precondition: in ::google::protobuf namespace. + void GenerateGetEnumDescriptorSpecializations(io::Printer* printer); + // Generate definitions for this class and all its nested types. void GenerateClassDefinition(io::Printer* printer); @@ -125,11 +129,6 @@ class MessageGenerator { // Generate the shared destructor code. void GenerateSharedDestructorCode(io::Printer* printer); - // Generate the member initializer list for the constructors. The member - // initializer list is shared between the default constructor and the copy - // constructor. - void GenerateInitializerList(io::Printer* printer); - // Generate standard Message methods. void GenerateClear(io::Printer* printer); void GenerateMergeFromCodedStream(io::Printer* printer); diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index 2a7eb3f8..059fba6e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -35,7 +35,6 @@ #include #include #include -#include #include namespace google { @@ -43,22 +42,12 @@ namespace protobuf { namespace compiler { namespace cpp { -using internal::WireFormat; - namespace { -// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of -// repeat code between this and the other field types. void SetMessageVariables(const FieldDescriptor* descriptor, map* variables) { - (*variables)["name"] = FieldName(descriptor); + SetCommonFieldVariables(descriptor, variables); (*variables)["type"] = ClassName(descriptor->message_type(), true); - (*variables)["index"] = SimpleItoa(descriptor->index()); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["classname"] = ClassName(FieldScope(descriptor), false); - (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type()); - (*variables)["tag_size"] = SimpleItoa( - WireFormat::TagSize(descriptor->number(), descriptor->type())); } } // namespace @@ -81,8 +70,8 @@ GeneratePrivateMembers(io::Printer* printer) const { void MessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline const $type$& $name$() const;\n" - "inline $type$* mutable_$name$();\n"); + "inline const $type$& $name$() const$deprecation$;\n" + "inline $type$* mutable_$name$()$deprecation$;\n"); } void MessageFieldGenerator:: @@ -124,35 +113,35 @@ void MessageFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(\n" + "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" " input, mutable_$name$()));\n"); } else { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormat::ReadGroupNoVirtual(" - "$number$, input, mutable_$name$()));\n"); + "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n" + " $number$, input, mutable_$name$()));\n"); } } void MessageFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual(" - "$number$, this->$name$(), output);\n"); + "::google::protobuf::internal::WireFormatLite::Write$declared_type$NoVirtual(\n" + " $number$, this->$name$(), output);\n"); } void MessageFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormat::" - "Write$declared_type$NoVirtualToArray(" - "$number$, this->$name$(), target);\n"); + "target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$NoVirtualToArray(\n" + " $number$, this->$name$(), target);\n"); } void MessageFieldGenerator:: GenerateByteSize(io::Printer* printer) const { printer->Print(variables_, "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormat::$declared_type$SizeNoVirtual(\n" + " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n" " this->$name$());\n"); } @@ -175,11 +164,13 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedMessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline const ::google::protobuf::RepeatedPtrField< $type$ >& $name$() const;\n" - "inline ::google::protobuf::RepeatedPtrField< $type$ >* mutable_$name$();\n" - "inline const $type$& $name$(int index) const;\n" - "inline $type$* mutable_$name$(int index);\n" - "inline $type$* add_$name$();\n"); + "inline const ::google::protobuf::RepeatedPtrField< $type$ >& $name$() const" + "$deprecation$;\n" + "inline ::google::protobuf::RepeatedPtrField< $type$ >* mutable_$name$()" + "$deprecation$;\n" + "inline const $type$& $name$(int index) const$deprecation$;\n" + "inline $type$* mutable_$name$(int index)$deprecation$;\n" + "inline $type$* add_$name$()$deprecation$;\n"); } void RepeatedMessageFieldGenerator:: @@ -228,12 +219,12 @@ void RepeatedMessageFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(\n" - " input, add_$name$()));\n"); + "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" + " input, add_$name$()));\n"); } else { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormat::ReadGroupNoVirtual(" - "$number$, input, add_$name$()));\n"); + "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n" + " $number$, input, add_$name$()));\n"); } } @@ -241,8 +232,8 @@ void RepeatedMessageFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n" - " ::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual(" - "$number$, this->$name$(i), output);\n" + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoVirtual(\n" + " $number$, this->$name$(i), output);\n" "}\n"); } @@ -250,9 +241,9 @@ void RepeatedMessageFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n" - " target = ::google::protobuf::internal::WireFormat::" - "Write$declared_type$NoVirtualToArray(" - "$number$, this->$name$(i), target);\n" + " target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$NoVirtualToArray(\n" + " $number$, this->$name$(i), target);\n" "}\n"); } @@ -262,7 +253,7 @@ GenerateByteSize(io::Printer* printer) const { "total_size += $tag_size$ * this->$name$_size();\n" "for (int i = 0; i < this->$name$_size(); i++) {\n" " total_size +=\n" - " ::google::protobuf::internal::WireFormat::$declared_type$SizeNoVirtual(\n" + " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n" " this->$name$(i));\n" "}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc index 44d0b97c..81f5ce07 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include namespace google { @@ -43,7 +43,7 @@ namespace protobuf { namespace compiler { namespace cpp { -using internal::WireFormat; +using internal::WireFormatLite; namespace { @@ -57,14 +57,14 @@ int FixedSize(FieldDescriptor::Type type) { case FieldDescriptor::TYPE_UINT64 : return -1; case FieldDescriptor::TYPE_SINT32 : return -1; case FieldDescriptor::TYPE_SINT64 : return -1; - case FieldDescriptor::TYPE_FIXED32 : return WireFormat::kFixed32Size; - case FieldDescriptor::TYPE_FIXED64 : return WireFormat::kFixed64Size; - case FieldDescriptor::TYPE_SFIXED32: return WireFormat::kSFixed32Size; - case FieldDescriptor::TYPE_SFIXED64: return WireFormat::kSFixed64Size; - case FieldDescriptor::TYPE_FLOAT : return WireFormat::kFloatSize; - case FieldDescriptor::TYPE_DOUBLE : return WireFormat::kDoubleSize; - - case FieldDescriptor::TYPE_BOOL : return WireFormat::kBoolSize; + case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; + case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; + case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; + case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; + case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; + case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; + + case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; case FieldDescriptor::TYPE_ENUM : return -1; case FieldDescriptor::TYPE_STRING : return -1; @@ -79,20 +79,11 @@ int FixedSize(FieldDescriptor::Type type) { return -1; } -// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of -// repeat code between this and the other field types. void SetPrimitiveVariables(const FieldDescriptor* descriptor, map* variables) { - (*variables)["name"] = FieldName(descriptor); + SetCommonFieldVariables(descriptor, variables); (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type()); (*variables)["default"] = DefaultValue(descriptor); - (*variables)["index"] = SimpleItoa(descriptor->index()); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["classname"] = ClassName(FieldScope(descriptor), false); - (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type()); - (*variables)["tag_size"] = SimpleItoa( - WireFormat::TagSize(descriptor->number(), descriptor->type())); - int fixed_size = FixedSize(descriptor->type()); if (fixed_size != -1) { (*variables)["fixed_size"] = SimpleItoa(fixed_size); @@ -119,8 +110,8 @@ GeneratePrivateMembers(io::Printer* printer) const { void PrimitiveFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline $type$ $name$() const;\n" - "inline void set_$name$($type$ value);\n"); + "inline $type$ $name$() const$deprecation$;\n" + "inline void set_$name$($type$ value)$deprecation$;\n"); } void PrimitiveFieldGenerator:: @@ -158,7 +149,7 @@ GenerateConstructorCode(io::Printer* printer) const { void PrimitiveFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(\n" + "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" " input, &$name$_));\n" "_set_bit($index$);\n"); } @@ -166,14 +157,14 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { void PrimitiveFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::Write$declared_type$(" + "::google::protobuf::internal::WireFormatLite::Write$declared_type$(" "$number$, this->$name$(), output);\n"); } void PrimitiveFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormat::Write$declared_type$ToArray(" + "target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(" "$number$, this->$name$(), target);\n"); } @@ -183,7 +174,7 @@ GenerateByteSize(io::Printer* printer) const { if (fixed_size == -1) { printer->Print(variables_, "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormat::$declared_type$Size(\n" + " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" " this->$name$());\n"); } else { printer->Print(variables_, @@ -205,8 +196,7 @@ void RepeatedPrimitiveFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, "::google::protobuf::RepeatedField< $type$ > $name$_;\n"); - if (descriptor_->options().packed() && - descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) { printer->Print(variables_, "mutable int _$name$_cached_byte_size_;\n"); } @@ -215,11 +205,12 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedPrimitiveFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline const ::google::protobuf::RepeatedField< $type$ >& $name$() const;\n" - "inline ::google::protobuf::RepeatedField< $type$ >* mutable_$name$();\n" - "inline $type$ $name$(int index) const;\n" - "inline void set_$name$(int index, $type$ value);\n" - "inline void add_$name$($type$ value);\n"); + "inline const ::google::protobuf::RepeatedField< $type$ >& $name$() const\n" + " $deprecation$;\n" + "inline ::google::protobuf::RepeatedField< $type$ >* mutable_$name$()$deprecation$;\n" + "inline $type$ $name$(int index) const$deprecation$;\n" + "inline void set_$name$(int index, $type$ value)$deprecation$;\n" + "inline void add_$name$($type$ value)$deprecation$;\n"); } void RepeatedPrimitiveFieldGenerator:: @@ -272,12 +263,12 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { printer->Print(variables_, "::google::protobuf::uint32 length;\n" "DO_(input->ReadVarint32(&length));\n" - "::google::protobuf::io::CodedInputStream::Limit limit = " - "input->PushLimit(length);\n" + "::google::protobuf::io::CodedInputStream::Limit limit =\n" + " input->PushLimit(length);\n" "while (input->BytesUntilLimit() > 0) {\n" " $type$ value;\n" - " DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(" - "input, &value));\n" + " DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" + " input, &value));\n" " add_$name$(value);\n" "}\n" "input->PopLimit(limit);\n"); @@ -286,8 +277,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { } else { printer->Print(variables_, "$type$ value;\n" - "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(" - "input, &value));\n" + "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" + " input, &value));\n" "add_$name$(value);\n"); } } @@ -298,9 +289,9 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { // Write the tag and the size. printer->Print(variables_, "if (this->$name$_size() > 0) {\n" - " ::google::protobuf::internal::WireFormat::WriteTag(" + " ::google::protobuf::internal::WireFormatLite::WriteTag(" "$number$, " - "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, " + "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, " "output);\n" " output->WriteVarint32(_$name$_cached_byte_size_);\n" "}\n"); @@ -309,12 +300,12 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { "for (int i = 0; i < this->$name$_size(); i++) {\n"); if (descriptor_->options().packed()) { printer->Print(variables_, - " ::google::protobuf::internal::WireFormat::Write$declared_type$NoTag(" - "this->$name$(i), output);\n"); + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n" + " this->$name$(i), output);\n"); } else { printer->Print(variables_, - " ::google::protobuf::internal::WireFormat::Write$declared_type$(" - "$number$, this->$name$(i), output);\n"); + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" + " $number$, this->$name$(i), output);\n"); } printer->Print("}\n"); } @@ -325,26 +316,24 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { // Write the tag and the size. printer->Print(variables_, "if (this->$name$_size() > 0) {\n" - " target = ::google::protobuf::internal::WireFormat::WriteTagToArray(" - "$number$, " - "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, " - "target);\n" - " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(" - "_$name$_cached_byte_size_, target);\n" + " target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n" + " $number$,\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" + " target);\n" + " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n" + " _$name$_cached_byte_size_, target);\n" "}\n"); } printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n"); if (descriptor_->options().packed()) { printer->Print(variables_, - " target = ::google::protobuf::internal::WireFormat::" - "Write$declared_type$NoTagToArray(" - "this->$name$(i), target);\n"); + " target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$NoTagToArray(this->$name$(i), target);\n"); } else { printer->Print(variables_, - " target = ::google::protobuf::internal::WireFormat::" - "Write$declared_type$ToArray(" - "$number$, this->$name$(i), target);\n"); + " target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$ToArray($number$, this->$name$(i), target);\n"); } printer->Print("}\n"); } @@ -359,8 +348,8 @@ GenerateByteSize(io::Printer* printer) const { if (fixed_size == -1) { printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n" - " data_size += ::google::protobuf::internal::WireFormat::$declared_type$Size(\n" - " this->$name$(i));\n" + " data_size += ::google::protobuf::internal::WireFormatLite::\n" + " $declared_type$Size(this->$name$(i));\n" "}\n"); } else { printer->Print(variables_, @@ -370,8 +359,8 @@ GenerateByteSize(io::Printer* printer) const { if (descriptor_->options().packed()) { printer->Print(variables_, "if (data_size > 0) {\n" - " total_size += $tag_size$ + " - "::google::protobuf::internal::WireFormat::Int32Size(data_size);\n" + " total_size += $tag_size$ +\n" + " ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n" "}\n" "_$name$_cached_byte_size_ = data_size;\n" "total_size += data_size;\n"); diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc index 7689fa13..c2825683 100644 --- a/src/google/protobuf/compiler/cpp/cpp_service.cc +++ b/src/google/protobuf/compiler/cpp/cpp_service.cc @@ -249,7 +249,7 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { sub_vars["input_type"] = ClassName(method->input_type(), true); sub_vars["output_type"] = ClassName(method->output_type(), true); - // Note: ::google::protobuf::down_cast does not work here because it only works on pointers, + // Note: down_cast does not work here because it only works on pointers, // not references. printer->Print(sub_vars, " case $index$:\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index 05858da4..72258e89 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -44,23 +43,13 @@ namespace protobuf { namespace compiler { namespace cpp { -using internal::WireFormat; - namespace { -// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of -// repeat code between this and the other field types. void SetStringVariables(const FieldDescriptor* descriptor, map* variables) { - (*variables)["name"] = FieldName(descriptor); + SetCommonFieldVariables(descriptor, variables); (*variables)["default"] = "\"" + CEscape(descriptor->default_value_string()) + "\""; - (*variables)["index"] = SimpleItoa(descriptor->index()); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["classname"] = ClassName(FieldScope(descriptor), false); - (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type()); - (*variables)["tag_size"] = SimpleItoa( - WireFormat::TagSize(descriptor->number(), descriptor->type())); (*variables)["pointer_type"] = descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char"; } @@ -111,11 +100,12 @@ GenerateAccessorDeclarations(io::Printer* printer) const { } printer->Print(variables_, - "inline const ::std::string& $name$() const;\n" - "inline void set_$name$(const ::std::string& value);\n" - "inline void set_$name$(const char* value);\n" - "inline void set_$name$(const $pointer_type$* value, size_t size);\n" - "inline ::std::string* mutable_$name$();\n"); + "inline const ::std::string& $name$() const$deprecation$;\n" + "inline void set_$name$(const ::std::string& value)$deprecation$;\n" + "inline void set_$name$(const char* value)$deprecation$;\n" + "inline void set_$name$(const $pointer_type$* value, size_t size)" + "$deprecation$;\n" + "inline ::std::string* mutable_$name$()$deprecation$;\n"); if (descriptor_->options().has_ctype()) { printer->Outdent(); @@ -221,29 +211,52 @@ GenerateDestructorCode(io::Printer* printer) const { void StringFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(" - "input, mutable_$name$()));\n"); + "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" + " input, this->mutable_$name$()));\n"); + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$().data(), this->$name$().length(),\n" + " ::google::protobuf::internal::WireFormat::PARSE);\n"); + } } void StringFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$().data(), this->$name$().length(),\n" + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + } printer->Print(variables_, - "::google::protobuf::internal::WireFormat::Write$declared_type$(" - "$number$, this->$name$(), output);\n"); + "::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" + " $number$, this->$name$(), output);\n"); } void StringFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$().data(), this->$name$().length(),\n" + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + } printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormat::Write$declared_type$ToArray(" - "$number$, this->$name$(), target);\n"); + "target =\n" + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(\n" + " $number$, this->$name$(), target);\n"); } void StringFieldGenerator:: GenerateByteSize(io::Printer* printer) const { printer->Print(variables_, "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormat::$declared_type$Size(this->$name$());\n"); + " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" + " this->$name$());\n"); } // =================================================================== @@ -274,18 +287,22 @@ GenerateAccessorDeclarations(io::Printer* printer) const { } printer->Print(variables_, - "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const;\n" - "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$();\n" - "inline const ::std::string& $name$(int index) const;\n" - "inline ::std::string* mutable_$name$(int index);\n" - "inline void set_$name$(int index, const ::std::string& value);\n" - "inline void set_$name$(int index, const char* value);\n" + "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const" + "$deprecation$;\n" + "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()" + "$deprecation$;\n" + "inline const ::std::string& $name$(int index) const$deprecation$;\n" + "inline ::std::string* mutable_$name$(int index)$deprecation$;\n" + "inline void set_$name$(int index, const ::std::string& value)$deprecation$;\n" + "inline void set_$name$(int index, const char* value)$deprecation$;\n" "inline " - "void set_$name$(int index, const $pointer_type$* value, size_t size);\n" - "inline ::std::string* add_$name$();\n" - "inline void add_$name$(const ::std::string& value);\n" - "inline void add_$name$(const char* value);\n" - "inline void add_$name$(const $pointer_type$* value, size_t size);\n"); + "void set_$name$(int index, const $pointer_type$* value, size_t size)" + "$deprecation$;\n" + "inline ::std::string* add_$name$()$deprecation$;\n" + "inline void add_$name$(const ::std::string& value)$deprecation$;\n" + "inline void add_$name$(const char* value)$deprecation$;\n" + "inline void add_$name$(const $pointer_type$* value, size_t size)" + "$deprecation$;\n"); if (descriptor_->options().has_ctype()) { printer->Outdent(); @@ -361,26 +378,48 @@ GenerateConstructorCode(io::Printer* printer) const { void RepeatedStringFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(\n" - " input, add_$name$()));\n"); + "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" + " input, this->add_$name$()));\n"); + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$(0).data(), this->$name$(0).length(),\n" + " ::google::protobuf::internal::WireFormat::PARSE);\n"); + } } void RepeatedStringFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { printer->Print(variables_, - "for (int i = 0; i < this->$name$_size(); i++) {\n" - " ::google::protobuf::internal::WireFormat::Write$declared_type$(" - "$number$, this->$name$(i), output);\n" + "for (int i = 0; i < this->$name$_size(); i++) {\n"); + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$(i).data(), this->$name$(i).length(),\n" + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + } + printer->Print(variables_, + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" + " $number$, this->$name$(i), output);\n" "}\n"); } void RepeatedStringFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { printer->Print(variables_, - "for (int i = 0; i < this->$name$_size(); i++) {\n" - " target = ::google::protobuf::internal::WireFormat::" - "Write$declared_type$ToArray(" - "$number$, this->$name$(i), target);\n" + "for (int i = 0; i < this->$name$_size(); i++) {\n"); + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + " ::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$(i).data(), this->$name$(i).length(),\n" + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + } + printer->Print(variables_, + " target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$ToArray($number$, this->$name$(i), target);\n" "}\n"); } @@ -389,7 +428,7 @@ GenerateByteSize(io::Printer* printer) const { printer->Print(variables_, "total_size += $tag_size$ * this->$name$_size();\n" "for (int i = 0; i < this->$name$_size(); i++) {\n" - " total_size += ::google::protobuf::internal::WireFormat::$declared_type$Size(\n" + " total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" " this->$name$(i));\n" "}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index cabf08fd..2b16e85d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -50,11 +50,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -75,18 +73,6 @@ namespace cpp { // Can't use an anonymous namespace here due to brokenness of Tru64 compiler. namespace cpp_unittest { -TEST(ExtremeDefaultValues, FloatingPoint) { - const unittest::TestExtremeDefaultValues& extreme_default = - unittest::TestExtremeDefaultValues::default_instance(); - - EXPECT_EQ(0.0f, extreme_default.zero_float()); - EXPECT_EQ(1.0f, extreme_default.one_float()); - EXPECT_EQ(1.5f, extreme_default.small_float()); - EXPECT_EQ(-1.0f, extreme_default.negative_one_float()); - EXPECT_EQ(-1.5f, extreme_default.negative_float()); - EXPECT_EQ(2.0e8f, extreme_default.large_float()); - EXPECT_EQ(-8e-28f, extreme_default.small_negative_float()); -} class MockErrorCollector : public MultiFileErrorCollector { public: @@ -157,6 +143,19 @@ TEST(GeneratedMessageTest, Defaults) { &message.optional_import_message()); } +TEST(GeneratedMessageTest, FloatingPointDefaults) { + const unittest::TestExtremeDefaultValues& extreme_default = + unittest::TestExtremeDefaultValues::default_instance(); + + EXPECT_EQ(0.0f, extreme_default.zero_float()); + EXPECT_EQ(1.0f, extreme_default.one_float()); + EXPECT_EQ(1.5f, extreme_default.small_float()); + EXPECT_EQ(-1.0f, extreme_default.negative_one_float()); + EXPECT_EQ(-1.5f, extreme_default.negative_float()); + EXPECT_EQ(2.0e8f, extreme_default.large_float()); + EXPECT_EQ(-8e-28f, extreme_default.small_negative_float()); +} + TEST(GeneratedMessageTest, Accessors) { // Set every field to a unique value then go back and check all those // values. @@ -710,6 +709,32 @@ TEST(GeneratedMessageTest, TestSpaceUsed) { #endif // !PROTOBUF_TEST_NO_DESCRIPTORS +TEST(GeneratedMessageTest, FieldConstantValues) { + unittest::TestRequired message; + EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1); + EXPECT_EQ(unittest::TestAllTypes::kOptionalInt32FieldNumber, 1); + EXPECT_EQ(unittest::TestAllTypes::kOptionalgroupFieldNumber, 16); + EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedMessageFieldNumber, 18); + EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedEnumFieldNumber, 21); + EXPECT_EQ(unittest::TestAllTypes::kRepeatedInt32FieldNumber, 31); + EXPECT_EQ(unittest::TestAllTypes::kRepeatedgroupFieldNumber, 46); + EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedMessageFieldNumber, 48); + EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedEnumFieldNumber, 51); +} + +TEST(GeneratedMessageTest, ExtensionConstantValues) { + EXPECT_EQ(unittest::TestRequired::kSingleFieldNumber, 1000); + EXPECT_EQ(unittest::TestRequired::kMultiFieldNumber, 1001); + EXPECT_EQ(unittest::kOptionalInt32ExtensionFieldNumber, 1); + EXPECT_EQ(unittest::kOptionalgroupExtensionFieldNumber, 16); + EXPECT_EQ(unittest::kOptionalNestedMessageExtensionFieldNumber, 18); + EXPECT_EQ(unittest::kOptionalNestedEnumExtensionFieldNumber, 21); + EXPECT_EQ(unittest::kRepeatedInt32ExtensionFieldNumber, 31); + EXPECT_EQ(unittest::kRepeatedgroupExtensionFieldNumber, 46); + EXPECT_EQ(unittest::kRepeatedNestedMessageExtensionFieldNumber, 48); + EXPECT_EQ(unittest::kRepeatedNestedEnumExtensionFieldNumber, 51); +} + // =================================================================== TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) { @@ -803,6 +828,17 @@ TEST(GeneratedEnumTest, Parse) { EXPECT_FALSE(unittest::TestEnumWithDupValue_Parse("FOO", &dup_value)); } +TEST(GeneratedEnumTest, GetEnumDescriptor) { + EXPECT_EQ(unittest::TestAllTypes::NestedEnum_descriptor(), + GetEnumDescriptor()); + EXPECT_EQ(unittest::ForeignEnum_descriptor(), + GetEnumDescriptor()); + EXPECT_EQ(unittest::TestEnumWithDupValue_descriptor(), + GetEnumDescriptor()); + EXPECT_EQ(unittest::TestSparseEnum_descriptor(), + GetEnumDescriptor()); +} + #endif // PROTOBUF_TEST_NO_DESCRIPTORS // =================================================================== diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc index 4aac6493..8ade50c9 100644 --- a/src/google/protobuf/compiler/java/java_enum.cc +++ b/src/google/protobuf/compiler/java/java_enum.cc @@ -67,14 +67,17 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) EnumGenerator::~EnumGenerator() {} void EnumGenerator::Generate(io::Printer* printer) { - bool is_own_file = - descriptor_->containing_type() == NULL && - descriptor_->file()->options().java_multiple_files(); - printer->Print( - "public $static$ enum $classname$\n" - " implements com.google.protobuf.ProtocolMessageEnum {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public enum $classname$\n" + " implements com.google.protobuf.ProtocolMessageEnum {\n", + "classname", descriptor_->name()); + } else { + printer->Print( + "public enum $classname$\n" + " implements com.google.protobuf.Internal.EnumLite {\n", + "classname", descriptor_->name()); + } printer->Indent(); for (int i = 0; i < canonical_values_.size(); i++) { @@ -126,63 +129,78 @@ void EnumGenerator::Generate(io::Printer* printer) { " default: return null;\n" " }\n" "}\n" - "\n"); + "\n" + "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" + " internalGetValueMap() {\n" + " return internalValueMap;\n" + "}\n" + "private static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" + " internalValueMap =\n" + " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" + " public $classname$ findValueByNumber(int number) {\n" + " return $classname$.valueOf(number)\n;" + " }\n" + " };\n" + "\n", + "classname", descriptor_->name()); // ----------------------------------------------------------------- // Reflection - printer->Print( - "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n" - " getValueDescriptor() {\n" - " return getDescriptor().getValues().get(index);\n" - "}\n" - "public final com.google.protobuf.Descriptors.EnumDescriptor\n" - " getDescriptorForType() {\n" - " return getDescriptor();\n" - "}\n" - "public static final com.google.protobuf.Descriptors.EnumDescriptor\n" - " getDescriptor() {\n"); - - // TODO(kenton): Cache statically? Note that we can't access descriptors - // at module init time because it wouldn't work with descriptor.proto, but - // we can cache the value the first time getDescriptor() is called. - if (descriptor_->containing_type() == NULL) { + if (HasDescriptorMethods(descriptor_)) { printer->Print( - " return $file$.getDescriptor().getEnumTypes().get($index$);\n", - "file", ClassName(descriptor_->file()), - "index", SimpleItoa(descriptor_->index())); - } else { - printer->Print( - " return $parent$.getDescriptor().getEnumTypes().get($index$);\n", - "parent", ClassName(descriptor_->containing_type()), - "index", SimpleItoa(descriptor_->index())); - } + "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n" + " getValueDescriptor() {\n" + " return getDescriptor().getValues().get(index);\n" + "}\n" + "public final com.google.protobuf.Descriptors.EnumDescriptor\n" + " getDescriptorForType() {\n" + " return getDescriptor();\n" + "}\n" + "public static final com.google.protobuf.Descriptors.EnumDescriptor\n" + " getDescriptor() {\n"); + + // TODO(kenton): Cache statically? Note that we can't access descriptors + // at module init time because it wouldn't work with descriptor.proto, but + // we can cache the value the first time getDescriptor() is called. + if (descriptor_->containing_type() == NULL) { + printer->Print( + " return $file$.getDescriptor().getEnumTypes().get($index$);\n", + "file", ClassName(descriptor_->file()), + "index", SimpleItoa(descriptor_->index())); + } else { + printer->Print( + " return $parent$.getDescriptor().getEnumTypes().get($index$);\n", + "parent", ClassName(descriptor_->containing_type()), + "index", SimpleItoa(descriptor_->index())); + } - printer->Print( - "}\n" - "\n" - "private static final $classname$[] VALUES = {\n" - " ", - "classname", descriptor_->name()); + printer->Print( + "}\n" + "\n" + "private static final $classname$[] VALUES = {\n" + " ", + "classname", descriptor_->name()); + + for (int i = 0; i < descriptor_->value_count(); i++) { + printer->Print("$name$, ", + "name", descriptor_->value(i)->name()); + } - for (int i = 0; i < descriptor_->value_count(); i++) { - printer->Print("$name$, ", - "name", descriptor_->value(i)->name()); + printer->Print( + "\n" + "};\n" + "public static $classname$ valueOf(\n" + " com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n" + " if (desc.getType() != getDescriptor()) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"EnumValueDescriptor is not for this type.\");\n" + " }\n" + " return VALUES[desc.getIndex()];\n" + "}\n", + "classname", descriptor_->name()); } - printer->Print( - "\n" - "};\n" - "public static $classname$ valueOf(\n" - " com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n" - " if (desc.getType() != getDescriptor()) {\n" - " throw new java.lang.IllegalArgumentException(\n" - " \"EnumValueDescriptor is not for this type.\");\n" - " }\n" - " return VALUES[desc.getIndex()];\n" - "}\n", - "classname", descriptor_->name()); - // ----------------------------------------------------------------- printer->Print( @@ -194,14 +212,16 @@ void EnumGenerator::Generate(io::Printer* printer) { "}\n", "classname", descriptor_->name()); - // Force the static initialization code for the file to run, since it may - // initialize static variables declared in this class. - printer->Print( - "\n" - "static {\n" - " $file$.getDescriptor();\n" - "}\n", - "file", ClassName(descriptor_->file())); + if (HasDescriptorMethods(descriptor_)) { + // Force the static initialization code for the file to run, since it may + // initialize static variables declared in this class. + printer->Print( + "\n" + "static {\n" + " $file$.getDescriptor();\n" + "}\n", + "file", ClassName(descriptor_->file())); + } printer->Outdent(); printer->Print("}\n\n"); diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc index 2153042d..dc36e06e 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.cc +++ b/src/google/protobuf/compiler/java/java_enum_field.cc @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include namespace google { @@ -53,18 +53,13 @@ namespace { // repeat code between this and the other field types. void SetEnumVariables(const FieldDescriptor* descriptor, map* variables) { - const EnumValueDescriptor* default_value; - default_value = descriptor->default_value_enum(); - - string type = ClassName(descriptor->enum_type()); - (*variables)["name"] = UnderscoresToCamelCase(descriptor); (*variables)["capitalized_name"] = UnderscoresToCapitalizedCamelCase(descriptor); (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["type"] = type; - (*variables)["default"] = type + "." + default_value->name(); + (*variables)["type"] = ClassName(descriptor->enum_type()); + (*variables)["default"] = DefaultValue(descriptor); (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); (*variables)["tag_size"] = SimpleItoa( internal::WireFormat::TagSize(descriptor->number(), descriptor->type())); @@ -132,10 +127,17 @@ void EnumFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "int rawValue = input.readEnum();\n" - "$type$ value = $type$.valueOf(rawValue);\n" - "if (value == null) {\n" - " unknownFields.mergeVarintField($number$, rawValue);\n" - "} else {\n" + "$type$ value = $type$.valueOf(rawValue);\n"); + if (HasUnknownFields(descriptor_->containing_type())) { + printer->Print(variables_, + "if (value == null) {\n" + " unknownFields.mergeVarintField($number$, rawValue);\n" + "} else {\n"); + } else { + printer->Print(variables_, + "if (value != null) {\n"); + } + printer->Print(variables_, " set$capitalized_name$(value);\n" "}\n"); } @@ -185,7 +187,7 @@ GenerateMembers(io::Printer* printer) const { "}\n"); if (descriptor_->options().packed() && - descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + HasGeneratedMethods(descriptor_->containing_type())) { printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); } @@ -272,10 +274,17 @@ GenerateParsingCode(io::Printer* printer) const { // Read and store the enum printer->Print(variables_, "int rawValue = input.readEnum();\n" - "$type$ value = $type$.valueOf(rawValue);\n" - "if (value == null) {\n" - " unknownFields.mergeVarintField($number$, rawValue);\n" - "} else {\n" + "$type$ value = $type$.valueOf(rawValue);\n"); + if (HasUnknownFields(descriptor_->containing_type())) { + printer->Print(variables_, + "if (value == null) {\n" + " unknownFields.mergeVarintField($number$, rawValue);\n" + "} else {\n"); + } else { + printer->Print(variables_, + "if (value != null) {\n"); + } + printer->Print(variables_, " add$capitalized_name$(value);\n" "}\n"); diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc index 302dcea4..4403220b 100644 --- a/src/google/protobuf/compiler/java/java_extension.cc +++ b/src/google/protobuf/compiler/java/java_extension.cc @@ -42,6 +42,39 @@ namespace protobuf { namespace compiler { namespace java { +namespace { + +const char* TypeName(FieldDescriptor::Type field_type) { + switch (field_type) { + case FieldDescriptor::TYPE_INT32 : return "INT32"; + case FieldDescriptor::TYPE_UINT32 : return "UINT32"; + case FieldDescriptor::TYPE_SINT32 : return "SINT32"; + case FieldDescriptor::TYPE_FIXED32 : return "FIXED32"; + case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32"; + case FieldDescriptor::TYPE_INT64 : return "INT64"; + case FieldDescriptor::TYPE_UINT64 : return "UINT64"; + case FieldDescriptor::TYPE_SINT64 : return "SINT64"; + case FieldDescriptor::TYPE_FIXED64 : return "FIXED64"; + case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64"; + case FieldDescriptor::TYPE_FLOAT : return "FLOAT"; + case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE"; + case FieldDescriptor::TYPE_BOOL : return "BOOL"; + case FieldDescriptor::TYPE_STRING : return "STRING"; + case FieldDescriptor::TYPE_BYTES : return "BYTES"; + case FieldDescriptor::TYPE_ENUM : return "ENUM"; + case FieldDescriptor::TYPE_GROUP : return "GROUP"; + case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE"; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +} + ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor) : descriptor_(descriptor) { if (descriptor_->extension_scope() != NULL) { @@ -59,6 +92,7 @@ void ExtensionGenerator::Generate(io::Printer* printer) { vars["containing_type"] = ClassName(descriptor_->containing_type()); vars["number"] = SimpleItoa(descriptor_->number()); vars["constant_name"] = FieldConstantName(descriptor_); + vars["lite"] = HasDescriptorMethods(descriptor_->file()) ? "" : "Lite"; JavaType java_type = GetJavaType(descriptor_); string singular_type; @@ -79,13 +113,13 @@ void ExtensionGenerator::Generate(io::Printer* printer) { if (descriptor_->is_repeated()) { printer->Print(vars, "public static\n" - " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n" " $containing_type$,\n" " java.util.List<$type$>> $name$;\n"); } else { printer->Print(vars, "public static\n" - " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n" " $containing_type$,\n" " $type$> $name$;\n"); } @@ -96,34 +130,71 @@ void ExtensionGenerator::GenerateInitializationCode(io::Printer* printer) { vars["name"] = UnderscoresToCamelCase(descriptor_); vars["scope"] = scope_; vars["index"] = SimpleItoa(descriptor_->index()); + vars["extendee"] = ClassName(descriptor_->containing_type()); + vars["default"] = descriptor_->is_repeated() ? "" : DefaultValue(descriptor_); + vars["number"] = SimpleItoa(descriptor_->number()); + vars["type_constant"] = TypeName(descriptor_->type()); + vars["packed"] = descriptor_->options().packed() ? "true" : "false"; + vars["enum_map"] = "null"; + vars["prototype"] = "null"; JavaType java_type = GetJavaType(descriptor_); string singular_type; switch (java_type) { case JAVATYPE_MESSAGE: vars["type"] = ClassName(descriptor_->message_type()); + vars["prototype"] = ClassName(descriptor_->message_type()) + + ".getDefaultInstance()"; break; case JAVATYPE_ENUM: vars["type"] = ClassName(descriptor_->enum_type()); + vars["enum_map"] = ClassName(descriptor_->enum_type()) + + ".internalGetValueMap()"; break; default: vars["type"] = BoxedPrimitiveTypeName(java_type); break; } - if (descriptor_->is_repeated()) { - printer->Print(vars, - "$scope$.$name$ =\n" - " com.google.protobuf.GeneratedMessage\n" - " .newRepeatedGeneratedExtension(\n" - " $scope$.getDescriptor().getExtensions().get($index$),\n" - " $type$.class);\n"); + if (HasDescriptorMethods(descriptor_->file())) { + if (descriptor_->is_repeated()) { + printer->Print(vars, + "$scope$.$name$ =\n" + " com.google.protobuf.GeneratedMessage\n" + " .newRepeatedGeneratedExtension(\n" + " $scope$.getDescriptor().getExtensions().get($index$),\n" + " $type$.class);\n"); + } else { + printer->Print(vars, + "$scope$.$name$ =\n" + " com.google.protobuf.GeneratedMessage.newGeneratedExtension(\n" + " $scope$.getDescriptor().getExtensions().get($index$),\n" + " $type$.class);\n"); + } } else { - printer->Print(vars, - "$scope$.$name$ =\n" - " com.google.protobuf.GeneratedMessage.newGeneratedExtension(\n" - " $scope$.getDescriptor().getExtensions().get($index$),\n" - " $type$.class);\n"); + if (descriptor_->is_repeated()) { + printer->Print(vars, + "$scope$.$name$ =\n" + " com.google.protobuf.GeneratedMessageLite\n" + " .newRepeatedGeneratedExtension(\n" + " $extendee$.getDefaultInstance(),\n" + " $prototype$,\n" + " $enum_map$,\n" + " $number$,\n" + " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" + " $packed$);\n"); + } else { + printer->Print(vars, + "$scope$.$name$ =\n" + " com.google.protobuf.GeneratedMessageLite\n" + " .newGeneratedExtension(\n" + " $extendee$.getDefaultInstance(),\n" + " $default$,\n" + " $prototype$,\n" + " $enum_map$,\n" + " $number$,\n" + " com.google.protobuf.WireFormat.FieldType.$type_constant$);\n"); + } } } diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc index 31d75be6..0e170b38 100644 --- a/src/google/protobuf/compiler/java/java_file.cc +++ b/src/google/protobuf/compiler/java/java_file.cc @@ -151,7 +151,9 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Print( "public static void registerAllExtensions(\n" - " com.google.protobuf.ExtensionRegistry registry) {\n"); + " com.google.protobuf.ExtensionRegistry$lite$ registry) {\n", + "lite", HasDescriptorMethods(file_) ? "" : "Lite"); + printer->Indent(); for (int i = 0; i < file_->extension_count(); i++) { @@ -195,8 +197,42 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Print("\n"); - // ----------------------------------------------------------------- + if (HasDescriptorMethods(file_)) { + GenerateEmbeddedDescriptor(printer); + } else { + printer->Print( + "static {\n"); + printer->Indent(); + for (int i = 0; i < file_->message_type_count(); i++) { + // TODO(kenton): Reuse MessageGenerator objects? + MessageGenerator(file_->message_type(i)) + .GenerateStaticVariableInitializers(printer); + } + + for (int i = 0; i < file_->extension_count(); i++) { + // TODO(kenton): Reuse ExtensionGenerator objects? + ExtensionGenerator(file_->extension(i)) + .GenerateInitializationCode(printer); + } + + printer->Outdent(); + printer->Print( + "}\n"); + } + + // Dummy function we can use to force the static initialization block to + // run. Needed by inner classes. Cannot be private due to + // java_multiple_files option. + printer->Print( + "\n" + "public static void internalForceInit() {}\n"); + + printer->Outdent(); + printer->Print("}\n"); +} + +void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) { // Embed the descriptor. We simply serialize the entire FileDescriptorProto // and embed it as a string literal, which is parsed and built into real // descriptors at initialization time. We unfortunately have to put it in @@ -310,9 +346,6 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Outdent(); printer->Print( "}\n"); - - printer->Outdent(); - printer->Print("}\n"); } template diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h index f1efd011..cb82cea2 100644 --- a/src/google/protobuf/compiler/java/java_file.h +++ b/src/google/protobuf/compiler/java/java_file.h @@ -81,6 +81,8 @@ class FileGenerator { string java_package_; string classname_; + void GenerateEmbeddedDescriptor(io::Printer* printer); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); }; diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc index 51af5f0d..8ed3affb 100644 --- a/src/google/protobuf/compiler/java/java_generator.cc +++ b/src/google/protobuf/compiler/java/java_generator.cc @@ -45,32 +45,6 @@ namespace protobuf { namespace compiler { namespace java { -namespace { - -// Parses a set of comma-delimited name/value pairs, e.g.: -// "foo=bar,baz,qux=corge" -// parses to the pairs: -// ("foo", "bar"), ("baz", ""), ("qux", "corge") -void ParseOptions(const string& text, vector >* output) { - vector parts; - SplitStringUsing(text, ",", &parts); - - for (int i = 0; i < parts.size(); i++) { - string::size_type equals_pos = parts[i].find_first_of('='); - pair value; - if (equals_pos == string::npos) { - value.first = parts[i]; - value.second = ""; - } else { - value.first = parts[i].substr(0, equals_pos); - value.second = parts[i].substr(equals_pos + 1); - } - output->push_back(value); - } -} - -} // namespace - JavaGenerator::JavaGenerator() {} JavaGenerator::~JavaGenerator() {} @@ -79,7 +53,7 @@ bool JavaGenerator::Generate(const FileDescriptor* file, OutputDirectory* output_directory, string* error) const { vector > options; - ParseOptions(parameter, &options); + ParseGeneratorParameter(parameter, &options); // ----------------------------------------------------------------- // parse generator options diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc index 6a107650..dc6748e3 100644 --- a/src/google/protobuf/compiler/java/java_helpers.cc +++ b/src/google/protobuf/compiler/java/java_helpers.cc @@ -37,6 +37,7 @@ #include #include #include +#include namespace google { namespace protobuf { @@ -243,6 +244,72 @@ const char* BoxedPrimitiveTypeName(JavaType type) { return NULL; } +bool AllAscii(const string& text) { + for (int i = 0; i < text.size(); i++) { + if ((text[i] & 0x80) != 0) { + return false; + } + } + return true; +} + +string DefaultValue(const FieldDescriptor* field) { + // Switch on cpp_type since we need to know which default_value_* method + // of FieldDescriptor to call. + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return SimpleItoa(field->default_value_int32()); + case FieldDescriptor::CPPTYPE_UINT32: + // Need to print as a signed int since Java has no unsigned. + return SimpleItoa(static_cast(field->default_value_uint32())); + case FieldDescriptor::CPPTYPE_INT64: + return SimpleItoa(field->default_value_int64()) + "L"; + case FieldDescriptor::CPPTYPE_UINT64: + return SimpleItoa(static_cast(field->default_value_uint64())) + + "L"; + case FieldDescriptor::CPPTYPE_DOUBLE: + return SimpleDtoa(field->default_value_double()) + "D"; + case FieldDescriptor::CPPTYPE_FLOAT: + return SimpleFtoa(field->default_value_float()) + "F"; + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() ? "true" : "false"; + case FieldDescriptor::CPPTYPE_STRING: + if (field->type() == FieldDescriptor::TYPE_BYTES) { + if (field->has_default_value()) { + // See comments in Internal.java for gory details. + return strings::Substitute( + "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")", + CEscape(field->default_value_string())); + } else { + return "com.google.protobuf.ByteString.EMPTY"; + } + } else { + if (AllAscii(field->default_value_string())) { + // All chars are ASCII. In this case CEscape() works fine. + return "\"" + CEscape(field->default_value_string()) + "\""; + } else { + // See comments in Internal.java for gory details. + return strings::Substitute( + "com.google.protobuf.Internal.stringDefaultValue(\"$0\")", + CEscape(field->default_value_string())); + } + } + + case FieldDescriptor::CPPTYPE_ENUM: + return ClassName(field->enum_type()) + "." + + field->default_value_enum()->name(); + + case FieldDescriptor::CPPTYPE_MESSAGE: + return ClassName(field->message_type()) + ".getDefaultInstance()"; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return ""; +} + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h index de3f883b..f1b643c3 100644 --- a/src/google/protobuf/compiler/java/java_helpers.h +++ b/src/google/protobuf/compiler/java/java_helpers.h @@ -36,6 +36,7 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ #include +#include #include namespace google { @@ -115,6 +116,35 @@ inline JavaType GetJavaType(const FieldDescriptor* field) { // types. const char* BoxedPrimitiveTypeName(JavaType type); +string DefaultValue(const FieldDescriptor* field); + +// Does this message class keep track of unknown fields? +inline bool HasUnknownFields(const Descriptor* descriptor) { + return descriptor->file()->options().optimize_for() != + FileOptions::LITE_RUNTIME; +} + +// Does this message class have generated parsing, serialization, and other +// standard methods for which reflection-based fallback implementations exist? +inline bool HasGeneratedMethods(const Descriptor* descriptor) { + return descriptor->file()->options().optimize_for() != + FileOptions::CODE_SIZE; +} + +// Does this message class have descriptor and reflection methods? +inline bool HasDescriptorMethods(const Descriptor* descriptor) { + return descriptor->file()->options().optimize_for() != + FileOptions::LITE_RUNTIME; +} +inline bool HasDescriptorMethods(const EnumDescriptor* descriptor) { + return descriptor->file()->options().optimize_for() != + FileOptions::LITE_RUNTIME; +} +inline bool HasDescriptorMethods(const FileDescriptor* descriptor) { + return descriptor->options().optimize_for() != + FileOptions::LITE_RUNTIME; +} + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index c9cbd13f..f79546d6 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include namespace google { @@ -50,6 +50,7 @@ namespace compiler { namespace java { using internal::WireFormat; +using internal::WireFormatLite; namespace { @@ -153,38 +154,41 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor) MessageGenerator::~MessageGenerator() {} void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { - // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is - // used in the construction of descriptors, we have a tricky bootstrapping - // problem. To help control static initialization order, we make sure all - // descriptors and other static data that depends on them are members of - // the outermost class in the file. This way, they will be initialized in - // a deterministic order. - - map vars; - vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); - vars["index"] = SimpleItoa(descriptor_->index()); - vars["classname"] = ClassName(descriptor_); - if (descriptor_->containing_type() != NULL) { - vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type()); - } - if (descriptor_->file()->options().java_multiple_files()) { - // We can only make these package-private since the classes that use them - // are in separate files. - vars["private"] = ""; - } else { - vars["private"] = "private "; - } + if (HasDescriptorMethods(descriptor_)) { + // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is + // used in the construction of descriptors, we have a tricky bootstrapping + // problem. To help control static initialization order, we make sure all + // descriptors and other static data that depends on them are members of + // the outermost class in the file. This way, they will be initialized in + // a deterministic order. + + map vars; + vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); + vars["index"] = SimpleItoa(descriptor_->index()); + vars["classname"] = ClassName(descriptor_); + if (descriptor_->containing_type() != NULL) { + vars["parent"] = UniqueFileScopeIdentifier( + descriptor_->containing_type()); + } + if (descriptor_->file()->options().java_multiple_files()) { + // We can only make these package-private since the classes that use them + // are in separate files. + vars["private"] = ""; + } else { + vars["private"] = "private "; + } - // The descriptor for this type. - printer->Print(vars, - "$private$static com.google.protobuf.Descriptors.Descriptor\n" - " internal_$identifier$_descriptor;\n"); + // The descriptor for this type. + printer->Print(vars, + "$private$static com.google.protobuf.Descriptors.Descriptor\n" + " internal_$identifier$_descriptor;\n"); - // And the FieldAccessorTable. - printer->Print(vars, - "$private$static\n" - " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" - " internal_$identifier$_fieldAccessorTable;\n"); + // And the FieldAccessorTable. + printer->Print(vars, + "$private$static\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internal_$identifier$_fieldAccessorTable;\n"); + } // Generate static members for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { @@ -196,41 +200,44 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { void MessageGenerator::GenerateStaticVariableInitializers( io::Printer* printer) { - map vars; - vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); - vars["index"] = SimpleItoa(descriptor_->index()); - vars["classname"] = ClassName(descriptor_); - if (descriptor_->containing_type() != NULL) { - vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type()); - } + if (HasDescriptorMethods(descriptor_)) { + map vars; + vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); + vars["index"] = SimpleItoa(descriptor_->index()); + vars["classname"] = ClassName(descriptor_); + if (descriptor_->containing_type() != NULL) { + vars["parent"] = UniqueFileScopeIdentifier( + descriptor_->containing_type()); + } - // The descriptor for this type. - if (descriptor_->containing_type() == NULL) { - printer->Print(vars, - "internal_$identifier$_descriptor =\n" - " getDescriptor().getMessageTypes().get($index$);\n"); - } else { - printer->Print(vars, - "internal_$identifier$_descriptor =\n" - " internal_$parent$_descriptor.getNestedTypes().get($index$);\n"); - } + // The descriptor for this type. + if (descriptor_->containing_type() == NULL) { + printer->Print(vars, + "internal_$identifier$_descriptor =\n" + " getDescriptor().getMessageTypes().get($index$);\n"); + } else { + printer->Print(vars, + "internal_$identifier$_descriptor =\n" + " internal_$parent$_descriptor.getNestedTypes().get($index$);\n"); + } - // And the FieldAccessorTable. - printer->Print(vars, - "internal_$identifier$_fieldAccessorTable = new\n" - " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" - " internal_$identifier$_descriptor,\n" - " new java.lang.String[] { "); - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print( - "\"$field_name$\", ", - "field_name", - UnderscoresToCapitalizedCamelCase(descriptor_->field(i))); + // And the FieldAccessorTable. + printer->Print(vars, + "internal_$identifier$_fieldAccessorTable = new\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" + " internal_$identifier$_descriptor,\n" + " new java.lang.String[] { "); + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print( + "\"$field_name$\", ", + "field_name", + UnderscoresToCapitalizedCamelCase(descriptor_->field(i))); + } + printer->Print("},\n" + " $classname$.class,\n" + " $classname$.Builder.class);\n", + "classname", ClassName(descriptor_)); } - printer->Print("},\n" - " $classname$.class,\n" - " $classname$.Builder.class);\n", - "classname", ClassName(descriptor_)); // Generate static member initializers for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { @@ -252,18 +259,35 @@ void MessageGenerator::Generate(io::Printer* printer) { descriptor_->file()->options().java_multiple_files(); if (descriptor_->extension_range_count() > 0) { - printer->Print( - "public $static$ final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" - " $classname$> {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public $static$ final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" + " $classname$> {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); + } else { + printer->Print( + "public $static$ final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" + " $classname$> {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); + } } else { - printer->Print( - "public $static$ final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public $static$ final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); + } else { + printer->Print( + "public $static$ final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); + } } printer->Indent(); printer->Print( @@ -280,20 +304,23 @@ void MessageGenerator::Generate(io::Printer* printer) { "}\n" "\n", "classname", descriptor_->name()); - printer->Print( - "public static final com.google.protobuf.Descriptors.Descriptor\n" - " getDescriptor() {\n" - " return $fileclass$.internal_$identifier$_descriptor;\n" - "}\n" - "\n" - "@Override\n" - "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" - " internalGetFieldAccessorTable() {\n" - " return $fileclass$.internal_$identifier$_fieldAccessorTable;\n" - "}\n" - "\n", - "fileclass", ClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_)); + + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public static final com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptor() {\n" + " return $fileclass$.internal_$identifier$_descriptor;\n" + "}\n" + "\n" + "@Override\n" + "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internalGetFieldAccessorTable() {\n" + " return $fileclass$.internal_$identifier$_fieldAccessorTable;\n" + "}\n" + "\n", + "fileclass", ClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); + } // Nested types and extensions for (int i = 0; i < descriptor_->enum_type_count(); i++) { @@ -318,7 +345,7 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print("\n"); } - if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + if (HasGeneratedMethods(descriptor_)) { GenerateIsInitialized(printer); GenerateMessageSerializationMethods(printer); } @@ -326,12 +353,23 @@ void MessageGenerator::Generate(io::Printer* printer) { GenerateParseFromMethods(printer); GenerateBuilder(printer); - // Force the static initialization code for the file to run, since it may - // initialize static variables declared in this class. + if (HasDescriptorMethods(descriptor_)) { + // Force the static initialization code for the file to run, since it may + // initialize static variables declared in this class. + printer->Print( + "\n" + "static {\n" + " $file$.getDescriptor();\n" + "}\n", + "file", ClassName(descriptor_->file())); + } + + // Force initialization of outer class. Otherwise, nested extensions may + // not be initialized. printer->Print( "\n" "static {\n" - " $file$.getDescriptor();\n" + " $file$.internalForceInit();\n" "}\n", "file", ClassName(descriptor_->file())); @@ -360,9 +398,18 @@ GenerateMessageSerializationMethods(io::Printer* printer) { printer->Indent(); if (descriptor_->extension_range_count() > 0) { - printer->Print( - "com.google.protobuf.GeneratedMessage.ExtendableMessage\n" - " .ExtensionWriter extensionWriter = newExtensionWriter();\n"); + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage\n" + " .ExtensionWriter extensionWriter =\n" + " newMessageSetExtensionWriter();\n", + "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite"); + } else { + printer->Print( + "com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage\n" + " .ExtensionWriter extensionWriter = newExtensionWriter();\n", + "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite"); + } } // Merge the fields and the extension ranges, both sorted by field number. @@ -380,12 +427,14 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } } - if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "getUnknownFields().writeAsMessageSetTo(output);\n"); - } else { - printer->Print( - "getUnknownFields().writeTo(output);\n"); + if (HasUnknownFields(descriptor_)) { + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "getUnknownFields().writeAsMessageSetTo(output);\n"); + } else { + printer->Print( + "getUnknownFields().writeTo(output);\n"); + } } printer->Outdent(); @@ -406,16 +455,23 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } if (descriptor_->extension_range_count() > 0) { - printer->Print( - "size += extensionsSerializedSize();\n"); + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "size += extensionsSerializedSizeAsMessageSet();\n"); + } else { + printer->Print( + "size += extensionsSerializedSize();\n"); + } } - if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "size += getUnknownFields().getSerializedSizeAsMessageSet();\n"); - } else { - printer->Print( - "size += getUnknownFields().getSerializedSize();\n"); + if (HasUnknownFields(descriptor_)) { + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "size += getUnknownFields().getSerializedSizeAsMessageSet();\n"); + } else { + printer->Print( + "size += getUnknownFields().getSerializedSize();\n"); + } } printer->Outdent(); @@ -439,7 +495,7 @@ GenerateParseFromMethods(io::Printer* printer) { "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.ByteString data,\n" - " com.google.protobuf.ExtensionRegistry extensionRegistry)\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" " return newBuilder().mergeFrom(data, extensionRegistry)\n" " .buildParsed();\n" @@ -450,7 +506,7 @@ GenerateParseFromMethods(io::Printer* printer) { "}\n" "public static $classname$ parseFrom(\n" " byte[] data,\n" - " com.google.protobuf.ExtensionRegistry extensionRegistry)\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" " return newBuilder().mergeFrom(data, extensionRegistry)\n" " .buildParsed();\n" @@ -461,7 +517,7 @@ GenerateParseFromMethods(io::Printer* printer) { "}\n" "public static $classname$ parseFrom(\n" " java.io.InputStream input,\n" - " com.google.protobuf.ExtensionRegistry extensionRegistry)\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" " return newBuilder().mergeFrom(input, extensionRegistry)\n" " .buildParsed();\n" @@ -472,7 +528,7 @@ GenerateParseFromMethods(io::Printer* printer) { "}\n" "public static $classname$ parseDelimitedFrom(\n" " java.io.InputStream input,\n" - " com.google.protobuf.ExtensionRegistry extensionRegistry)\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" " return newBuilder().mergeDelimitedFrom(input, extensionRegistry)\n" " .buildParsed();\n" @@ -484,7 +540,7 @@ GenerateParseFromMethods(io::Printer* printer) { "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistry extensionRegistry)\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" " return newBuilder().mergeFrom(input, extensionRegistry)\n" " .buildParsed();\n" @@ -509,32 +565,57 @@ void MessageGenerator::GenerateSerializeOneExtensionRange( void MessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print( - "public static Builder newBuilder() { return new Builder(); }\n" - "public Builder newBuilderForType() { return new Builder(); }\n" + "public static Builder newBuilder() { return Builder.create(); }\n" + "public Builder newBuilderForType() { return newBuilder(); }\n" "public static Builder newBuilder($classname$ prototype) {\n" - " return new Builder().mergeFrom(prototype);\n" + " return newBuilder().mergeFrom(prototype);\n" "}\n" "public Builder toBuilder() { return newBuilder(this); }\n" "\n", "classname", ClassName(descriptor_)); if (descriptor_->extension_range_count() > 0) { - printer->Print( - "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" - " $classname$, Builder> {\n", - "classname", ClassName(descriptor_)); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" + " $classname$, Builder> {\n", + "classname", ClassName(descriptor_)); + } else { + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n" + " $classname$, Builder> {\n", + "classname", ClassName(descriptor_)); + } } else { - printer->Print( - "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage.Builder {\n", - "classname", ClassName(descriptor_)); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessage.Builder {\n", + "classname", ClassName(descriptor_)); + } else { + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessageLite.Builder<\n" + " $classname$, Builder> {\n", + "classname", ClassName(descriptor_)); + } } printer->Indent(); + // By using a threadlocal queue, we do not have to worry about locking when + // accessing the queue. Current JDKs implement this very efficiently, using + // no locks themselves to acquire the value when needed. + printer->Print( + "private static final " + " com.google.protobuf.Internal.ThreadLocalQuickQueue builders =\n" + " new com.google.protobuf.Internal.ThreadLocalQuickQueue();\n" + "\n"); + GenerateCommonBuilderMethods(printer); - if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + if (HasGeneratedMethods(descriptor_)) { GenerateBuilderParsingMethods(printer); } @@ -553,10 +634,19 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { printer->Print( + "private $classname$ result;\n" + "\n" "// Construct using $classname$.newBuilder()\n" "private Builder() {}\n" "\n" - "$classname$ result = new $classname$();\n" + "private static Builder create() {\n" + " Builder builder = builders.get().poll();\n" + " if (builder == null) {\n" + " builder = new Builder();\n" + " }\n" + " builder.result = new $classname$();\n" + " return builder;\n" + "}\n" "\n" "@Override\n" "protected $classname$ internalGetResult() {\n" @@ -565,25 +655,38 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { "\n" "@Override\n" "public Builder clear() {\n" + " if (result == null) {\n" + " throw new IllegalStateException(\n" + " \"Cannot call clear() after build().\");\n" + " }\n" " result = new $classname$();\n" " return this;\n" "}\n" "\n" "@Override\n" "public Builder clone() {\n" - " return new Builder().mergeFrom(result);\n" + " return create().mergeFrom(result);\n" "}\n" - "\n" - "@Override\n" - "public com.google.protobuf.Descriptors.Descriptor\n" - " getDescriptorForType() {\n" - " return $classname$.getDescriptor();\n" - "}\n" - "\n" + "\n", + "classname", ClassName(descriptor_)); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "@Override\n" + "public com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptorForType() {\n" + " return $classname$.getDescriptor();\n" + "}\n" + "\n", + "classname", ClassName(descriptor_)); + } + printer->Print( "public $classname$ getDefaultInstanceForType() {\n" " return $classname$.getDefaultInstance();\n" "}\n" - "\n", + "\n" + "public boolean isInitialized() {\n" + " return result.isInitialized();\n" + "}\n", "classname", ClassName(descriptor_)); // ----------------------------------------------------------------- @@ -592,8 +695,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { "public $classname$ build() {\n" // If result == null, we'll throw an appropriate exception later. " if (result != null && !isInitialized()) {\n" - " throw new com.google.protobuf.UninitializedMessageException(\n" - " result);\n" + " throw newUninitializedMessageException(result);\n" " }\n" " return buildPartial();\n" "}\n" @@ -601,7 +703,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { "private $classname$ buildParsed()\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" " if (!isInitialized()) {\n" - " throw new com.google.protobuf.UninitializedMessageException(\n" + " throw newUninitializedMessageException(\n" " result).asInvalidProtocolBufferException();\n" " }\n" " return buildPartial();\n" @@ -610,7 +712,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { "public $classname$ buildPartial() {\n" " if (result == null) {\n" " throw new IllegalStateException(\n" - " \"build() has already been called on this Builder.\");" + " \"build() has already been called on this Builder.\");\n" " }\n", "classname", ClassName(descriptor_)); printer->Indent(); @@ -623,6 +725,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { printer->Print( " $classname$ returnMe = result;\n" " result = null;\n" + " builders.get().offer(this);\n" " return returnMe;\n" "}\n" "\n", @@ -630,18 +733,25 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { // ----------------------------------------------------------------- - if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + if (HasGeneratedMethods(descriptor_)) { + // MergeFrom(Message other) requires the ability to distinguish the other + // messages type by its descriptor. + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "@Override\n" + "public Builder mergeFrom(com.google.protobuf.Message other) {\n" + " if (other instanceof $classname$) {\n" + " return mergeFrom(($classname$)other);\n" + " } else {\n" + " super.mergeFrom(other);\n" + " return this;\n" + " }\n" + "}\n" + "\n", + "classname", ClassName(descriptor_)); + } + printer->Print( - "@Override\n" - "public Builder mergeFrom(com.google.protobuf.Message other) {\n" - " if (other instanceof $classname$) {\n" - " return mergeFrom(($classname$)other);\n" - " } else {\n" - " super.mergeFrom(other);\n" - " return this;\n" - " }\n" - "}\n" - "\n" "public Builder mergeFrom($classname$ other) {\n" // Optimization: If other is the default instance, we know none of its // fields are set so we can skip the merge. @@ -661,8 +771,12 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " this.mergeExtensionFields(other);\n"); } + if (HasUnknownFields(descriptor_)) { + printer->Print( + " this.mergeUnknownFields(other.getUnknownFields());\n"); + } + printer->Print( - " this.mergeUnknownFields(other.getUnknownFields());\n" " return this;\n" "}\n" "\n"); @@ -676,25 +790,21 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { SortFieldsByNumber(descriptor_)); printer->Print( - "@Override\n" - "public Builder mergeFrom(\n" - " com.google.protobuf.CodedInputStream input)\n" - " throws java.io.IOException {\n" - " return mergeFrom(input,\n" - " com.google.protobuf.ExtensionRegistry.getEmptyRegistry());\n" - "}\n" - "\n" "@Override\n" "public Builder mergeFrom(\n" " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistry extensionRegistry)\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n"); printer->Indent(); + if (HasUnknownFields(descriptor_)) { + printer->Print( + "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" + " com.google.protobuf.UnknownFieldSet.newBuilder(\n" + " this.getUnknownFields());\n"); + } + printer->Print( - "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" - " com.google.protobuf.UnknownFieldSet.newBuilder(\n" - " this.getUnknownFields());\n" "while (true) {\n"); printer->Indent(); @@ -703,22 +813,34 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { "switch (tag) {\n"); printer->Indent(); - printer->Print( - "case 0:\n" // zero signals EOF / limit reached - " this.setUnknownFields(unknownFields.build());\n" - " return this;\n" - "default: {\n" - " if (!parseUnknownField(input, unknownFields,\n" - " extensionRegistry, tag)) {\n" - " this.setUnknownFields(unknownFields.build());\n" - " return this;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); + if (HasUnknownFields(descriptor_)) { + printer->Print( + "case 0:\n" // zero signals EOF / limit reached + " this.setUnknownFields(unknownFields.build());\n" + " return this;\n" + "default: {\n" + " if (!parseUnknownField(input, unknownFields,\n" + " extensionRegistry, tag)) {\n" + " this.setUnknownFields(unknownFields.build());\n" + " return this;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); + } else { + printer->Print( + "case 0:\n" // zero signals EOF / limit reached + " return this;\n" + "default: {\n" + " if (!parseUnknownField(input, extensionRegistry, tag)) {\n" + " return this;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); + } for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = sorted_fields[i]; - uint32 tag = WireFormat::MakeTag(field->number(), + uint32 tag = WireFormatLite::MakeTag(field->number(), WireFormat::WireTypeForField(field)); printer->Print( diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index 798e8608..327c2053 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -39,9 +39,8 @@ #include #include #include -#include +#include #include -#include namespace google { namespace protobuf { @@ -49,6 +48,7 @@ namespace compiler { namespace java { using internal::WireFormat; +using internal::WireFormatLite; namespace { @@ -121,16 +121,6 @@ const char* GetCapitalizedType(const FieldDescriptor* field) { return NULL; } -bool AllPrintableAscii(const string& text) { - // Cannot use isprint() because it's locale-specific. :( - for (int i = 0; i < text.size(); i++) { - if ((text[i] < 0x20) || text[i] >= 0x7F) { - return false; - } - } - return true; -} - // For encodings with fixed sizes, returns that size in bytes. Otherwise // returns -1. int FixedSize(FieldDescriptor::Type type) { @@ -141,14 +131,14 @@ int FixedSize(FieldDescriptor::Type type) { case FieldDescriptor::TYPE_UINT64 : return -1; case FieldDescriptor::TYPE_SINT32 : return -1; case FieldDescriptor::TYPE_SINT64 : return -1; - case FieldDescriptor::TYPE_FIXED32 : return WireFormat::kFixed32Size; - case FieldDescriptor::TYPE_FIXED64 : return WireFormat::kFixed64Size; - case FieldDescriptor::TYPE_SFIXED32: return WireFormat::kSFixed32Size; - case FieldDescriptor::TYPE_SFIXED64: return WireFormat::kSFixed64Size; - case FieldDescriptor::TYPE_FLOAT : return WireFormat::kFloatSize; - case FieldDescriptor::TYPE_DOUBLE : return WireFormat::kDoubleSize; - - case FieldDescriptor::TYPE_BOOL : return WireFormat::kBoolSize; + case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; + case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; + case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; + case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; + case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; + case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; + + case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; case FieldDescriptor::TYPE_ENUM : return -1; case FieldDescriptor::TYPE_STRING : return -1; @@ -163,64 +153,6 @@ int FixedSize(FieldDescriptor::Type type) { return -1; } -string DefaultValue(const FieldDescriptor* field) { - // Switch on cpp_type since we need to know which default_value_* method - // of FieldDescriptor to call. - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: - return SimpleItoa(field->default_value_int32()); - case FieldDescriptor::CPPTYPE_UINT32: - // Need to print as a signed int since Java has no unsigned. - return SimpleItoa(static_cast(field->default_value_uint32())); - case FieldDescriptor::CPPTYPE_INT64: - return SimpleItoa(field->default_value_int64()) + "L"; - case FieldDescriptor::CPPTYPE_UINT64: - return SimpleItoa(static_cast(field->default_value_uint64())) + - "L"; - case FieldDescriptor::CPPTYPE_DOUBLE: - return SimpleDtoa(field->default_value_double()) + "D"; - case FieldDescriptor::CPPTYPE_FLOAT: - return SimpleFtoa(field->default_value_float()) + "F"; - case FieldDescriptor::CPPTYPE_BOOL: - return field->default_value_bool() ? "true" : "false"; - case FieldDescriptor::CPPTYPE_STRING: { - bool isBytes = field->type() == FieldDescriptor::TYPE_BYTES; - - if (!isBytes && AllPrintableAscii(field->default_value_string())) { - // All chars are ASCII and printable. In this case CEscape() works - // fine (it will only escape quotes and backslashes). - // Note: If this "optimization" is removed, DescriptorProtos will - // no longer be able to initialize itself due to bootstrapping - // problems. - return "\"" + CEscape(field->default_value_string()) + "\""; - } - - if (isBytes && !field->has_default_value()) { - return "com.google.protobuf.ByteString.EMPTY"; - } - - // Escaping strings correctly for Java and generating efficient - // initializers for ByteStrings are both tricky. We can sidestep the - // whole problem by just grabbing the default value from the descriptor. - return strings::Substitute( - "(($0) $1.getDescriptor().getFields().get($2).getDefaultValue())", - isBytes ? "com.google.protobuf.ByteString" : "java.lang.String", - ClassName(field->containing_type()), field->index()); - } - - case FieldDescriptor::CPPTYPE_ENUM: - case FieldDescriptor::CPPTYPE_MESSAGE: - GOOGLE_LOG(FATAL) << "Can't get here."; - return ""; - - // No default because we want the compiler to complain if any new - // types are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return ""; -} - void SetPrimitiveVariables(const FieldDescriptor* descriptor, map* variables) { (*variables)["name"] = @@ -285,8 +217,17 @@ GenerateBuilderMembers(io::Printer* printer) const { " return this;\n" "}\n" "public Builder clear$capitalized_name$() {\n" - " result.has$capitalized_name$ = false;\n" - " result.$name$_ = $default$;\n" + " result.has$capitalized_name$ = false;\n"); + if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + // The default value is not a simple literal so we want to avoid executing + // it multiple times. Instead, get the default out of the default instance. + printer->Print(variables_, + " result.$name$_ = getDefaultInstance().get$capitalized_name$();\n"); + } else { + printer->Print(variables_, + " result.$name$_ = $default$;\n"); + } + printer->Print(variables_, " return this;\n" "}\n"); } @@ -355,7 +296,7 @@ GenerateMembers(io::Printer* printer) const { "}\n"); if (descriptor_->options().packed() && - descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + HasGeneratedMethods(descriptor_->containing_type())) { printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); } diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index e9e01545..02304d6d 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -661,7 +661,7 @@ bool Parser::ParseOptionAssignment(Message* options) { GOOGLE_CHECK(uninterpreted_option_field != NULL) << "No field named \"uninterpreted_option\" in the Options proto."; - UninterpretedOption* uninterpreted_option = ::google::protobuf::down_cast( + UninterpretedOption* uninterpreted_option = down_cast( options->GetReflection()->AddMessage(options, uninterpreted_option_field)); diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index dd7f28c8..f82a3450 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -798,7 +798,7 @@ namespace { EncodedDescriptorDatabase* generated_database_ = NULL; DescriptorPool* generated_pool_ = NULL; -GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_); +GoogleOnceType generated_pool_init_; void DeleteGeneratedPool() { delete generated_database_; @@ -814,7 +814,7 @@ void InitGeneratedPool() { } inline void InitGeneratedPoolOnce() { - GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool); + ::google::protobuf::GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool); } } // anonymous namespace @@ -1859,7 +1859,11 @@ class DescriptorBuilder { // dependency of this file, it will fail, but will set // possible_undeclared_dependency_ to point at that file. This is only used // by AddNotDefinedError() to report a more useful error message. + // possible_undeclared_dependency_name_ is the name of the symbol that was + // actually found in possible_undeclared_dependency_, which may be a parent + // of the symbol actually looked for. const FileDescriptor* possible_undeclared_dependency_; + string possible_undeclared_dependency_name_; void AddError(const string& element_name, const Message& descriptor, @@ -2062,7 +2066,7 @@ class DescriptorBuilder { Message* options); // A recursive helper function that drills into the intermediate fields - // in unknown_fields to check if field #field_number is set on the + // in unknown_fields to check if field innermost_field is set on the // innermost message. Returns false and sets an error if so. bool ExamineIfOptionIsSet( vector::const_iterator intermediate_fields_iter, @@ -2233,8 +2237,9 @@ void DescriptorBuilder::AddNotDefinedError( "\"" + undefined_symbol + "\" is not defined."); } else { AddError(element_name, descriptor, location, - "\"" + undefined_symbol + "\" seems to be defined in \"" - + possible_undeclared_dependency_->name() + "\", which is not " + "\"" + possible_undeclared_dependency_name_ + + "\" seems to be defined in \"" + + possible_undeclared_dependency_->name() + "\", which is not " "imported by \"" + filename_ + "\". To use it here, please " "add the necessary import."); } @@ -2295,11 +2300,16 @@ Symbol DescriptorBuilder::FindSymbol(const string& name) { // symbol unless none of the dependencies define it. if (IsInPackage(file_, name)) return result; for (int i = 0; i < file_->dependency_count(); i++) { - if (IsInPackage(file_->dependency(i), name)) return result; + // Note: A dependency may be NULL if it was not found or had errors. + if (file_->dependency(i) != NULL && + IsInPackage(file_->dependency(i), name)) { + return result; + } } } possible_undeclared_dependency_ = file; + possible_undeclared_dependency_name_ = name; return kNullSymbol; } @@ -3592,12 +3602,38 @@ void DescriptorBuilder::CrossLinkMethod( proto.array_name(i)); \ } +// Determine if the file uses optimize_for = LITE_RUNTIME, being careful to +// avoid problems that exist at init time. +static bool IsLite(const FileDescriptor* file) { + // TODO(kenton): I don't even remember how many of these conditions are + // actually possible. I'm just being super-safe. + return file != NULL && + &file->options() != NULL && + &file->options() != &FileOptions::default_instance() && + file->options().optimize_for() == FileOptions::LITE_RUNTIME; +} + void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file, const FileDescriptorProto& proto) { VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message); VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum); VALIDATE_OPTIONS_FROM_ARRAY(file, service, Service); VALIDATE_OPTIONS_FROM_ARRAY(file, extension, Field); + + // Lite files can only be imported by other Lite files. + if (!IsLite(file)) { + for (int i = 0; i < file->dependency_count(); i++) { + if (IsLite(file->dependency(i))) { + AddError( + file->name(), proto, + DescriptorPool::ErrorCollector::OTHER, + "Files that do not use optimize_for = LITE_RUNTIME cannot import " + "files which do use this option. This file is not lite, but it " + "imports \"" + file->dependency(i)->name() + "\" which is."); + break; + } + } + } } void DescriptorBuilder::ValidateMessageOptions(Descriptor* message, @@ -3647,6 +3683,17 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field, "MessageSets cannot have fields, only extensions."); } } + + // Lite extensions can only be of Lite types. + if (IsLite(field->file()) && + field->containing_type_ != NULL && + !IsLite(field->containing_type()->file())) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::EXTENDEE, + "Extensions to non-lite types can only be declared in non-lite " + "files. Note that you cannot extend a non-lite type to contain " + "a lite type, but the reverse is allowed."); + } } void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm, @@ -3660,6 +3707,12 @@ void DescriptorBuilder::ValidateEnumValueOptions( } void DescriptorBuilder::ValidateServiceOptions(ServiceDescriptor* service, const ServiceDescriptorProto& proto) { + if (IsLite(service->file())) { + AddError(service->full_name(), proto, + DescriptorPool::ErrorCollector::NAME, + "Files with optimize_for = LITE_RUNTIME cannot define services."); + } + VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method); } @@ -3761,7 +3814,7 @@ bool DescriptorBuilder::OptionInterpreter::InterpretOptions( const int num_uninterpreted_options = original_options->GetReflection()-> FieldSize(*original_options, original_uninterpreted_options_field); for (int i = 0; i < num_uninterpreted_options; ++i) { - uninterpreted_option_ = ::google::protobuf::down_cast( + uninterpreted_option_ = down_cast( &original_options->GetReflection()->GetRepeatedMessage( *original_options, original_uninterpreted_options_field, i)); if (!InterpretSingleOption(options)) { @@ -4009,14 +4062,13 @@ bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet( const UnknownField* unknown_field = &unknown_fields.field(i); FieldDescriptor::Type type = (*intermediate_fields_iter)->type(); // Recurse into the next submessage. - ++intermediate_fields_iter; switch (type) { case FieldDescriptor::TYPE_MESSAGE: if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) { UnknownFieldSet intermediate_unknown_fields; if (intermediate_unknown_fields.ParseFromString( unknown_field->length_delimited()) && - !ExamineIfOptionIsSet(intermediate_fields_iter, + !ExamineIfOptionIsSet(intermediate_fields_iter + 1, intermediate_fields_end, innermost_field, debug_msg_name, intermediate_unknown_fields)) { @@ -4027,7 +4079,7 @@ bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet( case FieldDescriptor::TYPE_GROUP: if (unknown_field->type() == UnknownField::TYPE_GROUP) { - if (!ExamineIfOptionIsSet(intermediate_fields_iter, + if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1, intermediate_fields_end, innermost_field, debug_msg_name, unknown_field->group())) { @@ -4139,7 +4191,7 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue( option_field->full_name() + "\"."); } unknown_fields->AddFixed32(option_field->number(), - google::protobuf::internal::WireFormat::EncodeFloat(value)); + google::protobuf::internal::WireFormatLite::EncodeFloat(value)); break; } @@ -4156,7 +4208,7 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue( option_field->full_name() + "\"."); } unknown_fields->AddFixed64(option_field->number(), - google::protobuf::internal::WireFormat::EncodeDouble(value)); + google::protobuf::internal::WireFormatLite::EncodeDouble(value)); break; } @@ -4267,7 +4319,7 @@ void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value, case FieldDescriptor::TYPE_SINT32: unknown_fields->AddVarint(number, - google::protobuf::internal::WireFormat::ZigZagEncode32(value)); + google::protobuf::internal::WireFormatLite::ZigZagEncode32(value)); break; default: @@ -4289,7 +4341,7 @@ void DescriptorBuilder::OptionInterpreter::SetInt64(int number, int64 value, case FieldDescriptor::TYPE_SINT64: unknown_fields->AddVarint(number, - google::protobuf::internal::WireFormat::ZigZagEncode64(value)); + google::protobuf::internal::WireFormatLite::ZigZagEncode64(value)); break; default: diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 0caed839..a68a6a40 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -1,11 +1,13 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! +#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION #include "google/protobuf/descriptor.pb.h" #include -#include #include +#include +#include #include -#include +#include namespace google { namespace protobuf { @@ -268,8 +270,9 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { sizeof(FileOptions)); FileOptions_OptimizeMode_descriptor_ = FileOptions_descriptor_->enum_type(0); MessageOptions_descriptor_ = file->message_type(9); - static const int MessageOptions_offsets_[2] = { + static const int MessageOptions_offsets_[3] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, message_set_wire_format_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, no_standard_descriptor_accessor_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, uninterpreted_option_), }; MessageOptions_reflection_ = @@ -409,7 +412,7 @@ inline void protobuf_AssignDescriptorsOnce() { &protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto); } -void protobuf_RegisterTypes() { +void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( FileDescriptorSet_descriptor_, &FileDescriptorSet::default_instance()); @@ -549,42 +552,43 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "ptions\"\177\n\025MethodDescriptorProto\022\014\n\004name\030" "\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013output_type" "\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.protobu" - "f.MethodOptions\"\247\002\n\013FileOptions\022\024\n\014java_" + "f.MethodOptions\"\271\002\n\013FileOptions\022\024\n\014java_" "package\030\001 \001(\t\022\034\n\024java_outer_classname\030\010 " "\001(\t\022\"\n\023java_multiple_files\030\n \001(\010:\005false\022" "F\n\014optimize_for\030\t \001(\0162).google.protobuf." "FileOptions.OptimizeMode:\005SPEED\022C\n\024unint" "erpreted_option\030\347\007 \003(\0132$.google.protobuf" - ".UninterpretedOption\"(\n\014OptimizeMode\022\t\n\005" - "SPEED\020\001\022\r\n\tCODE_SIZE\020\002*\t\010\350\007\020\200\200\200\200\002\"\210\001\n\016Me" - "ssageOptions\022&\n\027message_set_wire_format\030" - "\001 \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 " + ".UninterpretedOption\":\n\014OptimizeMode\022\t\n\005" + "SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003" + "*\t\010\350\007\020\200\200\200\200\002\"\270\001\n\016MessageOptions\022&\n\027messag" + "e_set_wire_format\030\001 \001(\010:\005false\022.\n\037no_sta" + "ndard_descriptor_accessor\030\002 \001(\010:\005false\022C" + "\n\024uninterpreted_option\030\347\007 \003(\0132$.google.p" + "rotobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\200" + "\002\n\014FieldOptions\0222\n\005ctype\030\001 \001(\0162#.google." + "protobuf.FieldOptions.CType\022\016\n\006packed\030\002 " + "\001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\034\n\024experi" + "mental_map_key\030\t \001(\t\022C\n\024uninterpreted_op" + "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre" + "tedOption\"#\n\005CType\022\010\n\004CORD\020\001\022\020\n\014STRING_P" + "IECE\020\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022C\n\024unin" + "terpreted_option\030\347\007 \003(\0132$.google.protobu" + "f.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"b\n\020Enum" + "ValueOptions\022C\n\024uninterpreted_option\030\347\007 " "\003(\0132$.google.protobuf.UninterpretedOptio" - "n*\t\010\350\007\020\200\200\200\200\002\"\200\002\n\014FieldOptions\0222\n\005ctype\030\001" - " \001(\0162#.google.protobuf.FieldOptions.CTyp" - "e\022\016\n\006packed\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005f" - "alse\022\034\n\024experimental_map_key\030\t \001(\t\022C\n\024un" - "interpreted_option\030\347\007 \003(\0132$.google.proto" - "buf.UninterpretedOption\"#\n\005CType\022\010\n\004CORD" - "\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumO" - "ptions\022C\n\024uninterpreted_option\030\347\007 \003(\0132$." - "google.protobuf.UninterpretedOption*\t\010\350\007" - "\020\200\200\200\200\002\"b\n\020EnumValueOptions\022C\n\024uninterpre" - "ted_option\030\347\007 \003(\0132$.google.protobuf.Unin" - "terpretedOption*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceOpt" - "ions\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go" - "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200" - "\200\200\200\002\"_\n\rMethodOptions\022C\n\024uninterpreted_o" - "ption\030\347\007 \003(\0132$.google.protobuf.Uninterpr" - "etedOption*\t\010\350\007\020\200\200\200\200\002\"\205\002\n\023UninterpretedO" - "ption\022;\n\004name\030\002 \003(\0132-.google.protobuf.Un" - "interpretedOption.NamePart\022\030\n\020identifier" - "_value\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004" - "\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014double_v" - "alue\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\0323\n\010Name" - "Part\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension\030" - "\002 \002(\010B)\n\023com.google.protobufB\020Descriptor" - "ProtosH\001", 3488); + "n*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceOptions\022C\n\024uninte" + "rpreted_option\030\347\007 \003(\0132$.google.protobuf." + "UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"_\n\rMethod" + "Options\022C\n\024uninterpreted_option\030\347\007 \003(\0132$" + ".google.protobuf.UninterpretedOption*\t\010\350" + "\007\020\200\200\200\200\002\"\205\002\n\023UninterpretedOption\022;\n\004name\030" + "\002 \003(\0132-.google.protobuf.UninterpretedOpt" + "ion.NamePart\022\030\n\020identifier_value\030\003 \001(\t\022\032" + "\n\022positive_int_value\030\004 \001(\004\022\032\n\022negative_i" + "nt_value\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014" + "string_value\030\007 \001(\014\0323\n\010NamePart\022\021\n\tname_p" + "art\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010B)\n\023com.g" + "oogle.protobufB\020DescriptorProtosH\001", 3554); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); @@ -640,15 +644,14 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fdescriptor_2eproto { const int FileDescriptorSet::kFileFieldNumber; #endif // !_MSC_VER -FileDescriptorSet::FileDescriptorSet() - : ::google::protobuf::Message() { +FileDescriptorSet::FileDescriptorSet() { SharedCtor(); } -void FileDescriptorSet::InitAsDefaultInstance() {} +void FileDescriptorSet::InitAsDefaultInstance() { +} -FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from) - : ::google::protobuf::Message() { +FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from) { SharedCtor(); MergeFrom(from); } @@ -693,16 +696,16 @@ bool FileDescriptorSet::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated .google.protobuf.FileDescriptorProto file = 1; case 1: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_file: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_file())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_file())); if (input->ExpectTag(10)) goto parse_file; if (input->ExpectAtEnd()) return true; break; @@ -710,8 +713,8 @@ bool FileDescriptorSet::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } DO_(::google::protobuf::internal::WireFormat::SkipField( @@ -734,7 +737,8 @@ void FileDescriptorSet::SerializeWithCachedSizes( // repeated .google.protobuf.FileDescriptorProto file = 1; for (int i = 0; i < this->file_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(1, this->file(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 1, this->file(i), output); } if (!unknown_fields().empty()) { @@ -747,7 +751,9 @@ void FileDescriptorSet::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // repeated .google.protobuf.FileDescriptorProto file = 1; for (int i = 0; i < this->file_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(1, this->file(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->file(i), target); } if (!unknown_fields().empty()) { @@ -764,7 +770,7 @@ int FileDescriptorSet::ByteSize() const { total_size += 1 * this->file_size(); for (int i = 0; i < this->file_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->file(i)); } @@ -824,15 +830,15 @@ void FileDescriptorSet::Swap(FileDescriptorSet* other) { } } -const ::google::protobuf::Descriptor* FileDescriptorSet::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* FileDescriptorSet::GetReflection() const { +::google::protobuf::Metadata FileDescriptorSet::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return FileDescriptorSet_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = FileDescriptorSet_descriptor_; + metadata.reflection = FileDescriptorSet_reflection_; + return metadata; } + // =================================================================== const ::std::string FileDescriptorProto::_default_name_; @@ -848,16 +854,15 @@ const int FileDescriptorProto::kExtensionFieldNumber; const int FileDescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER -FileDescriptorProto::FileDescriptorProto() - : ::google::protobuf::Message() { +FileDescriptorProto::FileDescriptorProto() { SharedCtor(); } -void FileDescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::FileOptions*>(&::google::protobuf::FileOptions::default_instance()); +void FileDescriptorProto::InitAsDefaultInstance() { + options_ = const_cast< ::google::protobuf::FileOptions*>(&::google::protobuf::FileOptions::default_instance()); } -FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from) - : ::google::protobuf::Message() { +FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from) { SharedCtor(); MergeFrom(from); } @@ -931,39 +936,50 @@ bool FileDescriptorProto::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(18)) goto parse_package; break; } // optional string package = 2; case 2: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_package: - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_package())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_package())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->package().data(), this->package().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(26)) goto parse_dependency; break; } // repeated string dependency = 3; case 3: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_dependency: - DO_(::google::protobuf::internal::WireFormat::ReadString( - input, add_dependency())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->add_dependency())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->dependency(0).data(), this->dependency(0).length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(26)) goto parse_dependency; if (input->ExpectTag(34)) goto parse_message_type; break; @@ -971,13 +987,13 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.DescriptorProto message_type = 4; case 4: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_message_type: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_message_type())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_message_type())); if (input->ExpectTag(34)) goto parse_message_type; if (input->ExpectTag(42)) goto parse_enum_type; break; @@ -985,13 +1001,13 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; case 5: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_enum_type: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_enum_type())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_enum_type())); if (input->ExpectTag(42)) goto parse_enum_type; if (input->ExpectTag(50)) goto parse_service; break; @@ -999,13 +1015,13 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.ServiceDescriptorProto service = 6; case 6: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_service: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_service())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_service())); if (input->ExpectTag(50)) goto parse_service; if (input->ExpectTag(58)) goto parse_extension; break; @@ -1013,13 +1029,13 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.FieldDescriptorProto extension = 7; case 7: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_extension: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_extension())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_extension())); if (input->ExpectTag(58)) goto parse_extension; if (input->ExpectTag(66)) goto parse_options; break; @@ -1027,12 +1043,12 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.FileOptions options = 8; case 8: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_options: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); if (input->ExpectAtEnd()) return true; break; @@ -1040,8 +1056,8 @@ bool FileDescriptorProto::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } DO_(::google::protobuf::internal::WireFormat::SkipField( @@ -1064,42 +1080,59 @@ void FileDescriptorProto::SerializeWithCachedSizes( // optional string name = 1; if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); } // optional string package = 2; if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::WriteString(2, this->package(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->package().data(), this->package().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->package(), output); } // repeated string dependency = 3; for (int i = 0; i < this->dependency_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteString(3, this->dependency(i), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->dependency(i).data(), this->dependency(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 3, this->dependency(i), output); } // repeated .google.protobuf.DescriptorProto message_type = 4; for (int i = 0; i < this->message_type_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(4, this->message_type(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 4, this->message_type(i), output); } // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; for (int i = 0; i < this->enum_type_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(5, this->enum_type(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 5, this->enum_type(i), output); } // repeated .google.protobuf.ServiceDescriptorProto service = 6; for (int i = 0; i < this->service_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(6, this->service(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 6, this->service(i), output); } // repeated .google.protobuf.FieldDescriptorProto extension = 7; for (int i = 0; i < this->extension_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(7, this->extension(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 7, this->extension(i), output); } // optional .google.protobuf.FileOptions options = 8; if (_has_bit(7)) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(8, this->options(), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 8, this->options(), output); } if (!unknown_fields().empty()) { @@ -1112,42 +1145,66 @@ void FileDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // optional string name = 1; if (_has_bit(0)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); } // optional string package = 2; if (_has_bit(1)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(2, this->package(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->package().data(), this->package().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->package(), target); } // repeated string dependency = 3; for (int i = 0; i < this->dependency_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(3, this->dependency(i), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->dependency(i).data(), this->dependency(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = ::google::protobuf::internal::WireFormatLite:: + WriteStringToArray(3, this->dependency(i), target); } // repeated .google.protobuf.DescriptorProto message_type = 4; for (int i = 0; i < this->message_type_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(4, this->message_type(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 4, this->message_type(i), target); } // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; for (int i = 0; i < this->enum_type_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(5, this->enum_type(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 5, this->enum_type(i), target); } // repeated .google.protobuf.ServiceDescriptorProto service = 6; for (int i = 0; i < this->service_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(6, this->service(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 6, this->service(i), target); } // repeated .google.protobuf.FieldDescriptorProto extension = 7; for (int i = 0; i < this->extension_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(7, this->extension(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 7, this->extension(i), target); } // optional .google.protobuf.FileOptions options = 8; if (_has_bit(7)) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(8, this->options(), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 8, this->options(), target); } if (!unknown_fields().empty()) { @@ -1164,19 +1221,21 @@ int FileDescriptorProto::ByteSize() const { // optional string name = 1; if (has_name()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->name()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); } // optional string package = 2; if (has_package()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->package()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->package()); } // optional .google.protobuf.FileOptions options = 8; if (has_options()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->options()); } @@ -1184,7 +1243,7 @@ int FileDescriptorProto::ByteSize() const { // repeated string dependency = 3; total_size += 1 * this->dependency_size(); for (int i = 0; i < this->dependency_size(); i++) { - total_size += ::google::protobuf::internal::WireFormat::StringSize( + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( this->dependency(i)); } @@ -1192,7 +1251,7 @@ int FileDescriptorProto::ByteSize() const { total_size += 1 * this->message_type_size(); for (int i = 0; i < this->message_type_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->message_type(i)); } @@ -1200,7 +1259,7 @@ int FileDescriptorProto::ByteSize() const { total_size += 1 * this->enum_type_size(); for (int i = 0; i < this->enum_type_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->enum_type(i)); } @@ -1208,7 +1267,7 @@ int FileDescriptorProto::ByteSize() const { total_size += 1 * this->service_size(); for (int i = 0; i < this->service_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->service(i)); } @@ -1216,7 +1275,7 @@ int FileDescriptorProto::ByteSize() const { total_size += 1 * this->extension_size(); for (int i = 0; i < this->extension_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->extension(i)); } @@ -1310,15 +1369,15 @@ void FileDescriptorProto::Swap(FileDescriptorProto* other) { } } -const ::google::protobuf::Descriptor* FileDescriptorProto::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* FileDescriptorProto::GetReflection() const { +::google::protobuf::Metadata FileDescriptorProto::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return FileDescriptorProto_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = FileDescriptorProto_descriptor_; + metadata.reflection = FileDescriptorProto_reflection_; + return metadata; } + // =================================================================== #ifndef _MSC_VER @@ -1326,15 +1385,14 @@ const int DescriptorProto_ExtensionRange::kStartFieldNumber; const int DescriptorProto_ExtensionRange::kEndFieldNumber; #endif // !_MSC_VER -DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange() - : ::google::protobuf::Message() { +DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange() { SharedCtor(); } -void DescriptorProto_ExtensionRange::InitAsDefaultInstance() {} +void DescriptorProto_ExtensionRange::InitAsDefaultInstance() { +} -DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from) - : ::google::protobuf::Message() { +DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from) { SharedCtor(); MergeFrom(from); } @@ -1384,14 +1442,14 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional int32 start = 1; case 1: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } - DO_(::google::protobuf::internal::WireFormat::ReadInt32( + DO_(::google::protobuf::internal::WireFormatLite::ReadInt32( input, &start_)); _set_bit(0); if (input->ExpectTag(16)) goto parse_end; @@ -1400,12 +1458,12 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream( // optional int32 end = 2; case 2: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } parse_end: - DO_(::google::protobuf::internal::WireFormat::ReadInt32( + DO_(::google::protobuf::internal::WireFormatLite::ReadInt32( input, &end_)); _set_bit(1); if (input->ExpectAtEnd()) return true; @@ -1414,8 +1472,8 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } DO_(::google::protobuf::internal::WireFormat::SkipField( @@ -1438,12 +1496,12 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes( // optional int32 start = 1; if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::WriteInt32(1, this->start(), output); + ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output); } // optional int32 end = 2; if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::WriteInt32(2, this->end(), output); + ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output); } if (!unknown_fields().empty()) { @@ -1456,12 +1514,12 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // optional int32 start = 1; if (_has_bit(0)) { - target = ::google::protobuf::internal::WireFormat::WriteInt32ToArray(1, this->start(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target); } // optional int32 end = 2; if (_has_bit(1)) { - target = ::google::protobuf::internal::WireFormat::WriteInt32ToArray(2, this->end(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target); } if (!unknown_fields().empty()) { @@ -1478,14 +1536,14 @@ int DescriptorProto_ExtensionRange::ByteSize() const { // optional int32 start = 1; if (has_start()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::Int32Size( + ::google::protobuf::internal::WireFormatLite::Int32Size( this->start()); } // optional int32 end = 2; if (has_end()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::Int32Size( + ::google::protobuf::internal::WireFormatLite::Int32Size( this->end()); } @@ -1551,15 +1609,15 @@ void DescriptorProto_ExtensionRange::Swap(DescriptorProto_ExtensionRange* other) } } -const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* DescriptorProto_ExtensionRange::GetReflection() const { +::google::protobuf::Metadata DescriptorProto_ExtensionRange::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return DescriptorProto_ExtensionRange_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = DescriptorProto_ExtensionRange_descriptor_; + metadata.reflection = DescriptorProto_ExtensionRange_reflection_; + return metadata; } + // ------------------------------------------------------------------- const ::std::string DescriptorProto::_default_name_; @@ -1573,16 +1631,15 @@ const int DescriptorProto::kExtensionRangeFieldNumber; const int DescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER -DescriptorProto::DescriptorProto() - : ::google::protobuf::Message() { +DescriptorProto::DescriptorProto() { SharedCtor(); } -void DescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::MessageOptions*>(&::google::protobuf::MessageOptions::default_instance()); +void DescriptorProto::InitAsDefaultInstance() { + options_ = const_cast< ::google::protobuf::MessageOptions*>(&::google::protobuf::MessageOptions::default_instance()); } -DescriptorProto::DescriptorProto(const DescriptorProto& from) - : ::google::protobuf::Message() { +DescriptorProto::DescriptorProto(const DescriptorProto& from) { SharedCtor(); MergeFrom(from); } @@ -1647,27 +1704,31 @@ bool DescriptorProto::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(18)) goto parse_field; break; } // repeated .google.protobuf.FieldDescriptorProto field = 2; case 2: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_field: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_field())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_field())); if (input->ExpectTag(18)) goto parse_field; if (input->ExpectTag(26)) goto parse_nested_type; break; @@ -1675,13 +1736,13 @@ bool DescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.DescriptorProto nested_type = 3; case 3: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_nested_type: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_nested_type())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_nested_type())); if (input->ExpectTag(26)) goto parse_nested_type; if (input->ExpectTag(34)) goto parse_enum_type; break; @@ -1689,13 +1750,13 @@ bool DescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; case 4: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_enum_type: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_enum_type())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_enum_type())); if (input->ExpectTag(34)) goto parse_enum_type; if (input->ExpectTag(42)) goto parse_extension_range; break; @@ -1703,13 +1764,13 @@ bool DescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; case 5: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_extension_range: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_extension_range())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_extension_range())); if (input->ExpectTag(42)) goto parse_extension_range; if (input->ExpectTag(50)) goto parse_extension; break; @@ -1717,13 +1778,13 @@ bool DescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.FieldDescriptorProto extension = 6; case 6: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_extension: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_extension())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_extension())); if (input->ExpectTag(50)) goto parse_extension; if (input->ExpectTag(58)) goto parse_options; break; @@ -1731,12 +1792,12 @@ bool DescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.MessageOptions options = 7; case 7: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_options: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); if (input->ExpectAtEnd()) return true; break; @@ -1744,8 +1805,8 @@ bool DescriptorProto::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } DO_(::google::protobuf::internal::WireFormat::SkipField( @@ -1768,37 +1829,47 @@ void DescriptorProto::SerializeWithCachedSizes( // optional string name = 1; if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); } // repeated .google.protobuf.FieldDescriptorProto field = 2; for (int i = 0; i < this->field_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->field(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 2, this->field(i), output); } // repeated .google.protobuf.DescriptorProto nested_type = 3; for (int i = 0; i < this->nested_type_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->nested_type(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 3, this->nested_type(i), output); } // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; for (int i = 0; i < this->enum_type_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(4, this->enum_type(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 4, this->enum_type(i), output); } // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; for (int i = 0; i < this->extension_range_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(5, this->extension_range(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 5, this->extension_range(i), output); } // repeated .google.protobuf.FieldDescriptorProto extension = 6; for (int i = 0; i < this->extension_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(6, this->extension(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 6, this->extension(i), output); } // optional .google.protobuf.MessageOptions options = 7; if (_has_bit(6)) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(7, this->options(), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 7, this->options(), output); } if (!unknown_fields().empty()) { @@ -1811,37 +1882,54 @@ void DescriptorProto::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // optional string name = 1; if (_has_bit(0)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); } // repeated .google.protobuf.FieldDescriptorProto field = 2; for (int i = 0; i < this->field_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(2, this->field(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->field(i), target); } // repeated .google.protobuf.DescriptorProto nested_type = 3; for (int i = 0; i < this->nested_type_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(3, this->nested_type(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 3, this->nested_type(i), target); } // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; for (int i = 0; i < this->enum_type_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(4, this->enum_type(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 4, this->enum_type(i), target); } // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; for (int i = 0; i < this->extension_range_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(5, this->extension_range(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 5, this->extension_range(i), target); } // repeated .google.protobuf.FieldDescriptorProto extension = 6; for (int i = 0; i < this->extension_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(6, this->extension(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 6, this->extension(i), target); } // optional .google.protobuf.MessageOptions options = 7; if (_has_bit(6)) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(7, this->options(), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 7, this->options(), target); } if (!unknown_fields().empty()) { @@ -1858,13 +1946,14 @@ int DescriptorProto::ByteSize() const { // optional string name = 1; if (has_name()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->name()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); } // optional .google.protobuf.MessageOptions options = 7; if (has_options()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->options()); } @@ -1873,7 +1962,7 @@ int DescriptorProto::ByteSize() const { total_size += 1 * this->field_size(); for (int i = 0; i < this->field_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->field(i)); } @@ -1881,7 +1970,7 @@ int DescriptorProto::ByteSize() const { total_size += 1 * this->extension_size(); for (int i = 0; i < this->extension_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->extension(i)); } @@ -1889,7 +1978,7 @@ int DescriptorProto::ByteSize() const { total_size += 1 * this->nested_type_size(); for (int i = 0; i < this->nested_type_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->nested_type(i)); } @@ -1897,7 +1986,7 @@ int DescriptorProto::ByteSize() const { total_size += 1 * this->enum_type_size(); for (int i = 0; i < this->enum_type_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->enum_type(i)); } @@ -1905,7 +1994,7 @@ int DescriptorProto::ByteSize() const { total_size += 1 * this->extension_range_size(); for (int i = 0; i < this->extension_range_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->extension_range(i)); } @@ -1995,15 +2084,15 @@ void DescriptorProto::Swap(DescriptorProto* other) { } } -const ::google::protobuf::Descriptor* DescriptorProto::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* DescriptorProto::GetReflection() const { +::google::protobuf::Metadata DescriptorProto::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return DescriptorProto_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = DescriptorProto_descriptor_; + metadata.reflection = DescriptorProto_reflection_; + return metadata; } + // =================================================================== const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor() { @@ -2095,16 +2184,15 @@ const int FieldDescriptorProto::kDefaultValueFieldNumber; const int FieldDescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER -FieldDescriptorProto::FieldDescriptorProto() - : ::google::protobuf::Message() { +FieldDescriptorProto::FieldDescriptorProto() { SharedCtor(); } -void FieldDescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::FieldOptions*>(&::google::protobuf::FieldOptions::default_instance()); +void FieldDescriptorProto::InitAsDefaultInstance() { + options_ = const_cast< ::google::protobuf::FieldOptions*>(&::google::protobuf::FieldOptions::default_instance()); } -FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from) - : ::google::protobuf::Message() { +FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from) { SharedCtor(); MergeFrom(from); } @@ -2197,38 +2285,46 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(18)) goto parse_extendee; break; } // optional string extendee = 2; case 2: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_extendee: - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_extendee())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_extendee())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->extendee().data(), this->extendee().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(24)) goto parse_number; break; } // optional int32 number = 3; case 3: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } parse_number: - DO_(::google::protobuf::internal::WireFormat::ReadInt32( + DO_(::google::protobuf::internal::WireFormatLite::ReadInt32( input, &number_)); _set_bit(1); if (input->ExpectTag(32)) goto parse_label; @@ -2237,13 +2333,13 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.FieldDescriptorProto.Label label = 4; case 4: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } parse_label: int value; - DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value)); + DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value)); if (::google::protobuf::FieldDescriptorProto_Label_IsValid(value)) { set_label(static_cast< ::google::protobuf::FieldDescriptorProto_Label >(value)); } else { @@ -2255,13 +2351,13 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.FieldDescriptorProto.Type type = 5; case 5: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } parse_type: int value; - DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value)); + DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value)); if (::google::protobuf::FieldDescriptorProto_Type_IsValid(value)) { set_type(static_cast< ::google::protobuf::FieldDescriptorProto_Type >(value)); } else { @@ -2273,36 +2369,44 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( // optional string type_name = 6; case 6: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_type_name: - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_type_name())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_type_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->type_name().data(), this->type_name().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(58)) goto parse_default_value; break; } // optional string default_value = 7; case 7: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_default_value: - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_default_value())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_default_value())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->default_value().data(), this->default_value().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(66)) goto parse_options; break; } // optional .google.protobuf.FieldOptions options = 8; case 8: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_options: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); if (input->ExpectAtEnd()) return true; break; @@ -2310,8 +2414,8 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } DO_(::google::protobuf::internal::WireFormat::SkipField( @@ -2334,42 +2438,61 @@ void FieldDescriptorProto::SerializeWithCachedSizes( // optional string name = 1; if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); } // optional string extendee = 2; if (_has_bit(5)) { - ::google::protobuf::internal::WireFormat::WriteString(2, this->extendee(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->extendee().data(), this->extendee().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->extendee(), output); } // optional int32 number = 3; if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::WriteInt32(3, this->number(), output); + ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->number(), output); } // optional .google.protobuf.FieldDescriptorProto.Label label = 4; if (_has_bit(2)) { - ::google::protobuf::internal::WireFormat::WriteEnum(4, this->label(), output); + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 4, this->label(), output); } // optional .google.protobuf.FieldDescriptorProto.Type type = 5; if (_has_bit(3)) { - ::google::protobuf::internal::WireFormat::WriteEnum(5, this->type(), output); + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 5, this->type(), output); } // optional string type_name = 6; if (_has_bit(4)) { - ::google::protobuf::internal::WireFormat::WriteString(6, this->type_name(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->type_name().data(), this->type_name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 6, this->type_name(), output); } // optional string default_value = 7; if (_has_bit(6)) { - ::google::protobuf::internal::WireFormat::WriteString(7, this->default_value(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->default_value().data(), this->default_value().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 7, this->default_value(), output); } // optional .google.protobuf.FieldOptions options = 8; if (_has_bit(7)) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(8, this->options(), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 8, this->options(), output); } if (!unknown_fields().empty()) { @@ -2382,42 +2505,66 @@ void FieldDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // optional string name = 1; if (_has_bit(0)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); } // optional string extendee = 2; if (_has_bit(5)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(2, this->extendee(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->extendee().data(), this->extendee().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->extendee(), target); } // optional int32 number = 3; if (_has_bit(1)) { - target = ::google::protobuf::internal::WireFormat::WriteInt32ToArray(3, this->number(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->number(), target); } // optional .google.protobuf.FieldDescriptorProto.Label label = 4; if (_has_bit(2)) { - target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(4, this->label(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 4, this->label(), target); } // optional .google.protobuf.FieldDescriptorProto.Type type = 5; if (_has_bit(3)) { - target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(5, this->type(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 5, this->type(), target); } // optional string type_name = 6; if (_has_bit(4)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(6, this->type_name(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->type_name().data(), this->type_name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 6, this->type_name(), target); } // optional string default_value = 7; if (_has_bit(6)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(7, this->default_value(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->default_value().data(), this->default_value().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 7, this->default_value(), target); } // optional .google.protobuf.FieldOptions options = 8; if (_has_bit(7)) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(8, this->options(), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 8, this->options(), target); } if (!unknown_fields().empty()) { @@ -2434,50 +2581,54 @@ int FieldDescriptorProto::ByteSize() const { // optional string name = 1; if (has_name()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->name()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); } // optional int32 number = 3; if (has_number()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::Int32Size( + ::google::protobuf::internal::WireFormatLite::Int32Size( this->number()); } // optional .google.protobuf.FieldDescriptorProto.Label label = 4; if (has_label()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::EnumSize(this->label()); + ::google::protobuf::internal::WireFormatLite::EnumSize(this->label()); } // optional .google.protobuf.FieldDescriptorProto.Type type = 5; if (has_type()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::EnumSize(this->type()); + ::google::protobuf::internal::WireFormatLite::EnumSize(this->type()); } // optional string type_name = 6; if (has_type_name()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->type_name()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->type_name()); } // optional string extendee = 2; if (has_extendee()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->extendee()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->extendee()); } // optional string default_value = 7; if (has_default_value()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->default_value()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->default_value()); } // optional .google.protobuf.FieldOptions options = 8; if (has_options()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->options()); } @@ -2570,15 +2721,15 @@ void FieldDescriptorProto::Swap(FieldDescriptorProto* other) { } } -const ::google::protobuf::Descriptor* FieldDescriptorProto::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* FieldDescriptorProto::GetReflection() const { +::google::protobuf::Metadata FieldDescriptorProto::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return FieldDescriptorProto_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = FieldDescriptorProto_descriptor_; + metadata.reflection = FieldDescriptorProto_reflection_; + return metadata; } + // =================================================================== const ::std::string EnumDescriptorProto::_default_name_; @@ -2588,16 +2739,15 @@ const int EnumDescriptorProto::kValueFieldNumber; const int EnumDescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER -EnumDescriptorProto::EnumDescriptorProto() - : ::google::protobuf::Message() { +EnumDescriptorProto::EnumDescriptorProto() { SharedCtor(); } -void EnumDescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::EnumOptions*>(&::google::protobuf::EnumOptions::default_instance()); +void EnumDescriptorProto::InitAsDefaultInstance() { + options_ = const_cast< ::google::protobuf::EnumOptions*>(&::google::protobuf::EnumOptions::default_instance()); } -EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from) - : ::google::protobuf::Message() { +EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from) { SharedCtor(); MergeFrom(from); } @@ -2658,27 +2808,31 @@ bool EnumDescriptorProto::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(18)) goto parse_value; break; } // repeated .google.protobuf.EnumValueDescriptorProto value = 2; case 2: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_value: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_value())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_value())); if (input->ExpectTag(18)) goto parse_value; if (input->ExpectTag(26)) goto parse_options; break; @@ -2686,12 +2840,12 @@ bool EnumDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.EnumOptions options = 3; case 3: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_options: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); if (input->ExpectAtEnd()) return true; break; @@ -2699,8 +2853,8 @@ bool EnumDescriptorProto::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } DO_(::google::protobuf::internal::WireFormat::SkipField( @@ -2723,17 +2877,23 @@ void EnumDescriptorProto::SerializeWithCachedSizes( // optional string name = 1; if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); } // repeated .google.protobuf.EnumValueDescriptorProto value = 2; for (int i = 0; i < this->value_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->value(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 2, this->value(i), output); } // optional .google.protobuf.EnumOptions options = 3; if (_has_bit(2)) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->options(), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 3, this->options(), output); } if (!unknown_fields().empty()) { @@ -2746,17 +2906,26 @@ void EnumDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // optional string name = 1; if (_has_bit(0)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); } // repeated .google.protobuf.EnumValueDescriptorProto value = 2; for (int i = 0; i < this->value_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(2, this->value(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->value(i), target); } // optional .google.protobuf.EnumOptions options = 3; if (_has_bit(2)) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(3, this->options(), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 3, this->options(), target); } if (!unknown_fields().empty()) { @@ -2773,13 +2942,14 @@ int EnumDescriptorProto::ByteSize() const { // optional string name = 1; if (has_name()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->name()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); } // optional .google.protobuf.EnumOptions options = 3; if (has_options()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->options()); } @@ -2788,7 +2958,7 @@ int EnumDescriptorProto::ByteSize() const { total_size += 1 * this->value_size(); for (int i = 0; i < this->value_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->value(i)); } @@ -2861,15 +3031,15 @@ void EnumDescriptorProto::Swap(EnumDescriptorProto* other) { } } -const ::google::protobuf::Descriptor* EnumDescriptorProto::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* EnumDescriptorProto::GetReflection() const { +::google::protobuf::Metadata EnumDescriptorProto::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return EnumDescriptorProto_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = EnumDescriptorProto_descriptor_; + metadata.reflection = EnumDescriptorProto_reflection_; + return metadata; } + // =================================================================== const ::std::string EnumValueDescriptorProto::_default_name_; @@ -2879,16 +3049,15 @@ const int EnumValueDescriptorProto::kNumberFieldNumber; const int EnumValueDescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER -EnumValueDescriptorProto::EnumValueDescriptorProto() - : ::google::protobuf::Message() { +EnumValueDescriptorProto::EnumValueDescriptorProto() { SharedCtor(); } -void EnumValueDescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::EnumValueOptions*>(&::google::protobuf::EnumValueOptions::default_instance()); +void EnumValueDescriptorProto::InitAsDefaultInstance() { + options_ = const_cast< ::google::protobuf::EnumValueOptions*>(&::google::protobuf::EnumValueOptions::default_instance()); } -EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProto& from) - : ::google::protobuf::Message() { +EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProto& from) { SharedCtor(); MergeFrom(from); } @@ -2950,26 +3119,30 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(16)) goto parse_number; break; } // optional int32 number = 2; case 2: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } parse_number: - DO_(::google::protobuf::internal::WireFormat::ReadInt32( + DO_(::google::protobuf::internal::WireFormatLite::ReadInt32( input, &number_)); _set_bit(1); if (input->ExpectTag(26)) goto parse_options; @@ -2978,12 +3151,12 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.EnumValueOptions options = 3; case 3: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_options: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); if (input->ExpectAtEnd()) return true; break; @@ -2991,8 +3164,8 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } DO_(::google::protobuf::internal::WireFormat::SkipField( @@ -3015,17 +3188,22 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes( // optional string name = 1; if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); } // optional int32 number = 2; if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::WriteInt32(2, this->number(), output); + ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->number(), output); } // optional .google.protobuf.EnumValueOptions options = 3; if (_has_bit(2)) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->options(), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 3, this->options(), output); } if (!unknown_fields().empty()) { @@ -3038,17 +3216,24 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // optional string name = 1; if (_has_bit(0)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); } // optional int32 number = 2; if (_has_bit(1)) { - target = ::google::protobuf::internal::WireFormat::WriteInt32ToArray(2, this->number(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->number(), target); } // optional .google.protobuf.EnumValueOptions options = 3; if (_has_bit(2)) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(3, this->options(), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 3, this->options(), target); } if (!unknown_fields().empty()) { @@ -3065,20 +3250,21 @@ int EnumValueDescriptorProto::ByteSize() const { // optional string name = 1; if (has_name()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->name()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); } // optional int32 number = 2; if (has_number()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::Int32Size( + ::google::protobuf::internal::WireFormatLite::Int32Size( this->number()); } // optional .google.protobuf.EnumValueOptions options = 3; if (has_options()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->options()); } @@ -3151,15 +3337,15 @@ void EnumValueDescriptorProto::Swap(EnumValueDescriptorProto* other) { } } -const ::google::protobuf::Descriptor* EnumValueDescriptorProto::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* EnumValueDescriptorProto::GetReflection() const { +::google::protobuf::Metadata EnumValueDescriptorProto::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return EnumValueDescriptorProto_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = EnumValueDescriptorProto_descriptor_; + metadata.reflection = EnumValueDescriptorProto_reflection_; + return metadata; } + // =================================================================== const ::std::string ServiceDescriptorProto::_default_name_; @@ -3169,16 +3355,15 @@ const int ServiceDescriptorProto::kMethodFieldNumber; const int ServiceDescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER -ServiceDescriptorProto::ServiceDescriptorProto() - : ::google::protobuf::Message() { +ServiceDescriptorProto::ServiceDescriptorProto() { SharedCtor(); } -void ServiceDescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::ServiceOptions*>(&::google::protobuf::ServiceOptions::default_instance()); +void ServiceDescriptorProto::InitAsDefaultInstance() { + options_ = const_cast< ::google::protobuf::ServiceOptions*>(&::google::protobuf::ServiceOptions::default_instance()); } -ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& from) - : ::google::protobuf::Message() { +ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& from) { SharedCtor(); MergeFrom(from); } @@ -3239,27 +3424,31 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(18)) goto parse_method; break; } // repeated .google.protobuf.MethodDescriptorProto method = 2; case 2: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_method: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_method())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_method())); if (input->ExpectTag(18)) goto parse_method; if (input->ExpectTag(26)) goto parse_options; break; @@ -3267,12 +3456,12 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.ServiceOptions options = 3; case 3: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_options: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); if (input->ExpectAtEnd()) return true; break; @@ -3280,8 +3469,8 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } DO_(::google::protobuf::internal::WireFormat::SkipField( @@ -3304,17 +3493,23 @@ void ServiceDescriptorProto::SerializeWithCachedSizes( // optional string name = 1; if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); } // repeated .google.protobuf.MethodDescriptorProto method = 2; for (int i = 0; i < this->method_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->method(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 2, this->method(i), output); } // optional .google.protobuf.ServiceOptions options = 3; if (_has_bit(2)) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->options(), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 3, this->options(), output); } if (!unknown_fields().empty()) { @@ -3327,17 +3522,26 @@ void ServiceDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // optional string name = 1; if (_has_bit(0)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); } // repeated .google.protobuf.MethodDescriptorProto method = 2; for (int i = 0; i < this->method_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(2, this->method(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->method(i), target); } // optional .google.protobuf.ServiceOptions options = 3; if (_has_bit(2)) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(3, this->options(), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 3, this->options(), target); } if (!unknown_fields().empty()) { @@ -3354,13 +3558,14 @@ int ServiceDescriptorProto::ByteSize() const { // optional string name = 1; if (has_name()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->name()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); } // optional .google.protobuf.ServiceOptions options = 3; if (has_options()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->options()); } @@ -3369,7 +3574,7 @@ int ServiceDescriptorProto::ByteSize() const { total_size += 1 * this->method_size(); for (int i = 0; i < this->method_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->method(i)); } @@ -3442,15 +3647,15 @@ void ServiceDescriptorProto::Swap(ServiceDescriptorProto* other) { } } -const ::google::protobuf::Descriptor* ServiceDescriptorProto::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* ServiceDescriptorProto::GetReflection() const { +::google::protobuf::Metadata ServiceDescriptorProto::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return ServiceDescriptorProto_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = ServiceDescriptorProto_descriptor_; + metadata.reflection = ServiceDescriptorProto_reflection_; + return metadata; } + // =================================================================== const ::std::string MethodDescriptorProto::_default_name_; @@ -3463,16 +3668,15 @@ const int MethodDescriptorProto::kOutputTypeFieldNumber; const int MethodDescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER -MethodDescriptorProto::MethodDescriptorProto() - : ::google::protobuf::Message() { +MethodDescriptorProto::MethodDescriptorProto() { SharedCtor(); } -void MethodDescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::MethodOptions*>(&::google::protobuf::MethodOptions::default_instance()); +void MethodDescriptorProto::InitAsDefaultInstance() { + options_ = const_cast< ::google::protobuf::MethodOptions*>(&::google::protobuf::MethodOptions::default_instance()); } -MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from) - : ::google::protobuf::Message() { +MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from) { SharedCtor(); MergeFrom(from); } @@ -3550,50 +3754,62 @@ bool MethodDescriptorProto::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(18)) goto parse_input_type; break; } // optional string input_type = 2; case 2: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_input_type: - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_input_type())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_input_type())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->input_type().data(), this->input_type().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(26)) goto parse_output_type; break; } // optional string output_type = 3; case 3: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_output_type: - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_output_type())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_output_type())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->output_type().data(), this->output_type().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(34)) goto parse_options; break; } // optional .google.protobuf.MethodOptions options = 4; case 4: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_options: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); if (input->ExpectAtEnd()) return true; break; @@ -3601,8 +3817,8 @@ bool MethodDescriptorProto::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } DO_(::google::protobuf::internal::WireFormat::SkipField( @@ -3625,22 +3841,35 @@ void MethodDescriptorProto::SerializeWithCachedSizes( // optional string name = 1; if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); } // optional string input_type = 2; if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::WriteString(2, this->input_type(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->input_type().data(), this->input_type().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->input_type(), output); } // optional string output_type = 3; if (_has_bit(2)) { - ::google::protobuf::internal::WireFormat::WriteString(3, this->output_type(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->output_type().data(), this->output_type().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 3, this->output_type(), output); } // optional .google.protobuf.MethodOptions options = 4; if (_has_bit(3)) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(4, this->options(), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 4, this->options(), output); } if (!unknown_fields().empty()) { @@ -3653,22 +3882,39 @@ void MethodDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // optional string name = 1; if (_has_bit(0)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); } // optional string input_type = 2; if (_has_bit(1)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(2, this->input_type(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->input_type().data(), this->input_type().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->input_type(), target); } // optional string output_type = 3; if (_has_bit(2)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(3, this->output_type(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->output_type().data(), this->output_type().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 3, this->output_type(), target); } // optional .google.protobuf.MethodOptions options = 4; if (_has_bit(3)) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(4, this->options(), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 4, this->options(), target); } if (!unknown_fields().empty()) { @@ -3685,25 +3931,28 @@ int MethodDescriptorProto::ByteSize() const { // optional string name = 1; if (has_name()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->name()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); } // optional string input_type = 2; if (has_input_type()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->input_type()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->input_type()); } // optional string output_type = 3; if (has_output_type()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->output_type()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->output_type()); } // optional .google.protobuf.MethodOptions options = 4; if (has_options()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->options()); } @@ -3780,15 +4029,15 @@ void MethodDescriptorProto::Swap(MethodDescriptorProto* other) { } } -const ::google::protobuf::Descriptor* MethodDescriptorProto::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* MethodDescriptorProto::GetReflection() const { +::google::protobuf::Metadata MethodDescriptorProto::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return MethodDescriptorProto_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = MethodDescriptorProto_descriptor_; + metadata.reflection = MethodDescriptorProto_reflection_; + return metadata; } + // =================================================================== const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor() { @@ -3799,6 +4048,7 @@ bool FileOptions_OptimizeMode_IsValid(int value) { switch(value) { case 1: case 2: + case 3: return true; default: return false; @@ -3808,6 +4058,7 @@ bool FileOptions_OptimizeMode_IsValid(int value) { #ifndef _MSC_VER const FileOptions_OptimizeMode FileOptions::SPEED; const FileOptions_OptimizeMode FileOptions::CODE_SIZE; +const FileOptions_OptimizeMode FileOptions::LITE_RUNTIME; const FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN; const FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX; #endif // _MSC_VER @@ -3821,15 +4072,14 @@ const int FileOptions::kOptimizeForFieldNumber; const int FileOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER -FileOptions::FileOptions() - : ::google::protobuf::Message() { +FileOptions::FileOptions() { SharedCtor(); } -void FileOptions::InitAsDefaultInstance() {} +void FileOptions::InitAsDefaultInstance() { +} -FileOptions::FileOptions(const FileOptions& from) - : ::google::protobuf::Message() { +FileOptions::FileOptions(const FileOptions& from) { SharedCtor(); MergeFrom(from); } @@ -3899,39 +4149,47 @@ bool FileOptions::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string java_package = 1; case 1: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_java_package())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_java_package())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->java_package().data(), this->java_package().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(66)) goto parse_java_outer_classname; break; } // optional string java_outer_classname = 8; case 8: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_java_outer_classname: - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_java_outer_classname())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_java_outer_classname())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->java_outer_classname().data(), this->java_outer_classname().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(72)) goto parse_optimize_for; break; } // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; case 9: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } parse_optimize_for: int value; - DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value)); + DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value)); if (::google::protobuf::FileOptions_OptimizeMode_IsValid(value)) { set_optimize_for(static_cast< ::google::protobuf::FileOptions_OptimizeMode >(value)); } else { @@ -3943,12 +4201,12 @@ bool FileOptions::MergePartialFromCodedStream( // optional bool java_multiple_files = 10 [default = false]; case 10: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } parse_java_multiple_files: - DO_(::google::protobuf::internal::WireFormat::ReadBool( + DO_(::google::protobuf::internal::WireFormatLite::ReadBool( input, &java_multiple_files_)); _set_bit(2); if (input->ExpectTag(7994)) goto parse_uninterpreted_option; @@ -3957,13 +4215,13 @@ bool FileOptions::MergePartialFromCodedStream( // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_uninterpreted_option: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_uninterpreted_option())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_uninterpreted_option())); if (input->ExpectTag(7994)) goto parse_uninterpreted_option; if (input->ExpectAtEnd()) return true; break; @@ -3971,8 +4229,8 @@ bool FileOptions::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } if ((8000u <= tag)) { @@ -4000,27 +4258,37 @@ void FileOptions::SerializeWithCachedSizes( // optional string java_package = 1; if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::WriteString(1, this->java_package(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->java_package().data(), this->java_package().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->java_package(), output); } // optional string java_outer_classname = 8; if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::WriteString(8, this->java_outer_classname(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->java_outer_classname().data(), this->java_outer_classname().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 8, this->java_outer_classname(), output); } // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; if (_has_bit(3)) { - ::google::protobuf::internal::WireFormat::WriteEnum(9, this->optimize_for(), output); + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 9, this->optimize_for(), output); } // optional bool java_multiple_files = 10 [default = false]; if (_has_bit(2)) { - ::google::protobuf::internal::WireFormat::WriteBool(10, this->java_multiple_files(), output); + ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->java_multiple_files(), output); } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 999, this->uninterpreted_option(i), output); } // Extension range [1000, 536870912) @@ -4037,27 +4305,40 @@ void FileOptions::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // optional string java_package = 1; if (_has_bit(0)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->java_package(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->java_package().data(), this->java_package().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->java_package(), target); } // optional string java_outer_classname = 8; if (_has_bit(1)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(8, this->java_outer_classname(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->java_outer_classname().data(), this->java_outer_classname().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 8, this->java_outer_classname(), target); } // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; if (_has_bit(3)) { - target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(9, this->optimize_for(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 9, this->optimize_for(), target); } // optional bool java_multiple_files = 10 [default = false]; if (_has_bit(2)) { - target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(10, this->java_multiple_files(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->java_multiple_files(), target); } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 999, this->uninterpreted_option(i), target); } // Extension range [1000, 536870912) @@ -4078,13 +4359,15 @@ int FileOptions::ByteSize() const { // optional string java_package = 1; if (has_java_package()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->java_package()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->java_package()); } // optional string java_outer_classname = 8; if (has_java_outer_classname()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->java_outer_classname()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->java_outer_classname()); } // optional bool java_multiple_files = 10 [default = false]; @@ -4095,7 +4378,7 @@ int FileOptions::ByteSize() const { // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; if (has_optimize_for()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::EnumSize(this->optimize_for()); + ::google::protobuf::internal::WireFormatLite::EnumSize(this->optimize_for()); } } @@ -4103,7 +4386,7 @@ int FileOptions::ByteSize() const { total_size += 2 * this->uninterpreted_option_size(); for (int i = 0; i < this->uninterpreted_option_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->uninterpreted_option(i)); } @@ -4186,31 +4469,31 @@ void FileOptions::Swap(FileOptions* other) { } } -const ::google::protobuf::Descriptor* FileOptions::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* FileOptions::GetReflection() const { +::google::protobuf::Metadata FileOptions::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return FileOptions_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = FileOptions_descriptor_; + metadata.reflection = FileOptions_reflection_; + return metadata; } + // =================================================================== #ifndef _MSC_VER const int MessageOptions::kMessageSetWireFormatFieldNumber; +const int MessageOptions::kNoStandardDescriptorAccessorFieldNumber; const int MessageOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER -MessageOptions::MessageOptions() - : ::google::protobuf::Message() { +MessageOptions::MessageOptions() { SharedCtor(); } -void MessageOptions::InitAsDefaultInstance() {} +void MessageOptions::InitAsDefaultInstance() { +} -MessageOptions::MessageOptions(const MessageOptions& from) - : ::google::protobuf::Message() { +MessageOptions::MessageOptions(const MessageOptions& from) { SharedCtor(); MergeFrom(from); } @@ -4218,6 +4501,7 @@ MessageOptions::MessageOptions(const MessageOptions& from) void MessageOptions::SharedCtor() { _cached_size_ = 0; message_set_wire_format_ = false; + no_standard_descriptor_accessor_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -4249,6 +4533,7 @@ void MessageOptions::Clear() { _extensions_.Clear(); if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { message_set_wire_format_ = false; + no_standard_descriptor_accessor_ = false; } uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); @@ -4260,29 +4545,43 @@ bool MessageOptions::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional bool message_set_wire_format = 1 [default = false]; case 1: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } - DO_(::google::protobuf::internal::WireFormat::ReadBool( + DO_(::google::protobuf::internal::WireFormatLite::ReadBool( input, &message_set_wire_format_)); _set_bit(0); + if (input->ExpectTag(16)) goto parse_no_standard_descriptor_accessor; + break; + } + + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + goto handle_uninterpreted; + } + parse_no_standard_descriptor_accessor: + DO_(::google::protobuf::internal::WireFormatLite::ReadBool( + input, &no_standard_descriptor_accessor_)); + _set_bit(1); if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_uninterpreted_option: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_uninterpreted_option())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_uninterpreted_option())); if (input->ExpectTag(7994)) goto parse_uninterpreted_option; if (input->ExpectAtEnd()) return true; break; @@ -4290,8 +4589,8 @@ bool MessageOptions::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } if ((8000u <= tag)) { @@ -4319,12 +4618,18 @@ void MessageOptions::SerializeWithCachedSizes( // optional bool message_set_wire_format = 1 [default = false]; if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::WriteBool(1, this->message_set_wire_format(), output); + ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output); + } + + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + if (_has_bit(1)) { + ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->no_standard_descriptor_accessor(), output); } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 999, this->uninterpreted_option(i), output); } // Extension range [1000, 536870912) @@ -4341,12 +4646,19 @@ void MessageOptions::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // optional bool message_set_wire_format = 1 [default = false]; if (_has_bit(0)) { - target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(1, this->message_set_wire_format(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->message_set_wire_format(), target); + } + + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + if (_has_bit(1)) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->no_standard_descriptor_accessor(), target); } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 999, this->uninterpreted_option(i), target); } // Extension range [1000, 536870912) @@ -4369,12 +4681,17 @@ int MessageOptions::ByteSize() const { total_size += 1 + 1; } + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + if (has_no_standard_descriptor_accessor()) { + total_size += 1 + 1; + } + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); for (int i = 0; i < this->uninterpreted_option_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->uninterpreted_option(i)); } @@ -4408,6 +4725,9 @@ void MessageOptions::MergeFrom(const MessageOptions& from) { if (from._has_bit(0)) { set_message_set_wire_format(from.message_set_wire_format()); } + if (from._has_bit(1)) { + set_no_standard_descriptor_accessor(from.no_standard_descriptor_accessor()); + } } _extensions_.MergeFrom(from._extensions_); mutable_unknown_fields()->MergeFrom(from.unknown_fields()); @@ -4437,6 +4757,7 @@ bool MessageOptions::IsInitialized() const { void MessageOptions::Swap(MessageOptions* other) { if (other != this) { std::swap(message_set_wire_format_, other->message_set_wire_format_); + std::swap(no_standard_descriptor_accessor_, other->no_standard_descriptor_accessor_); uninterpreted_option_.Swap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -4445,15 +4766,15 @@ void MessageOptions::Swap(MessageOptions* other) { } } -const ::google::protobuf::Descriptor* MessageOptions::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* MessageOptions::GetReflection() const { +::google::protobuf::Metadata MessageOptions::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return MessageOptions_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = MessageOptions_descriptor_; + metadata.reflection = MessageOptions_reflection_; + return metadata; } + // =================================================================== const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor() { @@ -4485,15 +4806,14 @@ const int FieldOptions::kExperimentalMapKeyFieldNumber; const int FieldOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER -FieldOptions::FieldOptions() - : ::google::protobuf::Message() { +FieldOptions::FieldOptions() { SharedCtor(); } -void FieldOptions::InitAsDefaultInstance() {} +void FieldOptions::InitAsDefaultInstance() { +} -FieldOptions::FieldOptions(const FieldOptions& from) - : ::google::protobuf::Message() { +FieldOptions::FieldOptions(const FieldOptions& from) { SharedCtor(); MergeFrom(from); } @@ -4556,15 +4876,15 @@ bool FieldOptions::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional .google.protobuf.FieldOptions.CType ctype = 1; case 1: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } int value; - DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value)); + DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value)); if (::google::protobuf::FieldOptions_CType_IsValid(value)) { set_ctype(static_cast< ::google::protobuf::FieldOptions_CType >(value)); } else { @@ -4576,12 +4896,12 @@ bool FieldOptions::MergePartialFromCodedStream( // optional bool packed = 2; case 2: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } parse_packed: - DO_(::google::protobuf::internal::WireFormat::ReadBool( + DO_(::google::protobuf::internal::WireFormatLite::ReadBool( input, &packed_)); _set_bit(1); if (input->ExpectTag(24)) goto parse_deprecated; @@ -4590,12 +4910,12 @@ bool FieldOptions::MergePartialFromCodedStream( // optional bool deprecated = 3 [default = false]; case 3: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } parse_deprecated: - DO_(::google::protobuf::internal::WireFormat::ReadBool( + DO_(::google::protobuf::internal::WireFormatLite::ReadBool( input, &deprecated_)); _set_bit(2); if (input->ExpectTag(74)) goto parse_experimental_map_key; @@ -4604,25 +4924,29 @@ bool FieldOptions::MergePartialFromCodedStream( // optional string experimental_map_key = 9; case 9: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_experimental_map_key: - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_experimental_map_key())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_experimental_map_key())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->experimental_map_key().data(), this->experimental_map_key().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_uninterpreted_option: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_uninterpreted_option())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_uninterpreted_option())); if (input->ExpectTag(7994)) goto parse_uninterpreted_option; if (input->ExpectAtEnd()) return true; break; @@ -4630,8 +4954,8 @@ bool FieldOptions::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } if ((8000u <= tag)) { @@ -4659,27 +4983,33 @@ void FieldOptions::SerializeWithCachedSizes( // optional .google.protobuf.FieldOptions.CType ctype = 1; if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::WriteEnum(1, this->ctype(), output); + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 1, this->ctype(), output); } // optional bool packed = 2; if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::WriteBool(2, this->packed(), output); + ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->packed(), output); } // optional bool deprecated = 3 [default = false]; if (_has_bit(2)) { - ::google::protobuf::internal::WireFormat::WriteBool(3, this->deprecated(), output); + ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output); } // optional string experimental_map_key = 9; if (_has_bit(3)) { - ::google::protobuf::internal::WireFormat::WriteString(9, this->experimental_map_key(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->experimental_map_key().data(), this->experimental_map_key().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 9, this->experimental_map_key(), output); } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 999, this->uninterpreted_option(i), output); } // Extension range [1000, 536870912) @@ -4696,27 +5026,35 @@ void FieldOptions::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // optional .google.protobuf.FieldOptions.CType ctype = 1; if (_has_bit(0)) { - target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(1, this->ctype(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 1, this->ctype(), target); } // optional bool packed = 2; if (_has_bit(1)) { - target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(2, this->packed(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->packed(), target); } // optional bool deprecated = 3 [default = false]; if (_has_bit(2)) { - target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(3, this->deprecated(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target); } // optional string experimental_map_key = 9; if (_has_bit(3)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(9, this->experimental_map_key(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->experimental_map_key().data(), this->experimental_map_key().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 9, this->experimental_map_key(), target); } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 999, this->uninterpreted_option(i), target); } // Extension range [1000, 536870912) @@ -4737,7 +5075,7 @@ int FieldOptions::ByteSize() const { // optional .google.protobuf.FieldOptions.CType ctype = 1; if (has_ctype()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::EnumSize(this->ctype()); + ::google::protobuf::internal::WireFormatLite::EnumSize(this->ctype()); } // optional bool packed = 2; @@ -4753,7 +5091,8 @@ int FieldOptions::ByteSize() const { // optional string experimental_map_key = 9; if (has_experimental_map_key()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->experimental_map_key()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->experimental_map_key()); } } @@ -4761,7 +5100,7 @@ int FieldOptions::ByteSize() const { total_size += 2 * this->uninterpreted_option_size(); for (int i = 0; i < this->uninterpreted_option_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->uninterpreted_option(i)); } @@ -4844,30 +5183,29 @@ void FieldOptions::Swap(FieldOptions* other) { } } -const ::google::protobuf::Descriptor* FieldOptions::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* FieldOptions::GetReflection() const { +::google::protobuf::Metadata FieldOptions::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return FieldOptions_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = FieldOptions_descriptor_; + metadata.reflection = FieldOptions_reflection_; + return metadata; } + // =================================================================== #ifndef _MSC_VER const int EnumOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER -EnumOptions::EnumOptions() - : ::google::protobuf::Message() { +EnumOptions::EnumOptions() { SharedCtor(); } -void EnumOptions::InitAsDefaultInstance() {} +void EnumOptions::InitAsDefaultInstance() { +} -EnumOptions::EnumOptions(const EnumOptions& from) - : ::google::protobuf::Message() { +EnumOptions::EnumOptions(const EnumOptions& from) { SharedCtor(); MergeFrom(from); } @@ -4913,16 +5251,16 @@ bool EnumOptions::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_uninterpreted_option: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_uninterpreted_option())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_uninterpreted_option())); if (input->ExpectTag(7994)) goto parse_uninterpreted_option; if (input->ExpectAtEnd()) return true; break; @@ -4930,8 +5268,8 @@ bool EnumOptions::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } if ((8000u <= tag)) { @@ -4959,7 +5297,8 @@ void EnumOptions::SerializeWithCachedSizes( // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 999, this->uninterpreted_option(i), output); } // Extension range [1000, 536870912) @@ -4976,7 +5315,9 @@ void EnumOptions::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 999, this->uninterpreted_option(i), target); } // Extension range [1000, 536870912) @@ -4997,7 +5338,7 @@ int EnumOptions::ByteSize() const { total_size += 2 * this->uninterpreted_option_size(); for (int i = 0; i < this->uninterpreted_option_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->uninterpreted_option(i)); } @@ -5062,30 +5403,29 @@ void EnumOptions::Swap(EnumOptions* other) { } } -const ::google::protobuf::Descriptor* EnumOptions::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* EnumOptions::GetReflection() const { +::google::protobuf::Metadata EnumOptions::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return EnumOptions_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = EnumOptions_descriptor_; + metadata.reflection = EnumOptions_reflection_; + return metadata; } + // =================================================================== #ifndef _MSC_VER const int EnumValueOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER -EnumValueOptions::EnumValueOptions() - : ::google::protobuf::Message() { +EnumValueOptions::EnumValueOptions() { SharedCtor(); } -void EnumValueOptions::InitAsDefaultInstance() {} +void EnumValueOptions::InitAsDefaultInstance() { +} -EnumValueOptions::EnumValueOptions(const EnumValueOptions& from) - : ::google::protobuf::Message() { +EnumValueOptions::EnumValueOptions(const EnumValueOptions& from) { SharedCtor(); MergeFrom(from); } @@ -5131,16 +5471,16 @@ bool EnumValueOptions::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_uninterpreted_option: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_uninterpreted_option())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_uninterpreted_option())); if (input->ExpectTag(7994)) goto parse_uninterpreted_option; if (input->ExpectAtEnd()) return true; break; @@ -5148,8 +5488,8 @@ bool EnumValueOptions::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } if ((8000u <= tag)) { @@ -5177,7 +5517,8 @@ void EnumValueOptions::SerializeWithCachedSizes( // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 999, this->uninterpreted_option(i), output); } // Extension range [1000, 536870912) @@ -5194,7 +5535,9 @@ void EnumValueOptions::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 999, this->uninterpreted_option(i), target); } // Extension range [1000, 536870912) @@ -5215,7 +5558,7 @@ int EnumValueOptions::ByteSize() const { total_size += 2 * this->uninterpreted_option_size(); for (int i = 0; i < this->uninterpreted_option_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->uninterpreted_option(i)); } @@ -5280,30 +5623,29 @@ void EnumValueOptions::Swap(EnumValueOptions* other) { } } -const ::google::protobuf::Descriptor* EnumValueOptions::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* EnumValueOptions::GetReflection() const { +::google::protobuf::Metadata EnumValueOptions::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return EnumValueOptions_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = EnumValueOptions_descriptor_; + metadata.reflection = EnumValueOptions_reflection_; + return metadata; } + // =================================================================== #ifndef _MSC_VER const int ServiceOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER -ServiceOptions::ServiceOptions() - : ::google::protobuf::Message() { +ServiceOptions::ServiceOptions() { SharedCtor(); } -void ServiceOptions::InitAsDefaultInstance() {} +void ServiceOptions::InitAsDefaultInstance() { +} -ServiceOptions::ServiceOptions(const ServiceOptions& from) - : ::google::protobuf::Message() { +ServiceOptions::ServiceOptions(const ServiceOptions& from) { SharedCtor(); MergeFrom(from); } @@ -5349,16 +5691,16 @@ bool ServiceOptions::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_uninterpreted_option: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_uninterpreted_option())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_uninterpreted_option())); if (input->ExpectTag(7994)) goto parse_uninterpreted_option; if (input->ExpectAtEnd()) return true; break; @@ -5366,8 +5708,8 @@ bool ServiceOptions::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } if ((8000u <= tag)) { @@ -5395,7 +5737,8 @@ void ServiceOptions::SerializeWithCachedSizes( // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 999, this->uninterpreted_option(i), output); } // Extension range [1000, 536870912) @@ -5412,7 +5755,9 @@ void ServiceOptions::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 999, this->uninterpreted_option(i), target); } // Extension range [1000, 536870912) @@ -5433,7 +5778,7 @@ int ServiceOptions::ByteSize() const { total_size += 2 * this->uninterpreted_option_size(); for (int i = 0; i < this->uninterpreted_option_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->uninterpreted_option(i)); } @@ -5498,30 +5843,29 @@ void ServiceOptions::Swap(ServiceOptions* other) { } } -const ::google::protobuf::Descriptor* ServiceOptions::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* ServiceOptions::GetReflection() const { +::google::protobuf::Metadata ServiceOptions::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return ServiceOptions_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = ServiceOptions_descriptor_; + metadata.reflection = ServiceOptions_reflection_; + return metadata; } + // =================================================================== #ifndef _MSC_VER const int MethodOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER -MethodOptions::MethodOptions() - : ::google::protobuf::Message() { +MethodOptions::MethodOptions() { SharedCtor(); } -void MethodOptions::InitAsDefaultInstance() {} +void MethodOptions::InitAsDefaultInstance() { +} -MethodOptions::MethodOptions(const MethodOptions& from) - : ::google::protobuf::Message() { +MethodOptions::MethodOptions(const MethodOptions& from) { SharedCtor(); MergeFrom(from); } @@ -5567,16 +5911,16 @@ bool MethodOptions::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_uninterpreted_option: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_uninterpreted_option())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_uninterpreted_option())); if (input->ExpectTag(7994)) goto parse_uninterpreted_option; if (input->ExpectAtEnd()) return true; break; @@ -5584,8 +5928,8 @@ bool MethodOptions::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } if ((8000u <= tag)) { @@ -5613,7 +5957,8 @@ void MethodOptions::SerializeWithCachedSizes( // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 999, this->uninterpreted_option(i), output); } // Extension range [1000, 536870912) @@ -5630,7 +5975,9 @@ void MethodOptions::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 999, this->uninterpreted_option(i), target); } // Extension range [1000, 536870912) @@ -5651,7 +5998,7 @@ int MethodOptions::ByteSize() const { total_size += 2 * this->uninterpreted_option_size(); for (int i = 0; i < this->uninterpreted_option_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->uninterpreted_option(i)); } @@ -5716,15 +6063,15 @@ void MethodOptions::Swap(MethodOptions* other) { } } -const ::google::protobuf::Descriptor* MethodOptions::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* MethodOptions::GetReflection() const { +::google::protobuf::Metadata MethodOptions::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return MethodOptions_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = MethodOptions_descriptor_; + metadata.reflection = MethodOptions_reflection_; + return metadata; } + // =================================================================== const ::std::string UninterpretedOption_NamePart::_default_name_part_; @@ -5733,15 +6080,14 @@ const int UninterpretedOption_NamePart::kNamePartFieldNumber; const int UninterpretedOption_NamePart::kIsExtensionFieldNumber; #endif // !_MSC_VER -UninterpretedOption_NamePart::UninterpretedOption_NamePart() - : ::google::protobuf::Message() { +UninterpretedOption_NamePart::UninterpretedOption_NamePart() { SharedCtor(); } -void UninterpretedOption_NamePart::InitAsDefaultInstance() {} +void UninterpretedOption_NamePart::InitAsDefaultInstance() { +} -UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from) - : ::google::protobuf::Message() { +UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from) { SharedCtor(); MergeFrom(from); } @@ -5798,26 +6144,30 @@ bool UninterpretedOption_NamePart::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // required string name_part = 1; case 1: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_name_part())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name_part())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name_part().data(), this->name_part().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(16)) goto parse_is_extension; break; } // required bool is_extension = 2; case 2: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } parse_is_extension: - DO_(::google::protobuf::internal::WireFormat::ReadBool( + DO_(::google::protobuf::internal::WireFormatLite::ReadBool( input, &is_extension_)); _set_bit(1); if (input->ExpectAtEnd()) return true; @@ -5826,8 +6176,8 @@ bool UninterpretedOption_NamePart::MergePartialFromCodedStream( default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } DO_(::google::protobuf::internal::WireFormat::SkipField( @@ -5850,12 +6200,16 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes( // required string name_part = 1; if (_has_bit(0)) { - ::google::protobuf::internal::WireFormat::WriteString(1, this->name_part(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name_part().data(), this->name_part().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name_part(), output); } // required bool is_extension = 2; if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::WriteBool(2, this->is_extension(), output); + ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_extension(), output); } if (!unknown_fields().empty()) { @@ -5868,12 +6222,17 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // required string name_part = 1; if (_has_bit(0)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name_part(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name_part().data(), this->name_part().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name_part(), target); } // required bool is_extension = 2; if (_has_bit(1)) { - target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(2, this->is_extension(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_extension(), target); } if (!unknown_fields().empty()) { @@ -5890,7 +6249,8 @@ int UninterpretedOption_NamePart::ByteSize() const { // required string name_part = 1; if (has_name_part()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->name_part()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name_part()); } // required bool is_extension = 2; @@ -5961,15 +6321,15 @@ void UninterpretedOption_NamePart::Swap(UninterpretedOption_NamePart* other) { } } -const ::google::protobuf::Descriptor* UninterpretedOption_NamePart::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* UninterpretedOption_NamePart::GetReflection() const { +::google::protobuf::Metadata UninterpretedOption_NamePart::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return UninterpretedOption_NamePart_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = UninterpretedOption_NamePart_descriptor_; + metadata.reflection = UninterpretedOption_NamePart_reflection_; + return metadata; } + // ------------------------------------------------------------------- const ::std::string UninterpretedOption::_default_identifier_value_; @@ -5983,15 +6343,14 @@ const int UninterpretedOption::kDoubleValueFieldNumber; const int UninterpretedOption::kStringValueFieldNumber; #endif // !_MSC_VER -UninterpretedOption::UninterpretedOption() - : ::google::protobuf::Message() { +UninterpretedOption::UninterpretedOption() { SharedCtor(); } -void UninterpretedOption::InitAsDefaultInstance() {} +void UninterpretedOption::InitAsDefaultInstance() { +} -UninterpretedOption::UninterpretedOption(const UninterpretedOption& from) - : ::google::protobuf::Message() { +UninterpretedOption::UninterpretedOption(const UninterpretedOption& from) { SharedCtor(); MergeFrom(from); } @@ -6062,16 +6421,16 @@ bool UninterpretedOption::MergePartialFromCodedStream( #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; while ((tag = input->ReadTag()) != 0) { - switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; case 2: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_name: - DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual( - input, add_name())); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_name())); if (input->ExpectTag(18)) goto parse_name; if (input->ExpectTag(26)) goto parse_identifier_value; break; @@ -6079,24 +6438,28 @@ bool UninterpretedOption::MergePartialFromCodedStream( // optional string identifier_value = 3; case 3: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_identifier_value: - DO_(::google::protobuf::internal::WireFormat::ReadString(input, mutable_identifier_value())); + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_identifier_value())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->identifier_value().data(), this->identifier_value().length(), + ::google::protobuf::internal::WireFormat::PARSE); if (input->ExpectTag(32)) goto parse_positive_int_value; break; } // optional uint64 positive_int_value = 4; case 4: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } parse_positive_int_value: - DO_(::google::protobuf::internal::WireFormat::ReadUInt64( + DO_(::google::protobuf::internal::WireFormatLite::ReadUInt64( input, &positive_int_value_)); _set_bit(2); if (input->ExpectTag(40)) goto parse_negative_int_value; @@ -6105,12 +6468,12 @@ bool UninterpretedOption::MergePartialFromCodedStream( // optional int64 negative_int_value = 5; case 5: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { goto handle_uninterpreted; } parse_negative_int_value: - DO_(::google::protobuf::internal::WireFormat::ReadInt64( + DO_(::google::protobuf::internal::WireFormatLite::ReadInt64( input, &negative_int_value_)); _set_bit(3); if (input->ExpectTag(49)) goto parse_double_value; @@ -6119,12 +6482,12 @@ bool UninterpretedOption::MergePartialFromCodedStream( // optional double double_value = 6; case 6: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_FIXED64) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { goto handle_uninterpreted; } parse_double_value: - DO_(::google::protobuf::internal::WireFormat::ReadDouble( + DO_(::google::protobuf::internal::WireFormatLite::ReadDouble( input, &double_value_)); _set_bit(4); if (input->ExpectTag(58)) goto parse_string_value; @@ -6133,20 +6496,21 @@ bool UninterpretedOption::MergePartialFromCodedStream( // optional bytes string_value = 7; case 7: { - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) != - ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) != + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { goto handle_uninterpreted; } parse_string_value: - DO_(::google::protobuf::internal::WireFormat::ReadBytes(input, mutable_string_value())); + DO_(::google::protobuf::internal::WireFormatLite::ReadBytes( + input, this->mutable_string_value())); if (input->ExpectAtEnd()) return true; break; } default: { handle_uninterpreted: - if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { return true; } DO_(::google::protobuf::internal::WireFormat::SkipField( @@ -6169,32 +6533,38 @@ void UninterpretedOption::SerializeWithCachedSizes( // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; for (int i = 0; i < this->name_size(); i++) { - ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->name(i), output); + ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual( + 2, this->name(i), output); } // optional string identifier_value = 3; if (_has_bit(1)) { - ::google::protobuf::internal::WireFormat::WriteString(3, this->identifier_value(), output); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->identifier_value().data(), this->identifier_value().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 3, this->identifier_value(), output); } // optional uint64 positive_int_value = 4; if (_has_bit(2)) { - ::google::protobuf::internal::WireFormat::WriteUInt64(4, this->positive_int_value(), output); + ::google::protobuf::internal::WireFormatLite::WriteUInt64(4, this->positive_int_value(), output); } // optional int64 negative_int_value = 5; if (_has_bit(3)) { - ::google::protobuf::internal::WireFormat::WriteInt64(5, this->negative_int_value(), output); + ::google::protobuf::internal::WireFormatLite::WriteInt64(5, this->negative_int_value(), output); } // optional double double_value = 6; if (_has_bit(4)) { - ::google::protobuf::internal::WireFormat::WriteDouble(6, this->double_value(), output); + ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->double_value(), output); } // optional bytes string_value = 7; if (_has_bit(5)) { - ::google::protobuf::internal::WireFormat::WriteBytes(7, this->string_value(), output); + ::google::protobuf::internal::WireFormatLite::WriteBytes( + 7, this->string_value(), output); } if (!unknown_fields().empty()) { @@ -6207,32 +6577,41 @@ void UninterpretedOption::SerializeWithCachedSizes( ::google::protobuf::uint8* target) const { // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; for (int i = 0; i < this->name_size(); i++) { - target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(2, this->name(i), target); + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->name(i), target); } // optional string identifier_value = 3; if (_has_bit(1)) { - target = ::google::protobuf::internal::WireFormat::WriteStringToArray(3, this->identifier_value(), target); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->identifier_value().data(), this->identifier_value().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 3, this->identifier_value(), target); } // optional uint64 positive_int_value = 4; if (_has_bit(2)) { - target = ::google::protobuf::internal::WireFormat::WriteUInt64ToArray(4, this->positive_int_value(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(4, this->positive_int_value(), target); } // optional int64 negative_int_value = 5; if (_has_bit(3)) { - target = ::google::protobuf::internal::WireFormat::WriteInt64ToArray(5, this->negative_int_value(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(5, this->negative_int_value(), target); } // optional double double_value = 6; if (_has_bit(4)) { - target = ::google::protobuf::internal::WireFormat::WriteDoubleToArray(6, this->double_value(), target); + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->double_value(), target); } // optional bytes string_value = 7; if (_has_bit(5)) { - target = ::google::protobuf::internal::WireFormat::WriteBytesToArray(7, this->string_value(), target); + target = + ::google::protobuf::internal::WireFormatLite::WriteBytesToArray( + 7, this->string_value(), target); } if (!unknown_fields().empty()) { @@ -6249,20 +6628,21 @@ int UninterpretedOption::ByteSize() const { // optional string identifier_value = 3; if (has_identifier_value()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::StringSize(this->identifier_value()); + ::google::protobuf::internal::WireFormatLite::StringSize( + this->identifier_value()); } // optional uint64 positive_int_value = 4; if (has_positive_int_value()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::UInt64Size( + ::google::protobuf::internal::WireFormatLite::UInt64Size( this->positive_int_value()); } // optional int64 negative_int_value = 5; if (has_negative_int_value()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::Int64Size( + ::google::protobuf::internal::WireFormatLite::Int64Size( this->negative_int_value()); } @@ -6274,7 +6654,8 @@ int UninterpretedOption::ByteSize() const { // optional bytes string_value = 7; if (has_string_value()) { total_size += 1 + - ::google::protobuf::internal::WireFormat::BytesSize(this->string_value()); + ::google::protobuf::internal::WireFormatLite::BytesSize( + this->string_value()); } } @@ -6282,7 +6663,7 @@ int UninterpretedOption::ByteSize() const { total_size += 1 * this->name_size(); for (int i = 0; i < this->name_size(); i++) { total_size += - ::google::protobuf::internal::WireFormat::MessageSizeNoVirtual( + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->name(i)); } @@ -6364,14 +6745,14 @@ void UninterpretedOption::Swap(UninterpretedOption* other) { } } -const ::google::protobuf::Descriptor* UninterpretedOption::GetDescriptor() const { - return descriptor(); -} - -const ::google::protobuf::Reflection* UninterpretedOption::GetReflection() const { +::google::protobuf::Metadata UninterpretedOption::GetMetadata() const { protobuf_AssignDescriptorsOnce(); - return UninterpretedOption_reflection_; + ::google::protobuf::Metadata metadata; + metadata.descriptor = UninterpretedOption_descriptor_; + metadata.reflection = UninterpretedOption_reflection_; + return metadata; } + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index 6be84719..782a9efb 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -18,9 +18,10 @@ #error regenerate this file with a newer version of protoc. #endif -#include +#include #include #include +#include namespace google { namespace protobuf { @@ -69,11 +70,11 @@ enum FieldDescriptorProto_Type { FieldDescriptorProto_Type_TYPE_SINT32 = 17, FieldDescriptorProto_Type_TYPE_SINT64 = 18 }; -LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor(); LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Type_IsValid(int value); const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MIN = FieldDescriptorProto_Type_TYPE_DOUBLE; const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MAX = FieldDescriptorProto_Type_TYPE_SINT64; +LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor(); inline const ::std::string& FieldDescriptorProto_Type_Name(FieldDescriptorProto_Type value) { return ::google::protobuf::internal::NameOfEnum( FieldDescriptorProto_Type_descriptor(), value); @@ -88,11 +89,11 @@ enum FieldDescriptorProto_Label { FieldDescriptorProto_Label_LABEL_REQUIRED = 2, FieldDescriptorProto_Label_LABEL_REPEATED = 3 }; -LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor(); LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Label_IsValid(int value); const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MIN = FieldDescriptorProto_Label_LABEL_OPTIONAL; const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MAX = FieldDescriptorProto_Label_LABEL_REPEATED; +LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor(); inline const ::std::string& FieldDescriptorProto_Label_Name(FieldDescriptorProto_Label value) { return ::google::protobuf::internal::NameOfEnum( FieldDescriptorProto_Label_descriptor(), value); @@ -104,13 +105,14 @@ inline bool FieldDescriptorProto_Label_Parse( } enum FileOptions_OptimizeMode { FileOptions_OptimizeMode_SPEED = 1, - FileOptions_OptimizeMode_CODE_SIZE = 2 + FileOptions_OptimizeMode_CODE_SIZE = 2, + FileOptions_OptimizeMode_LITE_RUNTIME = 3 }; -LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor(); LIBPROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value); const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = FileOptions_OptimizeMode_SPEED; -const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = FileOptions_OptimizeMode_CODE_SIZE; +const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = FileOptions_OptimizeMode_LITE_RUNTIME; +LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor(); inline const ::std::string& FileOptions_OptimizeMode_Name(FileOptions_OptimizeMode value) { return ::google::protobuf::internal::NameOfEnum( FileOptions_OptimizeMode_descriptor(), value); @@ -124,11 +126,11 @@ enum FieldOptions_CType { FieldOptions_CType_CORD = 1, FieldOptions_CType_STRING_PIECE = 2 }; -LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor(); LIBPROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value); const FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_CORD; const FieldOptions_CType FieldOptions_CType_CType_MAX = FieldOptions_CType_STRING_PIECE; +LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor(); inline const ::std::string& FieldOptions_CType_Name(FieldOptions_CType value) { return ::google::protobuf::internal::NameOfEnum( FieldOptions_CType_descriptor(), value); @@ -187,8 +189,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -212,6 +213,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -277,8 +279,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -384,6 +385,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -449,8 +451,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -479,6 +480,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -544,8 +546,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -635,6 +636,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -700,8 +702,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -724,13 +725,17 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa static const Type TYPE_SFIXED64 = FieldDescriptorProto_Type_TYPE_SFIXED64; static const Type TYPE_SINT32 = FieldDescriptorProto_Type_TYPE_SINT32; static const Type TYPE_SINT64 = FieldDescriptorProto_Type_TYPE_SINT64; + static inline bool Type_IsValid(int value) { + return FieldDescriptorProto_Type_IsValid(value); + } + static const Type Type_MIN = + FieldDescriptorProto_Type_Type_MIN; + static const Type Type_MAX = + FieldDescriptorProto_Type_Type_MAX; static inline const ::google::protobuf::EnumDescriptor* Type_descriptor() { return FieldDescriptorProto_Type_descriptor(); } - static inline bool Type_IsValid(int value) { - return FieldDescriptorProto_Type_IsValid(value); - } static inline const ::std::string& Type_Name(Type value) { return FieldDescriptorProto_Type_Name(value); } @@ -738,22 +743,22 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa Type* value) { return FieldDescriptorProto_Type_Parse(name, value); } - static const Type Type_MIN = - FieldDescriptorProto_Type_Type_MIN; - static const Type Type_MAX = - FieldDescriptorProto_Type_Type_MAX; typedef FieldDescriptorProto_Label Label; static const Label LABEL_OPTIONAL = FieldDescriptorProto_Label_LABEL_OPTIONAL; static const Label LABEL_REQUIRED = FieldDescriptorProto_Label_LABEL_REQUIRED; static const Label LABEL_REPEATED = FieldDescriptorProto_Label_LABEL_REPEATED; + static inline bool Label_IsValid(int value) { + return FieldDescriptorProto_Label_IsValid(value); + } + static const Label Label_MIN = + FieldDescriptorProto_Label_Label_MIN; + static const Label Label_MAX = + FieldDescriptorProto_Label_Label_MAX; static inline const ::google::protobuf::EnumDescriptor* Label_descriptor() { return FieldDescriptorProto_Label_descriptor(); } - static inline bool Label_IsValid(int value) { - return FieldDescriptorProto_Label_IsValid(value); - } static inline const ::std::string& Label_Name(Label value) { return FieldDescriptorProto_Label_Name(value); } @@ -761,10 +766,6 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa Label* value) { return FieldDescriptorProto_Label_Parse(name, value); } - static const Label Label_MIN = - FieldDescriptorProto_Label_Label_MIN; - static const Label Label_MAX = - FieldDescriptorProto_Label_Label_MAX; // accessors ------------------------------------------------------- @@ -855,6 +856,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -920,8 +922,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -965,6 +966,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -1030,8 +1032,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1072,6 +1073,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -1137,8 +1139,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1182,6 +1183,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -1247,8 +1249,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1305,6 +1306,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -1370,21 +1372,25 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- typedef FileOptions_OptimizeMode OptimizeMode; static const OptimizeMode SPEED = FileOptions_OptimizeMode_SPEED; static const OptimizeMode CODE_SIZE = FileOptions_OptimizeMode_CODE_SIZE; + static const OptimizeMode LITE_RUNTIME = FileOptions_OptimizeMode_LITE_RUNTIME; + static inline bool OptimizeMode_IsValid(int value) { + return FileOptions_OptimizeMode_IsValid(value); + } + static const OptimizeMode OptimizeMode_MIN = + FileOptions_OptimizeMode_OptimizeMode_MIN; + static const OptimizeMode OptimizeMode_MAX = + FileOptions_OptimizeMode_OptimizeMode_MAX; static inline const ::google::protobuf::EnumDescriptor* OptimizeMode_descriptor() { return FileOptions_OptimizeMode_descriptor(); } - static inline bool OptimizeMode_IsValid(int value) { - return FileOptions_OptimizeMode_IsValid(value); - } static inline const ::std::string& OptimizeMode_Name(OptimizeMode value) { return FileOptions_OptimizeMode_Name(value); } @@ -1392,10 +1398,6 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { OptimizeMode* value) { return FileOptions_OptimizeMode_Parse(name, value); } - static const OptimizeMode OptimizeMode_MIN = - FileOptions_OptimizeMode_OptimizeMode_MIN; - static const OptimizeMode OptimizeMode_MAX = - FileOptions_OptimizeMode_OptimizeMode_MAX; // accessors ------------------------------------------------------- @@ -1459,6 +1461,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -1524,8 +1527,7 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1538,6 +1540,13 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { inline bool message_set_wire_format() const; inline void set_message_set_wire_format(bool value); + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + inline bool has_no_standard_descriptor_accessor() const; + inline void clear_no_standard_descriptor_accessor(); + static const int kNoStandardDescriptorAccessorFieldNumber = 2; + inline bool no_standard_descriptor_accessor() const; + inline void set_no_standard_descriptor_accessor(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; inline void clear_uninterpreted_option(); @@ -1555,11 +1564,13 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { mutable int _cached_size_; bool message_set_wire_format_; + bool no_standard_descriptor_accessor_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? inline bool _has_bit(int index) const { @@ -1624,21 +1635,24 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- typedef FieldOptions_CType CType; static const CType CORD = FieldOptions_CType_CORD; static const CType STRING_PIECE = FieldOptions_CType_STRING_PIECE; + static inline bool CType_IsValid(int value) { + return FieldOptions_CType_IsValid(value); + } + static const CType CType_MIN = + FieldOptions_CType_CType_MIN; + static const CType CType_MAX = + FieldOptions_CType_CType_MAX; static inline const ::google::protobuf::EnumDescriptor* CType_descriptor() { return FieldOptions_CType_descriptor(); } - static inline bool CType_IsValid(int value) { - return FieldOptions_CType_IsValid(value); - } static inline const ::std::string& CType_Name(CType value) { return FieldOptions_CType_Name(value); } @@ -1646,10 +1660,6 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { CType* value) { return FieldOptions_CType_Parse(name, value); } - static const CType CType_MIN = - FieldOptions_CType_CType_MIN; - static const CType CType_MAX = - FieldOptions_CType_CType_MAX; // accessors ------------------------------------------------------- @@ -1709,6 +1719,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -1774,8 +1785,7 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message { void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1801,6 +1811,7 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message { friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -1866,8 +1877,7 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message { void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1893,6 +1903,7 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message { friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -1958,8 +1969,7 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message { void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1985,6 +1995,7 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message { friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -2050,8 +2061,7 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message { void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -2077,6 +2087,7 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message { friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -2142,8 +2153,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -2176,6 +2186,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -2241,8 +2252,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag void SetCachedSize(int size) const { _cached_size_ = size; } public: - const ::google::protobuf::Descriptor* GetDescriptor() const; - const ::google::protobuf::Reflection* GetReflection() const; + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -2316,6 +2326,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32]; // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? @@ -3647,6 +3658,22 @@ inline void MessageOptions::set_message_set_wire_format(bool value) { message_set_wire_format_ = value; } +// optional bool no_standard_descriptor_accessor = 2 [default = false]; +inline bool MessageOptions::has_no_standard_descriptor_accessor() const { + return _has_bit(1); +} +inline void MessageOptions::clear_no_standard_descriptor_accessor() { + no_standard_descriptor_accessor_ = false; + _clear_bit(1); +} +inline bool MessageOptions::no_standard_descriptor_accessor() const { + return no_standard_descriptor_accessor_; +} +inline void MessageOptions::set_no_standard_descriptor_accessor(bool value) { + _set_bit(1); + no_standard_descriptor_accessor_ = value; +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int MessageOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); @@ -4134,4 +4161,30 @@ inline ::std::string* UninterpretedOption::mutable_string_value() { } // namespace protobuf } // namespace google + +#ifndef SWIG +namespace google { +namespace protobuf { + +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Type>() { + return ::google::protobuf::FieldDescriptorProto_Type_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Label>() { + return ::google::protobuf::FieldDescriptorProto_Label_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FileOptions_OptimizeMode>() { + return ::google::protobuf::FileOptions_OptimizeMode_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_CType>() { + return ::google::protobuf::FieldOptions_CType_descriptor(); +} + +} // namespace google +} // namespace protobuf +#endif // SWIG + #endif // PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index 381a7438..4db88a82 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -247,8 +247,10 @@ message FileOptions { // Generated classes can be optimized for speed or code size. enum OptimizeMode { - SPEED = 1; // Generate complete code for parsing, serialization, etc. - CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. } optional OptimizeMode optimize_for = 9 [default=SPEED]; @@ -282,6 +284,11 @@ message MessageOptions { // the protocol compiler. optional bool message_set_wire_format = 1 [default=false]; + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index ce216135..8fcfba3e 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -2135,6 +2135,83 @@ TEST(CustomOptions, OptionsFromOtherFile) { EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for()); } +TEST(CustomOptions, MessageOptionThreeFieldsSet) { + // This tests a bug which previously existed in custom options parsing. The + // bug occurred when you defined a custom option with message type and then + // set three fields of that option on a single definition (see the example + // below). The bug is a bit hard to explain, so check the change history if + // you want to know more. + DescriptorPool pool; + + FileDescriptorProto file_proto; + FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + protobuf_unittest::TestMessageWithCustomOptions::descriptor() + ->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + // The following represents the definition: + // + // import "google/protobuf/unittest_custom_options.proto" + // package protobuf_unittest; + // message Foo { + // option (complex_opt1).foo = 1234; + // option (complex_opt1).foo2 = 1234; + // option (complex_opt1).foo3 = 1234; + // } + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"custom_options_import.proto\" " + "package: \"protobuf_unittest\" " + "dependency: \"google/protobuf/unittest_custom_options.proto\" " + "message_type { " + " name: \"Foo\" " + " options { " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo\" " + " is_extension: false " + " } " + " positive_int_value: 1234 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo2\" " + " is_extension: false " + " } " + " positive_int_value: 1234 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo3\" " + " is_extension: false " + " } " + " positive_int_value: 1234 " + " } " + " } " + "}", + &file_proto)); + + const FileDescriptor* file = pool.BuildFile(file_proto); + ASSERT_TRUE(file != NULL); + ASSERT_EQ(1, file->message_type_count()); + + const MessageOptions& options = file->message_type(0)->options(); + EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo()); +} + // =================================================================== @@ -2335,6 +2412,30 @@ TEST_F(ValidationErrorTest, UnknownDependency) { "bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n"); } +TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) { + // Used to crash: If we depend on a non-existent file and then refer to a + // package defined in a file that we didn't import, and that package is + // nested within a parent package which this file is also in, and we don't + // include that parent package in the name (i.e. we do a relative lookup)... + // Yes, really. + BuildFile( + "name: 'foo.proto' " + "package: 'outer.foo' "); + BuildFileWithErrors( + "name: 'bar.proto' " + "dependency: 'baz.proto' " + "package: 'outer.bar' " + "message_type { " + " name: 'Bar' " + " field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }" + "}", + + "bar.proto: bar.proto: OTHER: Import \"baz.proto\" has not been loaded.\n" + "bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined in " + "\"foo.proto\", which is not imported by \"bar.proto\". To use it here, " + "please add the necessary import.\n"); +} + TEST_F(ValidationErrorTest, DupeFile) { BuildFile( "name: \"foo.proto\" " @@ -3345,6 +3446,50 @@ TEST_F(ValidationErrorTest, TryingToSetMessageValuedOption) { "message type.\n"); } +TEST_F(ValidationErrorTest, NotLiteImportsLite) { + BuildFile( + "name: \"bar.proto\" " + "options { optimize_for: LITE_RUNTIME } "); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"bar.proto\" ", + + "foo.proto: foo.proto: OTHER: Files that do not use optimize_for = " + "LITE_RUNTIME cannot import files which do use this option. This file " + "is not lite, but it imports \"bar.proto\" which is.\n"); +} + +TEST_F(ValidationErrorTest, LiteExtendsNotLite) { + BuildFile( + "name: \"bar.proto\" " + "message_type: {" + " name: \"Bar\"" + " extension_range { start: 1 end: 1000 }" + "}"); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"bar.proto\" " + "options { optimize_for: LITE_RUNTIME } " + "extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"Bar\" }", + + "foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be " + "declared in non-lite files. Note that you cannot extend a non-lite " + "type to contain a lite type, but the reverse is allowed.\n"); +} + +TEST_F(ValidationErrorTest, NoLiteServices) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "options { optimize_for: LITE_RUNTIME } " + "service { name: \"Foo\" }", + + "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot " + "define services.\n"); +} + TEST_F(ValidationErrorTest, RollbackAfterError) { // Build a file which contains every kind of construct but references an // undefined type. All these constructs will be added to the symbol table diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc index be8235e7..f8b5b4ea 100644 --- a/src/google/protobuf/dynamic_message.cc +++ b/src/google/protobuf/dynamic_message.cc @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -82,7 +83,6 @@ namespace protobuf { using internal::WireFormat; using internal::ExtensionSet; using internal::GeneratedMessageReflection; -using internal::GenericRepeatedField; // =================================================================== @@ -186,8 +186,7 @@ class DynamicMessage : public Message { int GetCachedSize() const; void SetCachedSize(int size) const; - const Descriptor* GetDescriptor() const; - const Reflection* GetReflection() const; + Metadata GetMetadata() const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage); @@ -279,20 +278,10 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info) break; case FieldDescriptor::CPPTYPE_MESSAGE: { - // If this object is the prototype, its CPPTYPE_MESSAGE fields - // must be initialized later, in CrossLinkPrototypes(), so we don't - // initialize them here. - if (!is_prototype()) { - if (!field->is_repeated()) { - new(field_ptr) Message*(NULL); - } else { - const RepeatedPtrField* prototype_field = - reinterpret_cast*>( - type_info_->prototype->OffsetToPointer( - type_info_->offsets[i])); - new(field_ptr) RepeatedPtrField( - prototype_field->prototype()); - } + if (!field->is_repeated()) { + new(field_ptr) Message*(NULL); + } else { + new(field_ptr) RepeatedPtrField(); } break; } @@ -322,9 +311,33 @@ DynamicMessage::~DynamicMessage() { void* field_ptr = OffsetToPointer(type_info_->offsets[i]); if (field->is_repeated()) { - GenericRepeatedField* field = - reinterpret_cast(field_ptr); - field->~GenericRepeatedField(); + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE : \ + reinterpret_cast*>(field_ptr) \ + ->~RepeatedField(); \ + break + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + reinterpret_cast*>(field_ptr) + ->~RepeatedPtrField(); + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: + reinterpret_cast*>(field_ptr) + ->~RepeatedPtrField(); + break; + } } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { string* ptr = *reinterpret_cast(field_ptr); @@ -353,24 +366,14 @@ void DynamicMessage::CrossLinkPrototypes() { const FieldDescriptor* field = descriptor->field(i); void* field_ptr = OffsetToPointer(type_info_->offsets[i]); - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !field->is_repeated()) { // For fields with message types, we need to cross-link with the // prototype for the field's type. - const Message* field_prototype = + // For singular fields, the field is just a pointer which should + // point to the prototype. + *reinterpret_cast(field_ptr) = factory->GetPrototype(field->message_type()); - - if (field->is_repeated()) { - // For repeated fields, we actually construct the RepeatedPtrField - // here, but only for fields with message types. All other repeated - // fields are constructed in DynamicMessage's constructor. - new(field_ptr) RepeatedPtrField(field_prototype); - } else { - // For singular fields, the field is just a pointer which should - // point to the prototype. (OK to const_cast here because the - // prototype itself will only be available const to the outside - // world.) - new(field_ptr) Message*(const_cast(field_prototype)); - } } } } @@ -392,12 +395,11 @@ void DynamicMessage::SetCachedSize(int size) const { cached_byte_size_ = size; } -const Descriptor* DynamicMessage::GetDescriptor() const { - return type_info_->type; -} - -const Reflection* DynamicMessage::GetReflection() const { - return type_info_->reflection.get(); +Metadata DynamicMessage::GetMetadata() const { + Metadata metadata; + metadata.descriptor = type_info_->type; + metadata.reflection = type_info_->reflection.get(); + return metadata; } // =================================================================== diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 61b8daae..0f799a5b 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -36,14 +36,11 @@ #include #include #include -#include -#include -#include +#include #include #include -#include +#include #include -#include #include namespace google { @@ -52,13 +49,13 @@ namespace internal { namespace { -inline FieldDescriptor::Type real_type(FieldType type) { - GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE); - return static_cast(type); +inline WireFormatLite::FieldType real_type(FieldType type) { + GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE); + return static_cast(type); } -inline FieldDescriptor::CppType cpp_type(FieldType type) { - return FieldDescriptor::TypeToCppType(real_type(type)); +inline WireFormatLite::CppType cpp_type(FieldType type) { + return WireFormatLite::FieldTypeToCppType(real_type(type)); } // Registry stuff. @@ -72,13 +69,14 @@ struct ExtensionInfo { union { ExtensionSet::EnumValidityFunc* enum_is_valid; - const Message* message_prototype; + const MessageLite* message_prototype; }; }; -typedef hash_map, ExtensionInfo> ExtensionRegistry; +typedef hash_map, + ExtensionInfo> ExtensionRegistry; ExtensionRegistry* registry_ = NULL; -GOOGLE_PROTOBUF_DECLARE_ONCE(registry_init_); +GoogleOnceType registry_init_; void DeleteRegistry() { delete registry_; @@ -92,56 +90,58 @@ void InitRegistry() { // This function is only called at startup, so there is no need for thread- // safety. -void Register(const Message* containing_type, int number, ExtensionInfo info) { - GoogleOnceInit(®istry_init_, &InitRegistry); +void Register(const MessageLite* containing_type, + int number, ExtensionInfo info) { + ::google::protobuf::GoogleOnceInit(®istry_init_, &InitRegistry); if (!InsertIfNotPresent(registry_, make_pair(containing_type, number), info)) { GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \"" - << containing_type->GetDescriptor()->full_name() + << containing_type->GetTypeName() << "\", field number " << number << "."; } } const ExtensionInfo* FindRegisteredExtension( - const Message* containing_type, int number) { + const MessageLite* containing_type, int number) { return (registry_ == NULL) ? NULL : FindOrNull(*registry_, make_pair(containing_type, number)); } } // namespace -void ExtensionSet::RegisterExtension(const Message* containing_type, +void ExtensionSet::RegisterExtension(const MessageLite* containing_type, int number, FieldType type, bool is_repeated, bool is_packed) { - GOOGLE_CHECK_NE(type, FieldDescriptor::TYPE_ENUM); - GOOGLE_CHECK_NE(type, FieldDescriptor::TYPE_MESSAGE); - GOOGLE_CHECK_NE(type, FieldDescriptor::TYPE_GROUP); + GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_ENUM); + GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_MESSAGE); + GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_GROUP); ExtensionInfo info(type, is_repeated, is_packed); Register(containing_type, number, info); } -void ExtensionSet::RegisterEnumExtension(const Message* containing_type, +void ExtensionSet::RegisterEnumExtension(const MessageLite* containing_type, int number, FieldType type, bool is_repeated, bool is_packed, EnumValidityFunc* is_valid) { - GOOGLE_CHECK_EQ(type, FieldDescriptor::TYPE_ENUM); + GOOGLE_CHECK_EQ(type, WireFormatLite::TYPE_ENUM); ExtensionInfo info(type, is_repeated, is_packed); info.enum_is_valid = is_valid; Register(containing_type, number, info); } -void ExtensionSet::RegisterMessageExtension(const Message* containing_type, +void ExtensionSet::RegisterMessageExtension(const MessageLite* containing_type, int number, FieldType type, bool is_repeated, bool is_packed, - const Message* prototype) { - GOOGLE_CHECK(type == FieldDescriptor::TYPE_MESSAGE || - type == FieldDescriptor::TYPE_GROUP); + const MessageLite* prototype) { + GOOGLE_CHECK(type == WireFormatLite::TYPE_MESSAGE || + type == WireFormatLite::TYPE_GROUP); ExtensionInfo info(type, is_repeated, is_packed); info.message_prototype = prototype; Register(containing_type, number, info); } + // =================================================================== // Constructors and basic methods. @@ -154,24 +154,10 @@ ExtensionSet::~ExtensionSet() { } } -void ExtensionSet::AppendToList(const Descriptor* containing_type, - const DescriptorPool* pool, - vector* output) const { - for (map::const_iterator iter = extensions_.begin(); - iter != extensions_.end(); ++iter) { - bool has = false; - if (iter->second.is_repeated) { - has = iter->second.GetSize() > 0; - } else { - has = !iter->second.is_cleared; - } - - if (has) { - output->push_back( - pool->FindExtensionByNumber(containing_type, iter->first)); - } - } -} +// Defined in extension_set_heavy.cc. +// void ExtensionSet::AppendToList(const Descriptor* containing_type, +// const DescriptorPool* pool, +// vector* output) const bool ExtensionSet::Has(int number) const { map::const_iterator iter = extensions_.find(number); @@ -195,11 +181,18 @@ void ExtensionSet::ClearExtension(int number) { // =================================================================== // Field accessors -#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \ - GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \ - : FieldDescriptor::LABEL_OPTIONAL, \ - FieldDescriptor::LABEL_##LABEL); \ - GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE) +namespace { + +enum Cardinality { + REPEATED, + OPTIONAL +}; + +} // namespace + +#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \ + GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? REPEATED : OPTIONAL, LABEL); \ + GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), WireFormatLite::CPPTYPE_##CPPTYPE) // ------------------------------------------------------------------- // Primitives @@ -222,7 +215,7 @@ void ExtensionSet::Set##CAMELCASE(int number, FieldType type, \ Extension* extension; \ if (MaybeNewExtension(number, &extension)) { \ extension->type = type; \ - GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_##UPPERCASE);\ + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \ extension->is_repeated = false; \ } else { \ GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, UPPERCASE); \ @@ -251,7 +244,7 @@ void ExtensionSet::Add##CAMELCASE(int number, FieldType type, \ Extension* extension; \ if (MaybeNewExtension(number, &extension)) { \ extension->type = type; \ - GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_##UPPERCASE);\ + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \ extension->is_repeated = true; \ extension->is_packed = packed; \ extension->repeated_##LOWERCASE##_value = new RepeatedField(); \ @@ -290,7 +283,7 @@ void ExtensionSet::SetEnum(int number, FieldType type, int value) { Extension* extension; if (MaybeNewExtension(number, &extension)) { extension->type = type; - GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_ENUM); + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM); extension->is_repeated = false; } else { GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, ENUM); @@ -318,7 +311,7 @@ void ExtensionSet::AddEnum(int number, FieldType type, Extension* extension; if (MaybeNewExtension(number, &extension)) { extension->type = type; - GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_ENUM); + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM); extension->is_repeated = true; extension->is_packed = packed; extension->repeated_enum_value = new RepeatedField(); @@ -348,7 +341,7 @@ string* ExtensionSet::MutableString(int number, FieldType type) { Extension* extension; if (MaybeNewExtension(number, &extension)) { extension->type = type; - GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_STRING); + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING); extension->is_repeated = false; extension->string_value = new string; } else { @@ -376,7 +369,7 @@ string* ExtensionSet::AddString(int number, FieldType type) { Extension* extension; if (MaybeNewExtension(number, &extension)) { extension->type = type; - GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_STRING); + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING); extension->is_repeated = true; extension->is_packed = false; extension->repeated_string_value = new RepeatedPtrField(); @@ -389,8 +382,8 @@ string* ExtensionSet::AddString(int number, FieldType type) { // ------------------------------------------------------------------- // Messages -const Message& ExtensionSet::GetMessage(int number, - const Message& default_value) const { +const MessageLite& ExtensionSet::GetMessage( + int number, const MessageLite& default_value) const { map::const_iterator iter = extensions_.find(number); if (iter == extensions_.end()) { // Not present. Return the default value. @@ -401,25 +394,17 @@ const Message& ExtensionSet::GetMessage(int number, } } -const Message& ExtensionSet::GetMessage(int number, - const Descriptor* message_type, - MessageFactory* factory) const { - map::const_iterator iter = extensions_.find(number); - if (iter == extensions_.end() || iter->second.is_cleared) { - // Not present. Return the default value. - return *factory->GetPrototype(message_type); - } else { - GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); - return *iter->second.message_value; - } -} +// Defined in extension_set_heavy.cc. +// const MessageLite& ExtensionSet::GetMessage(int number, +// const Descriptor* message_type, +// MessageFactory* factory) const -Message* ExtensionSet::MutableMessage(int number, FieldType type, - const Message& prototype) { +MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, + const MessageLite& prototype) { Extension* extension; if (MaybeNewExtension(number, &extension)) { extension->type = type; - GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE); + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); extension->is_repeated = false; extension->message_value = prototype.New(); } else { @@ -429,72 +414,55 @@ Message* ExtensionSet::MutableMessage(int number, FieldType type, return extension->message_value; } -Message* ExtensionSet::MutableMessage(int number, FieldType type, - const Descriptor* message_type, - MessageFactory* factory) { - Extension* extension; - if (MaybeNewExtension(number, &extension)) { - extension->type = type; - GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE); - extension->is_repeated = false; - extension->is_packed = false; - const Message* prototype = factory->GetPrototype(message_type); - GOOGLE_CHECK(prototype != NULL); - extension->message_value = prototype->New(); - } else { - GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); - } - extension->is_cleared = false; - return extension->message_value; -} +// Defined in extension_set_heavy.cc. +// MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, +// const Descriptor* message_type, +// MessageFactory* factory) -const Message& ExtensionSet::GetRepeatedMessage(int number, int index) const { +const MessageLite& ExtensionSet::GetRepeatedMessage( + int number, int index) const { map::const_iterator iter = extensions_.find(number); GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; GOOGLE_DCHECK_TYPE(iter->second, REPEATED, MESSAGE); return iter->second.repeated_message_value->Get(index); } -Message* ExtensionSet::MutableRepeatedMessage(int number, int index) { +MessageLite* ExtensionSet::MutableRepeatedMessage(int number, int index) { map::iterator iter = extensions_.find(number); GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; GOOGLE_DCHECK_TYPE(iter->second, REPEATED, MESSAGE); return iter->second.repeated_message_value->Mutable(index); } -Message* ExtensionSet::AddMessage(int number, FieldType type, - const Message& prototype) { +MessageLite* ExtensionSet::AddMessage(int number, FieldType type, + const MessageLite& prototype) { Extension* extension; if (MaybeNewExtension(number, &extension)) { extension->type = type; - GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE); + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); extension->is_repeated = true; extension->repeated_message_value = - new RepeatedPtrField(&prototype); + new RepeatedPtrField(); } else { GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE); } - return extension->repeated_message_value->Add(); -} -Message* ExtensionSet::AddMessage(int number, FieldType type, - const Descriptor* message_type, - MessageFactory* factory) { - Extension* extension; - if (MaybeNewExtension(number, &extension)) { - extension->type = type; - GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE); - extension->is_repeated = true; - const Message* prototype = factory->GetPrototype(message_type); - GOOGLE_CHECK(prototype != NULL); - extension->repeated_message_value = - new RepeatedPtrField(prototype); - } else { - GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE); + // RepeatedPtrField does not know how to Add() since it cannot + // allocate an abstract object, so we have to be tricky. + MessageLite* result = extension->repeated_message_value + ->AddFromCleared >(); + if (result == NULL) { + result = prototype.New(); + extension->repeated_message_value->AddAllocated(result); } - return extension->repeated_message_value->Add(); + return result; } +// Defined in extension_set_heavy.cc. +// MessageLite* ExtensionSet::AddMessage(int number, FieldType type, +// const Descriptor* message_type, +// MessageFactory* factory) + #undef GOOGLE_DCHECK_TYPE void ExtensionSet::RemoveLast(int number) { @@ -505,35 +473,35 @@ void ExtensionSet::RemoveLast(int number) { GOOGLE_DCHECK(extension->is_repeated); switch(cpp_type(extension->type)) { - case FieldDescriptor::CPPTYPE_INT32: - extension->repeated_int32_value->RemoveLast(); + case WireFormatLite::CPPTYPE_INT32: + extension->repeated_int32_value->RemoveLast(); break; - case FieldDescriptor::CPPTYPE_INT64: - extension->repeated_int64_value->RemoveLast(); + case WireFormatLite::CPPTYPE_INT64: + extension->repeated_int64_value->RemoveLast(); break; - case FieldDescriptor::CPPTYPE_UINT32: - extension->repeated_uint32_value->RemoveLast(); + case WireFormatLite::CPPTYPE_UINT32: + extension->repeated_uint32_value->RemoveLast(); break; - case FieldDescriptor::CPPTYPE_UINT64: - extension->repeated_uint64_value->RemoveLast(); + case WireFormatLite::CPPTYPE_UINT64: + extension->repeated_uint64_value->RemoveLast(); break; - case FieldDescriptor::CPPTYPE_FLOAT: - extension->repeated_float_value->RemoveLast(); + case WireFormatLite::CPPTYPE_FLOAT: + extension->repeated_float_value->RemoveLast(); break; - case FieldDescriptor::CPPTYPE_DOUBLE: - extension->repeated_double_value->RemoveLast(); + case WireFormatLite::CPPTYPE_DOUBLE: + extension->repeated_double_value->RemoveLast(); break; - case FieldDescriptor::CPPTYPE_BOOL: - extension->repeated_bool_value->RemoveLast(); + case WireFormatLite::CPPTYPE_BOOL: + extension->repeated_bool_value->RemoveLast(); break; - case FieldDescriptor::CPPTYPE_ENUM: - extension->repeated_enum_value->RemoveLast(); + case WireFormatLite::CPPTYPE_ENUM: + extension->repeated_enum_value->RemoveLast(); break; - case FieldDescriptor::CPPTYPE_STRING: - extension->repeated_string_value->RemoveLast(); + case WireFormatLite::CPPTYPE_STRING: + extension->repeated_string_value->RemoveLast(); break; - case FieldDescriptor::CPPTYPE_MESSAGE: - extension->repeated_message_value->RemoveLast(); + case WireFormatLite::CPPTYPE_MESSAGE: + extension->repeated_message_value->RemoveLast(); break; } } @@ -546,35 +514,35 @@ void ExtensionSet::SwapElements(int number, int index1, int index2) { GOOGLE_DCHECK(extension->is_repeated); switch(cpp_type(extension->type)) { - case FieldDescriptor::CPPTYPE_INT32: + case WireFormatLite::CPPTYPE_INT32: extension->repeated_int32_value->SwapElements(index1, index2); break; - case FieldDescriptor::CPPTYPE_INT64: - extension->repeated_int64_value->SwapElements(index1, index2); + case WireFormatLite::CPPTYPE_INT64: + extension->repeated_int64_value->SwapElements(index1, index2); break; - case FieldDescriptor::CPPTYPE_UINT32: + case WireFormatLite::CPPTYPE_UINT32: extension->repeated_uint32_value->SwapElements(index1, index2); break; - case FieldDescriptor::CPPTYPE_UINT64: + case WireFormatLite::CPPTYPE_UINT64: extension->repeated_uint64_value->SwapElements(index1, index2); break; - case FieldDescriptor::CPPTYPE_FLOAT: - extension->repeated_float_value->SwapElements(index1, index2); + case WireFormatLite::CPPTYPE_FLOAT: + extension->repeated_float_value->SwapElements(index1, index2); break; - case FieldDescriptor::CPPTYPE_DOUBLE: - extension->repeated_double_value->SwapElements(index1, index2); + case WireFormatLite::CPPTYPE_DOUBLE: + extension->repeated_double_value->SwapElements(index1, index2); break; - case FieldDescriptor::CPPTYPE_BOOL: - extension->repeated_bool_value->SwapElements(index1, index2); + case WireFormatLite::CPPTYPE_BOOL: + extension->repeated_bool_value->SwapElements(index1, index2); break; - case FieldDescriptor::CPPTYPE_ENUM: - extension->repeated_enum_value->SwapElements(index1, index2); + case WireFormatLite::CPPTYPE_ENUM: + extension->repeated_enum_value->SwapElements(index1, index2); break; - case FieldDescriptor::CPPTYPE_STRING: - extension->repeated_string_value->SwapElements(index1, index2); + case WireFormatLite::CPPTYPE_STRING: + extension->repeated_string_value->SwapElements(index1, index2); break; - case FieldDescriptor::CPPTYPE_MESSAGE: - extension->repeated_message_value->SwapElements(index1, index2); + case WireFormatLite::CPPTYPE_MESSAGE: + extension->repeated_message_value->SwapElements(index1, index2); break; } } @@ -607,7 +575,7 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) { switch (cpp_type(other_extension.type)) { #define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \ - case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ if (is_new) { \ extension->repeated_##LOWERCASE##_value = \ new REPEATED_TYPE; \ @@ -627,20 +595,32 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) { HANDLE_TYPE( STRING, string, RepeatedPtrField< string>); #undef HANDLE_TYPE - case FieldDescriptor::CPPTYPE_MESSAGE: + case WireFormatLite::CPPTYPE_MESSAGE: if (is_new) { - extension->repeated_message_value = new RepeatedPtrField( - other_extension.repeated_message_value->prototype()); + extension->repeated_message_value = + new RepeatedPtrField(); + } + // We can't call RepeatedPtrField::MergeFrom() because + // it would attempt to allocate new objects. + RepeatedPtrField* other_repeated_message = + other_extension.repeated_message_value; + for (int i = 0; i < other_repeated_message->size(); i++) { + const MessageLite& other_message = other_repeated_message->Get(i); + MessageLite* target = extension->repeated_message_value + ->AddFromCleared >(); + if (target == NULL) { + target = other_message.New(); + extension->repeated_message_value->AddAllocated(target); + } + target->CheckTypeAndMergeFrom(other_message); } - extension->repeated_message_value->MergeFrom( - *other_extension.repeated_message_value); break; } } else { if (!other_extension.is_cleared) { switch (cpp_type(other_extension.type)) { #define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \ - case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ Set##CAMELCASE(iter->first, other_extension.type, \ other_extension.LOWERCASE##_value); \ break; @@ -654,14 +634,14 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) { HANDLE_TYPE( BOOL, bool, Bool); HANDLE_TYPE( ENUM, enum, Enum); #undef HANDLE_TYPE - case FieldDescriptor::CPPTYPE_STRING: + case WireFormatLite::CPPTYPE_STRING: SetString(iter->first, other_extension.type, *other_extension.string_value); break; - case FieldDescriptor::CPPTYPE_MESSAGE: + case WireFormatLite::CPPTYPE_MESSAGE: MutableMessage(iter->first, other_extension.type, *other_extension.message_value) - ->MergeFrom(*other_extension.message_value); + ->CheckTypeAndMergeFrom(*other_extension.message_value); break; } } @@ -679,7 +659,7 @@ bool ExtensionSet::IsInitialized() const { for (map::const_iterator iter = extensions_.begin(); iter != extensions_.end(); ++iter) { const Extension& extension = iter->second; - if (cpp_type(extension.type) == FieldDescriptor::CPPTYPE_MESSAGE) { + if (cpp_type(extension.type) == WireFormatLite::CPPTYPE_MESSAGE) { if (extension.is_repeated) { for (int i = 0; i < extension.repeated_message_value->size(); i++) { if (!extension.repeated_message_value->Get(i).IsInitialized()) { @@ -698,10 +678,10 @@ bool ExtensionSet::IsInitialized() const { } bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, - const Message* containing_type, - UnknownFieldSet* unknown_fields) { - int number = WireFormat::GetTagFieldNumber(tag); - WireFormat::WireType wire_type = WireFormat::GetTagWireType(tag); + const MessageLite* containing_type, + FieldSkipper* field_skipper) { + int number = WireFormatLite::GetTagFieldNumber(tag); + WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); const ExtensionInfo* extension = FindRegisteredExtension(containing_type, number); @@ -710,15 +690,15 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, if (extension == NULL) { is_unknown = true; } else if (extension->is_packed) { - is_unknown = (wire_type != WireFormat::WIRETYPE_LENGTH_DELIMITED); + is_unknown = (wire_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED); } else { - WireFormat::WireType expected_wire_type = - WireFormat::WireTypeForFieldType(real_type(extension->type)); + WireFormatLite::WireType expected_wire_type = + WireFormatLite::WireTypeForFieldType(real_type(extension->type)); is_unknown = (wire_type != expected_wire_type); } if (is_unknown) { - WireFormat::SkipField(input, tag, unknown_fields); + field_skipper->SkipField(input, tag); } else if (extension->is_packed) { uint32 size; if (!input->ReadVarint32(&size)) return false; @@ -726,11 +706,11 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, switch (extension->type) { #define HANDLE_TYPE(UPPERCASE, CAMELCASE, CPP_CAMELCASE, CPP_LOWERCASE) \ - case FieldDescriptor::TYPE_##UPPERCASE: \ + case WireFormatLite::TYPE_##UPPERCASE: \ while (input->BytesUntilLimit() > 0) { \ CPP_LOWERCASE value; \ - if (!WireFormat::Read##CAMELCASE(input, &value)) return false; \ - Add##CPP_CAMELCASE(number, FieldDescriptor::TYPE_##UPPERCASE, \ + if (!WireFormatLite::Read##CAMELCASE(input, &value)) return false; \ + Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ true, value); \ } \ break @@ -750,20 +730,20 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, HANDLE_TYPE( BOOL, Bool, Bool, bool); #undef HANDLE_TYPE - case FieldDescriptor::TYPE_ENUM: + case WireFormatLite::TYPE_ENUM: while (input->BytesUntilLimit() > 0) { int value; - if (!WireFormat::ReadEnum(input, &value)) return false; + if (!WireFormatLite::ReadEnum(input, &value)) return false; if (extension->enum_is_valid(value)) { - AddEnum(number, FieldDescriptor::TYPE_ENUM, true, value); + AddEnum(number, WireFormatLite::TYPE_ENUM, true, value); } } break; - case FieldDescriptor::TYPE_STRING: - case FieldDescriptor::TYPE_BYTES: - case FieldDescriptor::TYPE_GROUP: - case FieldDescriptor::TYPE_MESSAGE: + case WireFormatLite::TYPE_STRING: + case WireFormatLite::TYPE_BYTES: + case WireFormatLite::TYPE_GROUP: + case WireFormatLite::TYPE_MESSAGE: GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; break; } @@ -772,14 +752,14 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, } else { switch (extension->type) { #define HANDLE_TYPE(UPPERCASE, CAMELCASE, CPP_CAMELCASE, CPP_LOWERCASE) \ - case FieldDescriptor::TYPE_##UPPERCASE: { \ + case WireFormatLite::TYPE_##UPPERCASE: { \ CPP_LOWERCASE value; \ - if (!WireFormat::Read##CAMELCASE(input, &value)) return false; \ + if (!WireFormatLite::Read##CAMELCASE(input, &value)) return false; \ if (extension->is_repeated) { \ - Add##CPP_CAMELCASE(number, FieldDescriptor::TYPE_##UPPERCASE, \ + Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ false, value); \ } else { \ - Set##CPP_CAMELCASE(number, FieldDescriptor::TYPE_##UPPERCASE, value);\ + Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value); \ } \ } break @@ -798,56 +778,54 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, HANDLE_TYPE( BOOL, Bool, Bool, bool); #undef HANDLE_TYPE - case FieldDescriptor::TYPE_ENUM: { + case WireFormatLite::TYPE_ENUM: { int value; - if (!WireFormat::ReadEnum(input, &value)) return false; + if (!WireFormatLite::ReadEnum(input, &value)) return false; if (!extension->enum_is_valid(value)) { // Invalid value. Treat as unknown. - if (unknown_fields != NULL) { - unknown_fields->AddVarint(number, value); - } + field_skipper->SkipUnknownEnum(number, value); } else if (extension->is_repeated) { - AddEnum(number, FieldDescriptor::TYPE_ENUM, false, value); + AddEnum(number, WireFormatLite::TYPE_ENUM, false, value); } else { - SetEnum(number, FieldDescriptor::TYPE_ENUM, value); + SetEnum(number, WireFormatLite::TYPE_ENUM, value); } break; } - case FieldDescriptor::TYPE_STRING: { + case WireFormatLite::TYPE_STRING: { string* value = extension->is_repeated ? - AddString(number, FieldDescriptor::TYPE_STRING) : - MutableString(number, FieldDescriptor::TYPE_STRING); - if (!WireFormat::ReadString(input, value)) return false; + AddString(number, WireFormatLite::TYPE_STRING) : + MutableString(number, WireFormatLite::TYPE_STRING); + if (!WireFormatLite::ReadString(input, value)) return false; break; } - case FieldDescriptor::TYPE_BYTES: { + case WireFormatLite::TYPE_BYTES: { string* value = extension->is_repeated ? - AddString(number, FieldDescriptor::TYPE_STRING) : - MutableString(number, FieldDescriptor::TYPE_STRING); - if (!WireFormat::ReadBytes(input, value)) return false; + AddString(number, WireFormatLite::TYPE_STRING) : + MutableString(number, WireFormatLite::TYPE_STRING); + if (!WireFormatLite::ReadBytes(input, value)) return false; break; } - case FieldDescriptor::TYPE_GROUP: { - Message* value = extension->is_repeated ? - AddMessage(number, FieldDescriptor::TYPE_GROUP, + case WireFormatLite::TYPE_GROUP: { + MessageLite* value = extension->is_repeated ? + AddMessage(number, WireFormatLite::TYPE_GROUP, *extension->message_prototype) : - MutableMessage(number, FieldDescriptor::TYPE_GROUP, + MutableMessage(number, WireFormatLite::TYPE_GROUP, *extension->message_prototype); - if (!WireFormat::ReadGroup(number, input, value)) return false; + if (!WireFormatLite::ReadGroup(number, input, value)) return false; break; } - case FieldDescriptor::TYPE_MESSAGE: { - Message* value = extension->is_repeated ? - AddMessage(number, FieldDescriptor::TYPE_MESSAGE, + case WireFormatLite::TYPE_MESSAGE: { + MessageLite* value = extension->is_repeated ? + AddMessage(number, WireFormatLite::TYPE_MESSAGE, *extension->message_prototype) : - MutableMessage(number, FieldDescriptor::TYPE_MESSAGE, + MutableMessage(number, WireFormatLite::TYPE_MESSAGE, *extension->message_prototype); - if (!WireFormat::ReadMessage(input, value)) return false; + if (!WireFormatLite::ReadMessage(input, value)) return false; break; } } @@ -856,6 +834,130 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, return true; } +bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, + const MessageLite* containing_type) { + FieldSkipper skipper; + return ParseField(tag, input, containing_type, &skipper); +} + +// Defined in extension_set_heavy.cc. +// bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, +// const MessageLite* containing_type, +// UnknownFieldSet* unknown_fields) + +bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, + const MessageLite* containing_type, + FieldSkipper* field_skipper) { + while (true) { + uint32 tag = input->ReadTag(); + switch (tag) { + case 0: + return true; + case WireFormatLite::kMessageSetItemStartTag: + if (!ParseMessageSetItem(input, containing_type, field_skipper)) { + return false; + } + break; + default: + if (!ParseField(tag, input, containing_type, field_skipper)) { + return false; + } + break; + } + } +} + +bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, + const MessageLite* containing_type) { + FieldSkipper skipper; + return ParseMessageSet(input, containing_type, &skipper); +} + +// Defined in extension_set_heavy.cc. +// bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, +// const MessageLite* containing_type, +// UnknownFieldSet* unknown_fields); + +bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input, + const MessageLite* containing_type, + FieldSkipper* field_skipper) { + // TODO(kenton): It would be nice to share code between this and + // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the + // differences would be hard to factor out. + + // This method parses a group which should contain two fields: + // required int32 type_id = 2; + // required data message = 3; + + // Once we see a type_id, we'll construct a fake tag for this extension + // which is the tag it would have had under the proto2 extensions wire + // format. + uint32 fake_tag = 0; + + // If we see message data before the type_id, we'll append it to this so + // we can parse it later. This will probably never happen in practice, + // as no MessageSet encoder I know of writes the message before the type ID. + // But, it's technically valid so we should allow it. + // TODO(kenton): Use a Cord instead? Do I care? + string message_data; + + while (true) { + uint32 tag = input->ReadTag(); + if (tag == 0) return false; + + switch (tag) { + case WireFormatLite::kMessageSetTypeIdTag: { + uint32 type_id; + if (!input->ReadVarint32(&type_id)) return false; + fake_tag = WireFormatLite::MakeTag(type_id, + WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + + if (!message_data.empty()) { + // We saw some message data before the type_id. Have to parse it + // now. + io::CodedInputStream sub_input( + reinterpret_cast(message_data.data()), + message_data.size()); + if (!ParseField(fake_tag, &sub_input, + containing_type, field_skipper)) { + return false; + } + message_data.clear(); + } + + break; + } + + case WireFormatLite::kMessageSetMessageTag: { + if (fake_tag == 0) { + // We haven't seen a type_id yet. Append this data to message_data. + string temp; + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (!input->ReadString(&temp, length)) return false; + message_data.append(temp); + } else { + // Already saw type_id, so we can parse this directly. + if (!ParseField(fake_tag, input, + containing_type, field_skipper)) { + return false; + } + } + + break; + } + + case WireFormatLite::kMessageSetItemEndTag: { + return true; + } + + default: { + if (!field_skipper->SkipField(input, tag)) return false; + } + } + } +} + void ExtensionSet::SerializeWithCachedSizes( int start_field_number, int end_field_number, io::CodedOutputStream* output) const { @@ -887,6 +989,31 @@ uint8* ExtensionSet::SerializeWithCachedSizesToArray( return target + written_bytes; } +void ExtensionSet::SerializeMessageSetWithCachedSizes( + io::CodedOutputStream* output) const { + map::const_iterator iter; + for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) { + iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output); + } +} + +uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray( + uint8* target) const { + // For now, just create an array output stream around the target and dispatch + // to SerializeWithCachedSizes(). Give the array output stream kint32max + // bytes; we will certainly write less than that. It is up to the caller to + // ensure that the buffer has sufficient space. + int written_bytes; + { + io::ArrayOutputStream array_stream(target, kint32max); + io::CodedOutputStream output_stream(&array_stream); + SerializeMessageSetWithCachedSizes(&output_stream); + written_bytes = output_stream.ByteCount(); + GOOGLE_DCHECK(!output_stream.HadError()); + } + return target + written_bytes; +} + int ExtensionSet::ByteSize() const { int total_size = 0; @@ -898,18 +1025,20 @@ int ExtensionSet::ByteSize() const { return total_size; } -int ExtensionSet::SpaceUsedExcludingSelf() const { - int total_size = - extensions_.size() * sizeof(map::value_type); - for (map::const_iterator iter = extensions_.begin(), - end = extensions_.end(); - iter != end; - ++iter) { - total_size += iter->second.SpaceUsedExcludingSelf(); +int ExtensionSet::MessageSetByteSize() const { + int total_size = 0; + + for (map::const_iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + total_size += iter->second.MessageSetItemByteSize(iter->first); } + return total_size; } +// Defined in extension_set_heavy.cc. +// int ExtensionSet::SpaceUsedExcludingSelf() const + bool ExtensionSet::MaybeNewExtension(int number, Extension** result) { pair::iterator, bool> insert_result = extensions_.insert(make_pair(number, Extension())); @@ -924,7 +1053,7 @@ void ExtensionSet::Extension::Clear() { if (is_repeated) { switch (cpp_type(type)) { #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ repeated_##LOWERCASE##_value->Clear(); \ break @@ -943,10 +1072,10 @@ void ExtensionSet::Extension::Clear() { } else { if (!is_cleared) { switch (cpp_type(type)) { - case FieldDescriptor::CPPTYPE_STRING: + case WireFormatLite::CPPTYPE_STRING: string_value->clear(); break; - case FieldDescriptor::CPPTYPE_MESSAGE: + case WireFormatLite::CPPTYPE_MESSAGE: message_value->Clear(); break; default: @@ -968,15 +1097,15 @@ void ExtensionSet::Extension::SerializeFieldWithCachedSizes( if (is_packed) { if (cached_size == 0) return; - WireFormat::WriteTag(number, WireFormat::WIRETYPE_LENGTH_DELIMITED, - output); + WireFormatLite::WriteTag(number, + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); output->WriteVarint32(cached_size); switch (real_type(type)) { #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case FieldDescriptor::TYPE_##UPPERCASE: \ + case WireFormatLite::TYPE_##UPPERCASE: \ for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - WireFormat::Write##CAMELCASE##NoTag( \ + WireFormatLite::Write##CAMELCASE##NoTag( \ repeated_##LOWERCASE##_value->Get(i), output); \ } \ break @@ -997,19 +1126,19 @@ void ExtensionSet::Extension::SerializeFieldWithCachedSizes( HANDLE_TYPE( ENUM, Enum, enum); #undef HANDLE_TYPE - case FieldDescriptor::TYPE_STRING: - case FieldDescriptor::TYPE_BYTES: - case FieldDescriptor::TYPE_GROUP: - case FieldDescriptor::TYPE_MESSAGE: + case WireFormatLite::TYPE_STRING: + case WireFormatLite::TYPE_BYTES: + case WireFormatLite::TYPE_GROUP: + case WireFormatLite::TYPE_MESSAGE: GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; break; } } else { switch (real_type(type)) { #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case FieldDescriptor::TYPE_##UPPERCASE: \ + case WireFormatLite::TYPE_##UPPERCASE: \ for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - WireFormat::Write##CAMELCASE(number, \ + WireFormatLite::Write##CAMELCASE(number, \ repeated_##LOWERCASE##_value->Get(i), output); \ } \ break @@ -1038,8 +1167,8 @@ void ExtensionSet::Extension::SerializeFieldWithCachedSizes( } else if (!is_cleared) { switch (real_type(type)) { #define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \ - case FieldDescriptor::TYPE_##UPPERCASE: \ - WireFormat::Write##CAMELCASE(number, VALUE, output); \ + case WireFormatLite::TYPE_##UPPERCASE: \ + WireFormatLite::Write##CAMELCASE(number, VALUE, output); \ break HANDLE_TYPE( INT32, Int32, int32_value); @@ -1065,6 +1194,34 @@ void ExtensionSet::Extension::SerializeFieldWithCachedSizes( } } +void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes( + int number, + io::CodedOutputStream* output) const { + if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { + // Not a valid MessageSet extension, but serialize it the normal way. + SerializeFieldWithCachedSizes(number, output); + return; + } + + if (is_cleared) return; + + // Start group. + output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag); + + // Write type ID. + output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag); + output->WriteVarint32(number); + + // Write message. + output->WriteVarint32(WireFormatLite::kMessageSetMessageTag); + + output->WriteVarint32(message_value->GetCachedSize()); + message_value->SerializeWithCachedSizes(output); + + // End group. + output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag); +} + int ExtensionSet::Extension::ByteSize(int number) const { int result = 0; @@ -1072,9 +1229,9 @@ int ExtensionSet::Extension::ByteSize(int number) const { if (is_packed) { switch (real_type(type)) { #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case FieldDescriptor::TYPE_##UPPERCASE: \ + case WireFormatLite::TYPE_##UPPERCASE: \ for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - result += WireFormat::CAMELCASE##Size( \ + result += WireFormatLite::CAMELCASE##Size( \ repeated_##LOWERCASE##_value->Get(i)); \ } \ break @@ -1090,8 +1247,8 @@ int ExtensionSet::Extension::ByteSize(int number) const { // Stuff with fixed size. #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case FieldDescriptor::TYPE_##UPPERCASE: \ - result += WireFormat::k##CAMELCASE##Size * \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += WireFormatLite::k##CAMELCASE##Size * \ repeated_##LOWERCASE##_value->size(); \ break HANDLE_TYPE( FIXED32, Fixed32, uint32); @@ -1103,10 +1260,10 @@ int ExtensionSet::Extension::ByteSize(int number) const { HANDLE_TYPE( BOOL, Bool, bool); #undef HANDLE_TYPE - case FieldDescriptor::TYPE_STRING: - case FieldDescriptor::TYPE_BYTES: - case FieldDescriptor::TYPE_GROUP: - case FieldDescriptor::TYPE_MESSAGE: + case WireFormatLite::TYPE_STRING: + case WireFormatLite::TYPE_BYTES: + case WireFormatLite::TYPE_GROUP: + case WireFormatLite::TYPE_MESSAGE: GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; break; } @@ -1115,17 +1272,18 @@ int ExtensionSet::Extension::ByteSize(int number) const { if (result > 0) { result += io::CodedOutputStream::VarintSize32(result); result += io::CodedOutputStream::VarintSize32( - WireFormat::MakeTag(number, WireFormat::WIRETYPE_LENGTH_DELIMITED)); + WireFormatLite::MakeTag(number, + WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); } } else { - int tag_size = WireFormat::TagSize(number, real_type(type)); + int tag_size = WireFormatLite::TagSize(number, real_type(type)); switch (real_type(type)) { #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case FieldDescriptor::TYPE_##UPPERCASE: \ + case WireFormatLite::TYPE_##UPPERCASE: \ result += tag_size * repeated_##LOWERCASE##_value->size(); \ for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - result += WireFormat::CAMELCASE##Size( \ + result += WireFormatLite::CAMELCASE##Size( \ repeated_##LOWERCASE##_value->Get(i)); \ } \ break @@ -1145,8 +1303,8 @@ int ExtensionSet::Extension::ByteSize(int number) const { // Stuff with fixed size. #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case FieldDescriptor::TYPE_##UPPERCASE: \ - result += (tag_size + WireFormat::k##CAMELCASE##Size) * \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += (tag_size + WireFormatLite::k##CAMELCASE##Size) * \ repeated_##LOWERCASE##_value->size(); \ break HANDLE_TYPE( FIXED32, Fixed32, uint32); @@ -1160,11 +1318,11 @@ int ExtensionSet::Extension::ByteSize(int number) const { } } } else if (!is_cleared) { - result += WireFormat::TagSize(number, real_type(type)); + result += WireFormatLite::TagSize(number, real_type(type)); switch (real_type(type)) { #define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case FieldDescriptor::TYPE_##UPPERCASE: \ - result += WireFormat::CAMELCASE##Size(LOWERCASE); \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += WireFormatLite::CAMELCASE##Size(LOWERCASE); \ break HANDLE_TYPE( INT32, Int32, int32_value); @@ -1182,8 +1340,8 @@ int ExtensionSet::Extension::ByteSize(int number) const { // Stuff with fixed size. #define HANDLE_TYPE(UPPERCASE, CAMELCASE) \ - case FieldDescriptor::TYPE_##UPPERCASE: \ - result += WireFormat::k##CAMELCASE##Size; \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += WireFormatLite::k##CAMELCASE##Size; \ break HANDLE_TYPE( FIXED32, Fixed32); HANDLE_TYPE( FIXED64, Fixed64); @@ -1199,11 +1357,34 @@ int ExtensionSet::Extension::ByteSize(int number) const { return result; } +int ExtensionSet::Extension::MessageSetItemByteSize(int number) const { + if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { + // Not a valid MessageSet extension, but compute the byte size for it the + // normal way. + return ByteSize(number); + } + + if (is_cleared) return 0; + + int our_size = WireFormatLite::kMessageSetItemTagsSize; + + // type_id + our_size += io::CodedOutputStream::VarintSize32(number); + + // message + int message_size = message_value->ByteSize(); + + our_size += io::CodedOutputStream::VarintSize32(message_size); + our_size += message_size; + + return our_size; +} + int ExtensionSet::Extension::GetSize() const { GOOGLE_DCHECK(is_repeated); switch (cpp_type(type)) { #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ return repeated_##LOWERCASE##_value->size() HANDLE_TYPE( INT32, int32); @@ -1227,7 +1408,7 @@ void ExtensionSet::Extension::Free() { if (is_repeated) { switch (cpp_type(type)) { #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ delete repeated_##LOWERCASE##_value; \ break @@ -1245,10 +1426,10 @@ void ExtensionSet::Extension::Free() { } } else { switch (cpp_type(type)) { - case FieldDescriptor::CPPTYPE_STRING: + case WireFormatLite::CPPTYPE_STRING: delete string_value; break; - case FieldDescriptor::CPPTYPE_MESSAGE: + case WireFormatLite::CPPTYPE_MESSAGE: delete message_value; break; default: @@ -1257,43 +1438,8 @@ void ExtensionSet::Extension::Free() { } } -int ExtensionSet::Extension::SpaceUsedExcludingSelf() const { - int total_size = 0; - if (is_repeated) { - switch (cpp_type(type)) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case FieldDescriptor::CPPTYPE_##UPPERCASE: \ - total_size += sizeof(*repeated_##LOWERCASE##_value) + \ - repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\ - break - - HANDLE_TYPE( INT32, int32); - HANDLE_TYPE( INT64, int64); - HANDLE_TYPE( UINT32, uint32); - HANDLE_TYPE( UINT64, uint64); - HANDLE_TYPE( FLOAT, float); - HANDLE_TYPE( DOUBLE, double); - HANDLE_TYPE( BOOL, bool); - HANDLE_TYPE( ENUM, enum); - HANDLE_TYPE( STRING, string); - HANDLE_TYPE(MESSAGE, message); - } - } else { - switch (cpp_type(type)) { - case FieldDescriptor::CPPTYPE_STRING: - total_size += sizeof(*string_value) + - StringSpaceUsedExcludingSelf(*string_value); - break; - case FieldDescriptor::CPPTYPE_MESSAGE: - total_size += message_value->SpaceUsed(); - break; - default: - // No extra storage costs for primitive types. - break; - } - } - return total_size; -} +// Defined in extension_set_heavy.cc. +// int ExtensionSet::Extension::SpaceUsedExcludingSelf() const } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h index e04614cc..8c1d73b8 100644 --- a/src/google/protobuf/extension_set.h +++ b/src/google/protobuf/extension_set.h @@ -45,20 +45,23 @@ #include #include -#include namespace google { + namespace protobuf { class Descriptor; // descriptor.h class FieldDescriptor; // descriptor.h class DescriptorPool; // descriptor.h - class Message; // message.h + class MessageLite; // message_lite.h class MessageFactory; // message.h class UnknownFieldSet; // unknown_field_set.h namespace io { class CodedInputStream; // coded_stream.h class CodedOutputStream; // coded_stream.h } + namespace internal { + class FieldSkipper; // wire_format_lite.h + } template class RepeatedField; // repeated_field.h template class RepeatedPtrField; // repeated_field.h } @@ -66,9 +69,9 @@ namespace protobuf { namespace protobuf { namespace internal { -// Used to store values of type FieldDescriptor::Type without having to -// #include descriptor.h. Also, ensures that we use only one byte to store -// these values, which is important to keep the layout of +// Used to store values of type WireFormatLite::FieldType without having to +// #include wire_format_lite.h. Also, ensures that we use only one byte to +// store these values, which is important to keep the layout of // ExtensionSet::Extension small. typedef uint8 FieldType; @@ -98,17 +101,17 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // to look up extensions for parsed field numbers. Note that dynamic parsing // does not use ParseField(); only protocol-compiler-generated parsing // methods do. - static void RegisterExtension(const Message* containing_type, + static void RegisterExtension(const MessageLite* containing_type, int number, FieldType type, bool is_repeated, bool is_packed); - static void RegisterEnumExtension(const Message* containing_type, + static void RegisterEnumExtension(const MessageLite* containing_type, int number, FieldType type, bool is_repeated, bool is_packed, EnumValidityFunc* is_valid); - static void RegisterMessageExtension(const Message* containing_type, + static void RegisterMessageExtension(const MessageLite* containing_type, int number, FieldType type, bool is_repeated, bool is_packed, - const Message* prototype); + const MessageLite* prototype); // ================================================================= @@ -167,9 +170,10 @@ class LIBPROTOBUF_EXPORT ExtensionSet { bool GetBool (int number, bool default_value) const; int GetEnum (int number, int default_value) const; const string & GetString (int number, const string& default_value) const; - const Message& GetMessage(int number, const Message& default_value) const; - const Message& GetMessage(int number, const Descriptor* message_type, - MessageFactory* factory) const; + const MessageLite& GetMessage(int number, + const MessageLite& default_value) const; + const MessageLite& GetMessage(int number, const Descriptor* message_type, + MessageFactory* factory) const; void SetInt32 (int number, FieldType type, int32 value); void SetInt64 (int number, FieldType type, int64 value); @@ -181,11 +185,11 @@ class LIBPROTOBUF_EXPORT ExtensionSet { void SetEnum (int number, FieldType type, int value); void SetString(int number, FieldType type, const string& value); string * MutableString (int number, FieldType type); - Message* MutableMessage(int number, FieldType type, - const Message& prototype); - Message* MutableMessage(int number, FieldType type, - const Descriptor* message_type, - MessageFactory* factory); + MessageLite* MutableMessage(int number, FieldType type, + const MessageLite& prototype); + MessageLite* MutableMessage(int number, FieldType type, + const Descriptor* message_type, + MessageFactory* factory); // repeated fields ------------------------------------------------- @@ -198,7 +202,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet { bool GetRepeatedBool (int number, int index) const; int GetRepeatedEnum (int number, int index) const; const string & GetRepeatedString (int number, int index) const; - const Message& GetRepeatedMessage(int number, int index) const; + const MessageLite& GetRepeatedMessage(int number, int index) const; void SetRepeatedInt32 (int number, int index, int32 value); void SetRepeatedInt64 (int number, int index, int64 value); @@ -210,7 +214,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet { void SetRepeatedEnum (int number, int index, int value); void SetRepeatedString(int number, int index, const string& value); string * MutableRepeatedString (int number, int index); - Message* MutableRepeatedMessage(int number, int index); + MessageLite* MutableRepeatedMessage(int number, int index); void AddInt32 (int number, FieldType type, bool packed, int32 value); void AddInt64 (int number, FieldType type, bool packed, int64 value); @@ -222,11 +226,11 @@ class LIBPROTOBUF_EXPORT ExtensionSet { void AddEnum (int number, FieldType type, bool packed, int value); void AddString(int number, FieldType type, const string& value); string * AddString (int number, FieldType type); - Message* AddMessage(int number, FieldType type, - const Message& prototype); - Message* AddMessage(int number, FieldType type, - const Descriptor* message_type, - MessageFactory* factory); + MessageLite* AddMessage(int number, FieldType type, + const MessageLite& prototype); + MessageLite* AddMessage(int number, FieldType type, + const Descriptor* message_type, + MessageFactory* factory); void RemoveLast(int number); void SwapElements(int number, int index1, int index2); @@ -252,9 +256,31 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // methods of ExtensionSet, this only works for generated message types -- // it looks up extensions registered using RegisterExtension(). bool ParseField(uint32 tag, io::CodedInputStream* input, - const Message* containing_type, + const MessageLite* containing_type, + FieldSkipper* field_skipper); + + // Specific versions for lite or full messages (constructs the appropriate + // FieldSkipper automatically). + bool ParseField(uint32 tag, io::CodedInputStream* input, + const MessageLite* containing_type); + bool ParseField(uint32 tag, io::CodedInputStream* input, + const MessageLite* containing_type, UnknownFieldSet* unknown_fields); + // Parse an entire message in MessageSet format. Such messages have no + // fields, only extensions. + bool ParseMessageSet(io::CodedInputStream* input, + const MessageLite* containing_type, + FieldSkipper* field_skipper); + + // Specific versions for lite or full messages (constructs the appropriate + // FieldSkipper automatically). + bool ParseMessageSet(io::CodedInputStream* input, + const MessageLite* containing_type); + bool ParseMessageSet(io::CodedInputStream* input, + const MessageLite* containing_type, + UnknownFieldSet* unknown_fields); + // Write all extension fields with field numbers in the range // [start_field_number, end_field_number) // to the output stream, using the cached sizes computed when ByteSize() was @@ -272,37 +298,50 @@ class LIBPROTOBUF_EXPORT ExtensionSet { int end_field_number, uint8* target) const; + // Like above but serializes in MessageSet format. + void SerializeMessageSetWithCachedSizes(io::CodedOutputStream* output) const; + uint8* SerializeMessageSetWithCachedSizesToArray(uint8* target) const; + // Returns the total serialized size of all the extensions. int ByteSize() const; + // Like ByteSize() but uses MessageSet format. + int MessageSetByteSize() const; + // Returns (an estimate of) the total number of bytes used for storing the - // extensions in memory, excluding sizeof(*this). + // extensions in memory, excluding sizeof(*this). If the ExtensionSet is + // for a lite message (and thus possibly contains lite messages), the results + // are undefined (might work, might crash, might corrupt data, might not even + // be linked in). It's up to the protocol compiler to avoid calling this on + // such ExtensionSets (easy enough since lite messages don't implement + // SpaceUsed()). int SpaceUsedExcludingSelf() const; private: + struct Extension { union { - int32 int32_value; - int64 int64_value; - uint32 uint32_value; - uint64 uint64_value; - float float_value; - double double_value; - bool bool_value; - int enum_value; - string* string_value; - Message* message_value; - - RepeatedField * repeated_int32_value; - RepeatedField * repeated_int64_value; - RepeatedField * repeated_uint32_value; - RepeatedField * repeated_uint64_value; - RepeatedField * repeated_float_value; - RepeatedField * repeated_double_value; - RepeatedField * repeated_bool_value; - RepeatedField * repeated_enum_value; - RepeatedPtrField* repeated_string_value; - RepeatedPtrField* repeated_message_value; + int32 int32_value; + int64 int64_value; + uint32 uint32_value; + uint64 uint64_value; + float float_value; + double double_value; + bool bool_value; + int enum_value; + string* string_value; + MessageLite* message_value; + + RepeatedField * repeated_int32_value; + RepeatedField * repeated_int64_value; + RepeatedField * repeated_uint32_value; + RepeatedField * repeated_uint64_value; + RepeatedField * repeated_float_value; + RepeatedField * repeated_double_value; + RepeatedField * repeated_bool_value; + RepeatedField * repeated_enum_value; + RepeatedPtrField* repeated_string_value; + RepeatedPtrField* repeated_message_value; }; FieldType type; @@ -328,7 +367,11 @@ class LIBPROTOBUF_EXPORT ExtensionSet { void SerializeFieldWithCachedSizes( int number, io::CodedOutputStream* output) const; + void SerializeMessageSetItemWithCachedSizes( + int number, + io::CodedOutputStream* output) const; int ByteSize(int number) const; + int MessageSetItemByteSize(int number) const; void Clear(); int GetSize() const; void Free(); @@ -339,6 +382,13 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // already exist. Returns true if the extension did not already exist. bool MaybeNewExtension(int number, Extension** result); + // Parse a single MessageSet item -- called just after the item group start + // tag has been read. + bool ParseMessageSetItem(io::CodedInputStream* input, + const MessageLite* containing_type, + FieldSkipper* field_skipper); + + // The Extension struct is small enough to be passed by value, so we use it // directly as the value type in the map rather than use pointers. We use // a map rather than hash_map here because we expect most ExtensionSets will diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc new file mode 100644 index 00000000..dbe9e336 --- /dev/null +++ b/src/google/protobuf/extension_set_heavy.cc @@ -0,0 +1,218 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Contains methods defined in extension_set.h which cannot be part of the +// lite library because they use descriptors or reflection. + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +void ExtensionSet::AppendToList(const Descriptor* containing_type, + const DescriptorPool* pool, + vector* output) const { + for (map::const_iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + bool has = false; + if (iter->second.is_repeated) { + has = iter->second.GetSize() > 0; + } else { + has = !iter->second.is_cleared; + } + + if (has) { + output->push_back( + pool->FindExtensionByNumber(containing_type, iter->first)); + } + } +} + +inline FieldDescriptor::CppType cpp_type(FieldType type) { + return FieldDescriptor::TypeToCppType( + static_cast(type)); +} + +#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \ + GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \ + : FieldDescriptor::LABEL_OPTIONAL, \ + FieldDescriptor::LABEL_##LABEL); \ + GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE) + +const MessageLite& ExtensionSet::GetMessage(int number, + const Descriptor* message_type, + MessageFactory* factory) const { + map::const_iterator iter = extensions_.find(number); + if (iter == extensions_.end() || iter->second.is_cleared) { + // Not present. Return the default value. + return *factory->GetPrototype(message_type); + } else { + GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); + return *iter->second.message_value; + } +} + +MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, + const Descriptor* message_type, + MessageFactory* factory) { + Extension* extension; + if (MaybeNewExtension(number, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE); + extension->is_repeated = false; + extension->is_packed = false; + const MessageLite* prototype = factory->GetPrototype(message_type); + GOOGLE_CHECK(prototype != NULL); + extension->message_value = prototype->New(); + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + } + extension->is_cleared = false; + return extension->message_value; +} + +MessageLite* ExtensionSet::AddMessage(int number, FieldType type, + const Descriptor* message_type, + MessageFactory* factory) { + Extension* extension; + if (MaybeNewExtension(number, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE); + extension->is_repeated = true; + extension->repeated_message_value = + new RepeatedPtrField(); + } else { + GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE); + } + + // RepeatedPtrField does not know how to Add() since it cannot + // allocate an abstract object, so we have to be tricky. + MessageLite* result = extension->repeated_message_value + ->AddFromCleared >(); + if (result == NULL) { + const MessageLite* prototype; + if (extension->repeated_message_value->size() == 0) { + prototype = factory->GetPrototype(message_type); + GOOGLE_CHECK(prototype != NULL); + } else { + prototype = &extension->repeated_message_value->Get(0); + } + result = prototype->New(); + extension->repeated_message_value->AddAllocated(result); + } + return result; +} + +bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, + const MessageLite* containing_type, + UnknownFieldSet* unknown_fields) { + UnknownFieldSetFieldSkipper skipper(unknown_fields); + return ParseField(tag, input, containing_type, &skipper); +} + +bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, + const MessageLite* containing_type, + UnknownFieldSet* unknown_fields) { + UnknownFieldSetFieldSkipper skipper(unknown_fields); + return ParseMessageSet(input, containing_type, &skipper); +} + +int ExtensionSet::SpaceUsedExcludingSelf() const { + int total_size = + extensions_.size() * sizeof(map::value_type); + for (map::const_iterator iter = extensions_.begin(), + end = extensions_.end(); + iter != end; + ++iter) { + total_size += iter->second.SpaceUsedExcludingSelf(); + } + return total_size; +} + +int ExtensionSet::Extension::SpaceUsedExcludingSelf() const { + int total_size = 0; + if (is_repeated) { + switch (cpp_type(type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + total_size += sizeof(*repeated_##LOWERCASE##_value) + \ + repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\ + break + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE( UINT32, uint32); + HANDLE_TYPE( UINT64, uint64); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( DOUBLE, double); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, enum); + HANDLE_TYPE( STRING, string); + + case WireFormatLite::CPPTYPE_MESSAGE: + // repeated_message_value is actually a RepeatedPtrField, + // but MessageLite has no SpaceUsed(), so we must directly call + // RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type + // handler. + total_size += sizeof(*repeated_message_value) + + repeated_message_value-> + RepeatedPtrFieldBase::SpaceUsedExcludingSelf< + GenericTypeHandler >(); + break; + } + } else { + switch (cpp_type(type)) { + case WireFormatLite::CPPTYPE_STRING: + total_size += sizeof(*string_value) + + StringSpaceUsedExcludingSelf(*string_value); + break; + case WireFormatLite::CPPTYPE_MESSAGE: + total_size += down_cast(message_value)->SpaceUsed(); + break; + default: + // No extra storage costs for primitive types. + break; + } + } + return total_size; +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 0cd367de..d294e587 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -38,6 +38,7 @@ #include #include #include +#include #include namespace google { @@ -220,8 +221,36 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const { const FieldDescriptor* field = descriptor_->field(i); if (field->is_repeated()) { - total_size += GetRaw(message, field) - .GenericSpaceUsedExcludingSelf(); + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE : \ + total_size += GetRaw >(message, field) \ + .SpaceUsedExcludingSelf(); \ + break + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + total_size += GetRaw >(message, field) + .SpaceUsedExcludingSelf(); + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: + // We don't know which subclass of RepeatedPtrFieldBase the type is, + // so we use RepeatedPtrFieldBase directly. + total_size += + GetRaw(message, field) + .SpaceUsedExcludingSelf >(); + break; + } } else { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32 : @@ -274,25 +303,59 @@ void GeneratedMessageReflection::Swap( Message* message2) const { if (message1 == message2) return; + // TODO(kenton): Other Reflection methods should probably check this too. GOOGLE_CHECK_EQ(message1->GetReflection(), this) - << "Tried to swap using reflection object incompatible with message1."; - + << "First argument to Swap() (of type \"" + << message1->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type \"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; GOOGLE_CHECK_EQ(message2->GetReflection(), this) - << "Tried to swap using reflection object incompatible with message2."; + << "Second argument to Swap() (of type \"" + << message1->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type \"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; uint32* has_bits1 = MutableHasBits(message1); uint32* has_bits2 = MutableHasBits(message2); int has_bits_size = (descriptor_->field_count() + 31) / 32; for (int i = 0; i < has_bits_size; i++) { - std::swap(has_bits1[i], has_bits2[i]); + swap(has_bits1[i], has_bits2[i]); } for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); if (field->is_repeated()) { - MutableRaw(message1, field)->GenericSwap( - MutableRaw(message2, field)); + switch (field->cpp_type()) { +#define SWAP_ARRAYS(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + MutableRaw >(message1, field)->Swap( \ + MutableRaw >(message2, field)); \ + break; + + SWAP_ARRAYS(INT32 , int32 ); + SWAP_ARRAYS(INT64 , int64 ); + SWAP_ARRAYS(UINT32, uint32); + SWAP_ARRAYS(UINT64, uint64); + SWAP_ARRAYS(FLOAT , float ); + SWAP_ARRAYS(DOUBLE, double); + SWAP_ARRAYS(BOOL , bool ); + SWAP_ARRAYS(ENUM , int ); +#undef SWAP_ARRAYS + + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + MutableRaw(message1, field)->Swap( + MutableRaw(message2, field)); + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); + } } else { switch (field->cpp_type()) { #define SWAP_VALUES(CPPTYPE, TYPE) \ @@ -300,6 +363,7 @@ void GeneratedMessageReflection::Swap( swap(*MutableRaw(message1, field), \ *MutableRaw(message2, field)); \ break; + SWAP_VALUES(INT32 , int32 ); SWAP_VALUES(INT64 , int64 ); SWAP_VALUES(UINT32, uint32); @@ -307,10 +371,15 @@ void GeneratedMessageReflection::Swap( SWAP_VALUES(FLOAT , float ); SWAP_VALUES(DOUBLE, double); SWAP_VALUES(BOOL , bool ); - SWAP_VALUES(ENUM , int32 ); - SWAP_VALUES(STRING, string*); + SWAP_VALUES(ENUM , int ); SWAP_VALUES(MESSAGE, Message*); -#undef SWAP_PRIMITIVE_VALUES +#undef SWAP_VALUES + + case FieldDescriptor::CPPTYPE_STRING: + swap(*MutableRaw(message1, field), + *MutableRaw(message2, field)); + break; + default: GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); } @@ -346,7 +415,28 @@ int GeneratedMessageReflection::FieldSize(const Message& message, if (field->is_extension()) { return GetExtensionSet(message).ExtensionSize(field->number()); } else { - return GetRaw(message, field).GenericSize(); + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE : \ + return GetRaw >(message, field).size() + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + return GetRaw(message, field).size(); + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return 0; } } @@ -401,7 +491,35 @@ void GeneratedMessageReflection::ClearField( } } } else { - MutableRaw(message, field)->GenericClear(); + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE : \ + MutableRaw >(message, field)->Clear(); \ + break + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: { + MutableRaw >(message, field)->Clear(); + break; + } + + case FieldDescriptor::CPPTYPE_MESSAGE: { + // We don't know which subclass of RepeatedPtrFieldBase the type is, + // so we use RepeatedPtrFieldBase directly. + MutableRaw(message, field) + ->Clear >(); + break; + } + } } } @@ -414,7 +532,31 @@ void GeneratedMessageReflection::RemoveLast( if (field->is_extension()) { MutableExtensionSet(message)->RemoveLast(field->number()); } else { - MutableRaw(message, field)->GenericRemoveLast(); + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE : \ + MutableRaw >(message, field)->RemoveLast(); \ + break + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + MutableRaw >(message, field)->RemoveLast(); + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: + MutableRaw(message, field) + ->RemoveLast >(); + break; + } } } @@ -427,11 +569,31 @@ void GeneratedMessageReflection::SwapElements( USAGE_CHECK_REPEATED(Swap); if (field->is_extension()) { - MutableExtensionSet(message)->SwapElements( - field->number(), index1, index2); + MutableExtensionSet(message)->SwapElements(field->number(), index1, index2); } else { - MutableRaw(message, field)->GenericSwapElements( - index1, index2); + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE : \ + MutableRaw >(message, field) \ + ->SwapElements(index1, index2); \ + break + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + MutableRaw(message, field) + ->SwapElements(index1, index2); + break; + } } } @@ -456,7 +618,7 @@ void GeneratedMessageReflection::ListFields( for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); if (field->is_repeated()) { - if (GetRaw(message, field).GenericSize() > 0) { + if (FieldSize(message, field) > 0) { output->push_back(field); } } else { @@ -597,7 +759,7 @@ string GeneratedMessageReflection::GetRepeatedString( if (field->is_extension()) { return GetExtensionSet(message).GetRepeatedString(field->number(), index); } else { - return GetRepeatedField(message, field, index); + return GetRepeatedPtrField(message, field, index); } } @@ -608,7 +770,7 @@ const string& GeneratedMessageReflection::GetRepeatedStringReference( if (field->is_extension()) { return GetExtensionSet(message).GetRepeatedString(field->number(), index); } else { - return GetRepeatedField(message, field, index); + return GetRepeatedPtrField(message, field, index); } } @@ -621,7 +783,7 @@ void GeneratedMessageReflection::SetRepeatedString( MutableExtensionSet(message)->SetRepeatedString( field->number(), index, value); } else { - SetRepeatedField(message, field, index, value); + *MutableRepeatedField(message, field, index) = value; } } @@ -634,7 +796,7 @@ void GeneratedMessageReflection::AddString( MutableExtensionSet(message)->AddString(field->number(), field->type(), value); } else { - AddField(message, field, value); + *AddField(message, field) = value; } } @@ -725,9 +887,10 @@ const Message& GeneratedMessageReflection::GetMessage( USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE); if (field->is_extension()) { - return GetExtensionSet(message).GetMessage(field->number(), - field->message_type(), - message_factory_); + return static_cast( + GetExtensionSet(message).GetMessage(field->number(), + field->message_type(), + message_factory_)); } else { const Message* result = GetRaw(message, field); if (result == NULL) { @@ -742,10 +905,11 @@ Message* GeneratedMessageReflection::MutableMessage( USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE); if (field->is_extension()) { - return MutableExtensionSet(message)->MutableMessage(field->number(), - field->type(), - field->message_type(), - message_factory_); + return static_cast( + MutableExtensionSet(message)->MutableMessage(field->number(), + field->type(), + field->message_type(), + message_factory_)); } else { Message** result = MutableField(message, field); if (*result == NULL) { @@ -761,9 +925,11 @@ const Message& GeneratedMessageReflection::GetRepeatedMessage( USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE); if (field->is_extension()) { - return GetExtensionSet(message).GetRepeatedMessage(field->number(), index); + return static_cast( + GetExtensionSet(message).GetRepeatedMessage(field->number(), index)); } else { - return GetRepeatedField(message, field, index); + return GetRaw(message, field) + .Get >(index); } } @@ -772,10 +938,12 @@ Message* GeneratedMessageReflection::MutableRepeatedMessage( USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE); if (field->is_extension()) { - return MutableExtensionSet(message)->MutableRepeatedMessage( - field->number(), index); + return static_cast( + MutableExtensionSet(message)->MutableRepeatedMessage( + field->number(), index)); } else { - return MutableRepeatedField(message, field, index); + return MutableRaw(message, field) + ->Mutable >(index); } } @@ -784,12 +952,29 @@ Message* GeneratedMessageReflection::AddMessage( USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE); if (field->is_extension()) { - return MutableExtensionSet(message)->AddMessage(field->number(), - field->type(), - field->message_type(), - message_factory_); + return static_cast( + MutableExtensionSet(message)->AddMessage(field->number(), + field->type(), + field->message_type(), + message_factory_)); } else { - return AddField(message, field); + // We can't use AddField() because RepeatedPtrFieldBase doesn't + // know how to allocate one. + RepeatedPtrFieldBase* repeated = + MutableRaw(message, field); + Message* result = repeated->AddFromCleared >(); + if (result == NULL) { + // We must allocate a new object. + const Message* prototype; + if (repeated->size() == 0) { + prototype = message_factory_->GetPrototype(field->message_type()); + } else { + prototype = &repeated->Get >(0); + } + result = prototype->New(); + repeated->AddAllocated >(result); + } + return result; } } @@ -925,46 +1110,46 @@ inline Type* GeneratedMessageReflection::MutableField( } template -inline const Type& GeneratedMessageReflection::GetRepeatedField( +inline Type GeneratedMessageReflection::GetRepeatedField( + const Message& message, const FieldDescriptor* field, int index) const { + return GetRaw >(message, field).Get(index); +} + +template +inline const Type& GeneratedMessageReflection::GetRepeatedPtrField( const Message& message, const FieldDescriptor* field, int index) const { - return *reinterpret_cast( - GetRaw(message, field).GenericGet(index)); + return GetRaw >(message, field).Get(index); } template inline void GeneratedMessageReflection::SetRepeatedField( Message* message, const FieldDescriptor* field, - int index, const Type& value) const { - GenericRepeatedField* repeated = - MutableRaw(message, field); - *reinterpret_cast(repeated->GenericMutable(index)) = value; + int index, Type value) const { + MutableRaw >(message, field)->Set(index, value); } template inline Type* GeneratedMessageReflection::MutableRepeatedField( Message* message, const FieldDescriptor* field, int index) const { - GenericRepeatedField* repeated = - MutableRaw(message, field); - return reinterpret_cast(repeated->GenericMutable(index)); + RepeatedPtrField* repeated = + MutableRaw >(message, field); + return repeated->Mutable(index); } template inline void GeneratedMessageReflection::AddField( - Message* message, const FieldDescriptor* field, const Type& value) const { - GenericRepeatedField* repeated = - MutableRaw(message, field); - *reinterpret_cast(repeated->GenericAdd()) = value; + Message* message, const FieldDescriptor* field, Type value) const { + MutableRaw >(message, field)->Add(value); } template inline Type* GeneratedMessageReflection::AddField( Message* message, const FieldDescriptor* field) const { - GenericRepeatedField* repeated = - MutableRaw(message, field); - return reinterpret_cast(repeated->GenericAdd()); + RepeatedPtrField* repeated = + MutableRaw >(message, field); + return repeated->Add(); } - } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h index 702f189e..d0b5b43b 100644 --- a/src/google/protobuf/generated_message_reflection.h +++ b/src/google/protobuf/generated_message_reflection.h @@ -142,7 +142,7 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { void ClearField(Message* message, const FieldDescriptor* field) const; void RemoveLast(Message* message, const FieldDescriptor* field) const; void Swap(Message* message1, Message* message2) const; - void SwapElements(Message* message, const FieldDescriptor* field, + void SwapElements(Message* message, const FieldDescriptor* field, int index1, int index2) const; void ListFields(const Message& message, vector* output) const; @@ -314,20 +314,24 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { inline Type* MutableField(Message* message, const FieldDescriptor* field) const; template - inline const Type& GetRepeatedField(const Message& message, - const FieldDescriptor* field, - int index) const; + inline Type GetRepeatedField(const Message& message, + const FieldDescriptor* field, + int index) const; + template + inline const Type& GetRepeatedPtrField(const Message& message, + const FieldDescriptor* field, + int index) const; template inline void SetRepeatedField(Message* message, const FieldDescriptor* field, int index, - const Type& value) const; + Type value) const; template inline Type* MutableRepeatedField(Message* message, const FieldDescriptor* field, int index) const; template inline void AddField(Message* message, - const FieldDescriptor* field, const Type& value) const; + const FieldDescriptor* field, Type value) const; template inline Type* AddField(Message* message, const FieldDescriptor* field) const; @@ -388,11 +392,6 @@ inline To dynamic_cast_if_available(From from) { #endif } -// Compute the space used by a string, not including sizeof(string) itself. -// This is slightly complicated because small strings store their data within -// the string object but large strings do not. -LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str); - // Helper for EnumType_Parse functions: try to parse the string 'name' as an // enum name of the given type, returning true and filling in value on success, // or returning false and leaving value unchanged on failure. @@ -415,7 +414,6 @@ bool ParseNamedEnum(const EnumDescriptor* descriptor, // descriptor.h. LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value); - } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc new file mode 100644 index 00000000..9470bb08 --- /dev/null +++ b/src/google/protobuf/generated_message_util.cc @@ -0,0 +1,44 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include + +namespace google { +namespace protobuf { +namespace internal { + + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h new file mode 100644 index 00000000..80dd028e --- /dev/null +++ b/src/google/protobuf/generated_message_util.h @@ -0,0 +1,65 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file contains miscellaneous helper code used by generated code -- +// including lite types -- but which should not be used directly by users. + +#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ +#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ + +#include + + +namespace google { +namespace protobuf { +namespace internal { + +// Annotation for the compiler to emit a deprecation message if a field marked +// with option 'deprecated=true' is used in the code. +// +// For internal use in the pb.cc files, deprecation warnings are suppressed +// there. +#undef DEPRECATED_PROTOBUF_FIELD +#if !defined(INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION) +# define DEPRECATED_PROTOBUF_FIELD GOOGLE_ATTRIBUTE_DEPRECATED +#else +# define DEPRECATED_PROTOBUF_FIELD +#endif + + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc index 0a00d2bb..e17a4775 100644 --- a/src/google/protobuf/io/coded_stream.cc +++ b/src/google/protobuf/io/coded_stream.cc @@ -80,18 +80,49 @@ CodedInputStream::CodedInputStream(ZeroCopyInputStream* input) total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold), recursion_depth_(0), recursion_limit_(kDefaultRecursionLimit) { + // Eagerly Refresh() so buffer space is immediately available. + Refresh(); +} + +CodedInputStream::CodedInputStream(const uint8* buffer, int size) + : input_(NULL), + buffer_(buffer), + buffer_size_(size), + total_bytes_read_(size), + overflow_bytes_(0), + last_tag_(0), + legitimate_message_end_(false), + aliasing_enabled_(false), + current_limit_(size), + buffer_size_after_limit_(0), + total_bytes_limit_(kDefaultTotalBytesLimit), + total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold), + recursion_depth_(0), + recursion_limit_(kDefaultRecursionLimit) { + // Note that setting current_limit_ == size is important to prevent some + // code paths from trying to access input_ and segfaulting. } CodedInputStream::~CodedInputStream() { + if (input_ != NULL) { + BackUpInputToCurrentPosition(); + } +} + + +void CodedInputStream::BackUpInputToCurrentPosition() { int backup_bytes = buffer_size_ + buffer_size_after_limit_ + overflow_bytes_; if (backup_bytes > 0) { - // We still have bytes left over from the last buffer. Back up over - // them. input_->BackUp(backup_bytes); + + // total_bytes_read_ doesn't include overflow_bytes_. + total_bytes_read_ -= buffer_size_ + buffer_size_after_limit_; + buffer_size_ = 0; + buffer_size_after_limit_ = 0; + overflow_bytes_ = 0; } } - inline void CodedInputStream::RecomputeBufferLimits() { buffer_size_ += buffer_size_after_limit_; int closest_limit = min(current_limit_, total_bytes_limit_); @@ -193,8 +224,10 @@ bool CodedInputStream::Skip(int count) { int bytes_until_limit = closest_limit - total_bytes_read_; if (bytes_until_limit < count) { // We hit the limit. Skip up to it then fail. - total_bytes_read_ = closest_limit; - input_->Skip(bytes_until_limit); + if (bytes_until_limit > 0) { + total_bytes_read_ = closest_limit; + input_->Skip(bytes_until_limit); + } return false; } @@ -216,6 +249,7 @@ bool CodedInputStream::ReadRaw(void* buffer, int size) { memcpy(buffer, buffer_, buffer_size_); buffer = reinterpret_cast(buffer) + buffer_size_; size -= buffer_size_; + Advance(buffer_size_); if (!Refresh()) return false; } @@ -247,6 +281,7 @@ bool CodedInputStream::ReadString(string* buffer, int size) { buffer->append(reinterpret_cast(buffer_), buffer_size_); } size -= buffer_size_; + Advance(buffer_size_); if (!Refresh()) return false; } @@ -441,11 +476,11 @@ bool CodedInputStream::ReadVarint64(uint64* value) { } bool CodedInputStream::Refresh() { - if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0) { - // We've hit a limit. Stop. - buffer_ += buffer_size_; - buffer_size_ = 0; + GOOGLE_DCHECK_EQ(buffer_size_, 0); + if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 || + total_bytes_read_ == current_limit_) { + // We've hit a limit. Stop. int current_position = total_bytes_read_ - buffer_size_after_limit_; if (current_position >= total_bytes_limit_ && @@ -570,10 +605,7 @@ void CodedOutputStream::WriteLittleEndian32(uint32 value) { bool use_fast = buffer_size_ >= sizeof(value); uint8* ptr = use_fast ? buffer_ : bytes; - ptr[0] = static_cast(value ); - ptr[1] = static_cast(value >> 8); - ptr[2] = static_cast(value >> 16); - ptr[3] = static_cast(value >> 24); + WriteLittleEndian32ToArray(value, ptr); if (use_fast) { Advance(sizeof(value)); @@ -582,32 +614,13 @@ void CodedOutputStream::WriteLittleEndian32(uint32 value) { } } -uint8* CodedOutputStream::WriteLittleEndian32ToArray( - uint32 value, uint8* target) { - target[0] = static_cast(value ); - target[1] = static_cast(value >> 8); - target[2] = static_cast(value >> 16); - target[3] = static_cast(value >> 24); - return target + sizeof(value); -} - void CodedOutputStream::WriteLittleEndian64(uint64 value) { uint8 bytes[sizeof(value)]; - uint32 part0 = static_cast(value); - uint32 part1 = static_cast(value >> 32); - bool use_fast = buffer_size_ >= sizeof(value); uint8* ptr = use_fast ? buffer_ : bytes; - ptr[0] = static_cast(part0 ); - ptr[1] = static_cast(part0 >> 8); - ptr[2] = static_cast(part0 >> 16); - ptr[3] = static_cast(part0 >> 24); - ptr[4] = static_cast(part1 ); - ptr[5] = static_cast(part1 >> 8); - ptr[6] = static_cast(part1 >> 16); - ptr[7] = static_cast(part1 >> 24); + WriteLittleEndian64ToArray(value, ptr); if (use_fast) { Advance(sizeof(value)); @@ -616,23 +629,6 @@ void CodedOutputStream::WriteLittleEndian64(uint64 value) { } } -uint8* CodedOutputStream::WriteLittleEndian64ToArray( - uint64 value, uint8* target) { - uint32 part0 = static_cast(value); - uint32 part1 = static_cast(value >> 32); - - target[0] = static_cast(part0 ); - target[1] = static_cast(part0 >> 8); - target[2] = static_cast(part0 >> 16); - target[3] = static_cast(part0 >> 24); - target[4] = static_cast(part1 ); - target[5] = static_cast(part1 >> 8); - target[6] = static_cast(part1 >> 16); - target[7] = static_cast(part1 >> 24); - - return target + sizeof(value); -} - inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline( uint32 value, uint8* target) { target[0] = static_cast(value | 0x80); diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index 9e450216..fa023f35 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -110,6 +110,9 @@ #define GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ #include +#ifndef _MSC_VER +#include +#endif // !_MSC_VER #include namespace google { @@ -137,6 +140,11 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Create a CodedInputStream that reads from the given ZeroCopyInputStream. explicit CodedInputStream(ZeroCopyInputStream* input); + // Create a CodedInputStream that reads from the given flat array. This is + // faster than using an ArrayInputStream. PushLimit(size) is implied by + // this constructor. + explicit CodedInputStream(const uint8* buffer, int size); + // Destroy the CodedInputStream and position the underlying // ZeroCopyInputStream at the first unread byte. If an error occurred while // reading (causing a method to return false), then the exact position of @@ -360,6 +368,9 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Advance the buffer by a given number of bytes. void Advance(int amount); + // Back up input_ to the current buffer position. + void BackUpInputToCurrentPosition(); + // Recomputes the value of buffer_size_after_limit_. Must be called after // current_limit_ or total_bytes_limit_ changes. void RecomputeBufferLimits(); @@ -664,6 +675,41 @@ inline uint8* CodedOutputStream::WriteVarint32SignExtendedToArray( } } +inline uint8* CodedOutputStream::WriteLittleEndian32ToArray(uint32 value, + uint8* target) { +#if !defined(PROTOBUF_TEST_NOT_LITTLE_ENDIAN) && \ + defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN + memcpy(target, &value, sizeof(value)); +#else + target[0] = static_cast(value ); + target[1] = static_cast(value >> 8); + target[2] = static_cast(value >> 16); + target[3] = static_cast(value >> 24); +#endif + return target + sizeof(value); +} + +inline uint8* CodedOutputStream::WriteLittleEndian64ToArray(uint64 value, + uint8* target) { +#if !defined(PROTOBUF_TEST_NOT_LITTLE_ENDIAN) && \ + defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN + memcpy(target, &value, sizeof(value)); +#else + uint32 part0 = static_cast(value); + uint32 part1 = static_cast(value >> 32); + + target[0] = static_cast(part0 ); + target[1] = static_cast(part0 >> 8); + target[2] = static_cast(part0 >> 16); + target[3] = static_cast(part0 >> 24); + target[4] = static_cast(part1 ); + target[5] = static_cast(part1 >> 8); + target[6] = static_cast(part1 >> 16); + target[7] = static_cast(part1 >> 24); +#endif + return target + sizeof(value); +} + inline void CodedOutputStream::WriteTag(uint32 value) { WriteVarint32(value); } diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc index d8d0e70d..243b3e32 100644 --- a/src/google/protobuf/io/gzip_stream.cc +++ b/src/google/protobuf/io/gzip_stream.cc @@ -1,5 +1,5 @@ // Protocol Buffers - Google's data interchange format -// Copyright 2009 Google Inc. All rights reserved. +// Copyright 2008 Google Inc. All rights reserved. // http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without @@ -29,8 +29,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Author: brianolson@google.com (Brian Olson) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. // // This file contains the implementation of classes GzipInputStream and // GzipOutputStream. @@ -39,6 +37,7 @@ #if HAVE_ZLIB #include + #include namespace google { @@ -291,6 +290,6 @@ bool GzipOutputStream::Close() { } // namespace io } // namespace protobuf -} // namespace google #endif // HAVE_ZLIB +} // namespace google diff --git a/src/google/protobuf/io/gzip_stream.h b/src/google/protobuf/io/gzip_stream.h index 4f29499a..50a2ad70 100644 --- a/src/google/protobuf/io/gzip_stream.h +++ b/src/google/protobuf/io/gzip_stream.h @@ -1,5 +1,5 @@ // Protocol Buffers - Google's data interchange format -// Copyright 2009 Google Inc. All rights reserved. +// Copyright 2008 Google Inc. All rights reserved. // http://code.google.com/p/protobuf/ // // Redistribution and use in source and binary forms, with or without @@ -29,8 +29,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Author: brianolson@google.com (Brian Olson) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. // // This file contains the definition for classes GzipInputStream and // GzipOutputStream. @@ -173,6 +171,6 @@ class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream { } // namespace io } // namespace protobuf -} // namespace google +} // namespace google #endif // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__ diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc index 4823912a..0bda451b 100644 --- a/src/google/protobuf/io/tokenizer.cc +++ b/src/google/protobuf/io/tokenizer.cc @@ -571,7 +571,7 @@ bool Tokenizer::ParseInteger(const string& text, uint64 max_value, const char* ptr = text.c_str(); int base = 10; if (ptr[0] == '0') { - if (ptr[1] == 'x') { + if (ptr[1] == 'x' || ptr[1] == 'X') { // This is hex. base = 16; ptr += 2; diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc index dd7ed5c8..eac1455d 100644 --- a/src/google/protobuf/io/tokenizer_unittest.cc +++ b/src/google/protobuf/io/tokenizer_unittest.cc @@ -487,6 +487,7 @@ TEST_F(TokenizerTest, ParseInteger) { EXPECT_EQ(0xabcdef12u, ParseInteger("0xABCDEF12")); EXPECT_EQ(kuint64max, ParseInteger("0xFFFFFFFFFFFFFFFF")); EXPECT_EQ(01234567, ParseInteger("01234567")); + EXPECT_EQ(0X123, ParseInteger("0X123")); // Test invalid integers that may still be tokenized as integers. EXPECT_EQ(0, ParseInteger("0x")); diff --git a/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc index 0b4516ef..1384c746 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl.cc @@ -60,7 +60,6 @@ namespace io { namespace { - // EINTR sucks. int close_no_eintr(int fd) { int result; @@ -70,352 +69,8 @@ int close_no_eintr(int fd) { return result; } -// Default block size for Copying{In,Out}putStreamAdaptor. -static const int kDefaultBlockSize = 8192; - } // namespace -// =================================================================== - -ArrayInputStream::ArrayInputStream(const void* data, int size, - int block_size) - : data_(reinterpret_cast(data)), - size_(size), - block_size_(block_size > 0 ? block_size : size), - position_(0), - last_returned_size_(0) { -} - -ArrayInputStream::~ArrayInputStream() { -} - -bool ArrayInputStream::Next(const void** data, int* size) { - if (position_ < size_) { - last_returned_size_ = min(block_size_, size_ - position_); - *data = data_ + position_; - *size = last_returned_size_; - position_ += last_returned_size_; - return true; - } else { - // We're at the end of the array. - last_returned_size_ = 0; // Don't let caller back up. - return false; - } -} - -void ArrayInputStream::BackUp(int count) { - GOOGLE_CHECK_GT(last_returned_size_, 0) - << "BackUp() can only be called after a successful Next()."; - GOOGLE_CHECK_LE(count, last_returned_size_); - GOOGLE_CHECK_GE(count, 0); - position_ -= count; - last_returned_size_ = 0; // Don't let caller back up further. -} - -bool ArrayInputStream::Skip(int count) { - GOOGLE_CHECK_GE(count, 0); - last_returned_size_ = 0; // Don't let caller back up. - if (count > size_ - position_) { - position_ = size_; - return false; - } else { - position_ += count; - return true; - } -} - -int64 ArrayInputStream::ByteCount() const { - return position_; -} - - -// =================================================================== - -ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size) - : data_(reinterpret_cast(data)), - size_(size), - block_size_(block_size > 0 ? block_size : size), - position_(0), - last_returned_size_(0) { -} - -ArrayOutputStream::~ArrayOutputStream() { -} - -bool ArrayOutputStream::Next(void** data, int* size) { - if (position_ < size_) { - last_returned_size_ = min(block_size_, size_ - position_); - *data = data_ + position_; - *size = last_returned_size_; - position_ += last_returned_size_; - return true; - } else { - // We're at the end of the array. - last_returned_size_ = 0; // Don't let caller back up. - return false; - } -} - -void ArrayOutputStream::BackUp(int count) { - GOOGLE_CHECK_GT(last_returned_size_, 0) - << "BackUp() can only be called after a successful Next()."; - GOOGLE_CHECK_LE(count, last_returned_size_); - GOOGLE_CHECK_GE(count, 0); - position_ -= count; - last_returned_size_ = 0; // Don't let caller back up further. -} - -int64 ArrayOutputStream::ByteCount() const { - return position_; -} - -// =================================================================== - -StringOutputStream::StringOutputStream(string* target) - : target_(target) { -} - -StringOutputStream::~StringOutputStream() { -} - -bool StringOutputStream::Next(void** data, int* size) { - int old_size = target_->size(); - - // Grow the string. - if (old_size < target_->capacity()) { - // Resize the string to match its capacity, since we can get away - // without a memory allocation this way. - STLStringResizeUninitialized(target_, target_->capacity()); - } else { - // Size has reached capacity, so double the size. Also make sure - // that the new size is at least kMinimumSize. - STLStringResizeUninitialized( - target_, - max(old_size * 2, - kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness. - } - - *data = string_as_array(target_) + old_size; - *size = target_->size() - old_size; - return true; -} - -void StringOutputStream::BackUp(int count) { - GOOGLE_CHECK_GE(count, 0); - GOOGLE_CHECK_LE(count, target_->size()); - target_->resize(target_->size() - count); -} - -int64 StringOutputStream::ByteCount() const { - return target_->size(); -} - -// =================================================================== - - -// =================================================================== - -CopyingInputStream::~CopyingInputStream() {} - -int CopyingInputStream::Skip(int count) { - char junk[4096]; - int skipped = 0; - while (skipped < count) { - int bytes = Read(junk, min(count - skipped, - implicit_cast(sizeof(junk)))); - if (bytes <= 0) { - // EOF or read error. - return skipped; - } - skipped += bytes; - } - return skipped; -} - -CopyingInputStreamAdaptor::CopyingInputStreamAdaptor( - CopyingInputStream* copying_stream, int block_size) - : copying_stream_(copying_stream), - owns_copying_stream_(false), - failed_(false), - position_(0), - buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize), - buffer_used_(0), - backup_bytes_(0) { -} - -CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() { - if (owns_copying_stream_) { - delete copying_stream_; - } -} - -bool CopyingInputStreamAdaptor::Next(const void** data, int* size) { - if (failed_) { - // Already failed on a previous read. - return false; - } - - AllocateBufferIfNeeded(); - - if (backup_bytes_ > 0) { - // We have data left over from a previous BackUp(), so just return that. - *data = buffer_.get() + buffer_used_ - backup_bytes_; - *size = backup_bytes_; - backup_bytes_ = 0; - return true; - } - - // Read new data into the buffer. - buffer_used_ = copying_stream_->Read(buffer_.get(), buffer_size_); - if (buffer_used_ <= 0) { - // EOF or read error. We don't need the buffer anymore. - if (buffer_used_ < 0) { - // Read error (not EOF). - failed_ = true; - } - FreeBuffer(); - return false; - } - position_ += buffer_used_; - - *size = buffer_used_; - *data = buffer_.get(); - return true; -} - -void CopyingInputStreamAdaptor::BackUp(int count) { - GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL) - << " BackUp() can only be called after Next()."; - GOOGLE_CHECK_LE(count, buffer_used_) - << " Can't back up over more bytes than were returned by the last call" - " to Next()."; - GOOGLE_CHECK_GE(count, 0) - << " Parameter to BackUp() can't be negative."; - - backup_bytes_ = count; -} - -bool CopyingInputStreamAdaptor::Skip(int count) { - GOOGLE_CHECK_GE(count, 0); - - if (failed_) { - // Already failed on a previous read. - return false; - } - - // First skip any bytes left over from a previous BackUp(). - if (backup_bytes_ >= count) { - // We have more data left over than we're trying to skip. Just chop it. - backup_bytes_ -= count; - return true; - } - - count -= backup_bytes_; - backup_bytes_ = 0; - - int skipped = copying_stream_->Skip(count); - position_ += skipped; - return skipped == count; -} - -int64 CopyingInputStreamAdaptor::ByteCount() const { - return position_ - backup_bytes_; -} - -void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() { - if (buffer_.get() == NULL) { - buffer_.reset(new uint8[buffer_size_]); - } -} - -void CopyingInputStreamAdaptor::FreeBuffer() { - GOOGLE_CHECK_EQ(backup_bytes_, 0); - buffer_used_ = 0; - buffer_.reset(); -} - -// =================================================================== - -CopyingOutputStream::~CopyingOutputStream() {} - -CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor( - CopyingOutputStream* copying_stream, int block_size) - : copying_stream_(copying_stream), - owns_copying_stream_(false), - failed_(false), - position_(0), - buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize), - buffer_used_(0) { -} - -CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() { - WriteBuffer(); - if (owns_copying_stream_) { - delete copying_stream_; - } -} - -bool CopyingOutputStreamAdaptor::Flush() { - return WriteBuffer(); -} - -bool CopyingOutputStreamAdaptor::Next(void** data, int* size) { - if (buffer_used_ == buffer_size_) { - if (!WriteBuffer()) return false; - } - - AllocateBufferIfNeeded(); - - *data = buffer_.get() + buffer_used_; - *size = buffer_size_ - buffer_used_; - buffer_used_ = buffer_size_; - return true; -} - -void CopyingOutputStreamAdaptor::BackUp(int count) { - GOOGLE_CHECK_GE(count, 0); - GOOGLE_CHECK_EQ(buffer_used_, buffer_size_) - << " BackUp() can only be called after Next()."; - GOOGLE_CHECK_LE(count, buffer_used_) - << " Can't back up over more bytes than were returned by the last call" - " to Next()."; - - buffer_used_ -= count; -} - -int64 CopyingOutputStreamAdaptor::ByteCount() const { - return position_ + buffer_used_; -} - -bool CopyingOutputStreamAdaptor::WriteBuffer() { - if (failed_) { - // Already failed on a previous write. - return false; - } - - if (buffer_used_ == 0) return true; - - if (copying_stream_->Write(buffer_.get(), buffer_used_)) { - position_ += buffer_used_; - buffer_used_ = 0; - return true; - } else { - failed_ = true; - FreeBuffer(); - return false; - } -} - -void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() { - if (buffer_ == NULL) { - buffer_.reset(new uint8[buffer_size_]); - } -} - -void CopyingOutputStreamAdaptor::FreeBuffer() { - buffer_used_ = 0; - buffer_.reset(); -} // =================================================================== diff --git a/src/google/protobuf/io/zero_copy_stream_impl.h b/src/google/protobuf/io/zero_copy_stream_impl.h index 448aa216..d7cf73ff 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl.h +++ b/src/google/protobuf/io/zero_copy_stream_impl.h @@ -45,6 +45,7 @@ #include #include #include +#include #include @@ -52,285 +53,6 @@ namespace google { namespace protobuf { namespace io { -// =================================================================== - -// A ZeroCopyInputStream backed by an in-memory array of bytes. -class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream { - public: - // Create an InputStream that returns the bytes pointed to by "data". - // "data" remains the property of the caller but must remain valid until - // the stream is destroyed. If a block_size is given, calls to Next() - // will return data blocks no larger than the given size. Otherwise, the - // first call to Next() returns the entire array. block_size is mainly - // useful for testing; in production you would probably never want to set - // it. - ArrayInputStream(const void* data, int size, int block_size = -1); - ~ArrayInputStream(); - - // implements ZeroCopyInputStream ---------------------------------- - bool Next(const void** data, int* size); - void BackUp(int count); - bool Skip(int count); - int64 ByteCount() const; - - - private: - const uint8* const data_; // The byte array. - const int size_; // Total size of the array. - const int block_size_; // How many bytes to return at a time. - - int position_; - int last_returned_size_; // How many bytes we returned last time Next() - // was called (used for error checking only). - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream); -}; - -// =================================================================== - -// A ZeroCopyOutputStream backed by an in-memory array of bytes. -class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream { - public: - // Create an OutputStream that writes to the bytes pointed to by "data". - // "data" remains the property of the caller but must remain valid until - // the stream is destroyed. If a block_size is given, calls to Next() - // will return data blocks no larger than the given size. Otherwise, the - // first call to Next() returns the entire array. block_size is mainly - // useful for testing; in production you would probably never want to set - // it. - ArrayOutputStream(void* data, int size, int block_size = -1); - ~ArrayOutputStream(); - - // implements ZeroCopyOutputStream --------------------------------- - bool Next(void** data, int* size); - void BackUp(int count); - int64 ByteCount() const; - - private: - uint8* const data_; // The byte array. - const int size_; // Total size of the array. - const int block_size_; // How many bytes to return at a time. - - int position_; - int last_returned_size_; // How many bytes we returned last time Next() - // was called (used for error checking only). - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream); -}; - -// =================================================================== - -// A ZeroCopyOutputStream which appends bytes to a string. -class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream { - public: - // Create a StringOutputStream which appends bytes to the given string. - // The string remains property of the caller, but it MUST NOT be accessed - // in any way until the stream is destroyed. - // - // Hint: If you call target->reserve(n) before creating the stream, - // the first call to Next() will return at least n bytes of buffer - // space. - explicit StringOutputStream(string* target); - ~StringOutputStream(); - - // implements ZeroCopyOutputStream --------------------------------- - bool Next(void** data, int* size); - void BackUp(int count); - int64 ByteCount() const; - - private: - static const int kMinimumSize = 16; - - string* target_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream); -}; - -// Note: There is no StringInputStream. Instead, just create an -// ArrayInputStream as follows: -// ArrayInputStream input(str.data(), str.size()); - -// =================================================================== - - -// =================================================================== - -// A generic traditional input stream interface. -// -// Lots of traditional input streams (e.g. file descriptors, C stdio -// streams, and C++ iostreams) expose an interface where every read -// involves copying bytes into a buffer. If you want to take such an -// interface and make a ZeroCopyInputStream based on it, simply implement -// CopyingInputStream and then use CopyingInputStreamAdaptor. -// -// CopyingInputStream implementations should avoid buffering if possible. -// CopyingInputStreamAdaptor does its own buffering and will read data -// in large blocks. -class LIBPROTOBUF_EXPORT CopyingInputStream { - public: - virtual ~CopyingInputStream(); - - // Reads up to "size" bytes into the given buffer. Returns the number of - // bytes read. Read() waits until at least one byte is available, or - // returns zero if no bytes will ever become available (EOF), or -1 if a - // permanent read error occurred. - virtual int Read(void* buffer, int size) = 0; - - // Skips the next "count" bytes of input. Returns the number of bytes - // actually skipped. This will always be exactly equal to "count" unless - // EOF was reached or a permanent read error occurred. - // - // The default implementation just repeatedly calls Read() into a scratch - // buffer. - virtual int Skip(int count); -}; - -// A ZeroCopyInputStream which reads from a CopyingInputStream. This is -// useful for implementing ZeroCopyInputStreams that read from traditional -// streams. Note that this class is not really zero-copy. -// -// If you want to read from file descriptors or C++ istreams, this is -// already implemented for you: use FileInputStream or IstreamInputStream -// respectively. -class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream { - public: - // Creates a stream that reads from the given CopyingInputStream. - // If a block_size is given, it specifies the number of bytes that - // should be read and returned with each call to Next(). Otherwise, - // a reasonable default is used. The caller retains ownership of - // copying_stream unless SetOwnsCopyingStream(true) is called. - explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream, - int block_size = -1); - ~CopyingInputStreamAdaptor(); - - // Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to - // delete the underlying CopyingInputStream when it is destroyed. - void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; } - - // implements ZeroCopyInputStream ---------------------------------- - bool Next(const void** data, int* size); - void BackUp(int count); - bool Skip(int count); - int64 ByteCount() const; - - private: - // Insures that buffer_ is not NULL. - void AllocateBufferIfNeeded(); - // Frees the buffer and resets buffer_used_. - void FreeBuffer(); - - // The underlying copying stream. - CopyingInputStream* copying_stream_; - bool owns_copying_stream_; - - // True if we have seen a permenant error from the underlying stream. - bool failed_; - - // The current position of copying_stream_, relative to the point where - // we started reading. - int64 position_; - - // Data is read into this buffer. It may be NULL if no buffer is currently - // in use. Otherwise, it points to an array of size buffer_size_. - scoped_array buffer_; - const int buffer_size_; - - // Number of valid bytes currently in the buffer (i.e. the size last - // returned by Next()). 0 <= buffer_used_ <= buffer_size_. - int buffer_used_; - - // Number of bytes in the buffer which were backed up over by a call to - // BackUp(). These need to be returned again. - // 0 <= backup_bytes_ <= buffer_used_ - int backup_bytes_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor); -}; - -// =================================================================== - -// A generic traditional output stream interface. -// -// Lots of traditional output streams (e.g. file descriptors, C stdio -// streams, and C++ iostreams) expose an interface where every write -// involves copying bytes from a buffer. If you want to take such an -// interface and make a ZeroCopyOutputStream based on it, simply implement -// CopyingOutputStream and then use CopyingOutputStreamAdaptor. -// -// CopyingOutputStream implementations should avoid buffering if possible. -// CopyingOutputStreamAdaptor does its own buffering and will write data -// in large blocks. -class LIBPROTOBUF_EXPORT CopyingOutputStream { - public: - virtual ~CopyingOutputStream(); - - // Writes "size" bytes from the given buffer to the output. Returns true - // if successful, false on a write error. - virtual bool Write(const void* buffer, int size) = 0; -}; - -// A ZeroCopyOutputStream which writes to a CopyingOutputStream. This is -// useful for implementing ZeroCopyOutputStreams that write to traditional -// streams. Note that this class is not really zero-copy. -// -// If you want to write to file descriptors or C++ ostreams, this is -// already implemented for you: use FileOutputStream or OstreamOutputStream -// respectively. -class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream { - public: - // Creates a stream that writes to the given Unix file descriptor. - // If a block_size is given, it specifies the size of the buffers - // that should be returned by Next(). Otherwise, a reasonable default - // is used. - explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream, - int block_size = -1); - ~CopyingOutputStreamAdaptor(); - - // Writes all pending data to the underlying stream. Returns false if a - // write error occurred on the underlying stream. (The underlying - // stream itself is not necessarily flushed.) - bool Flush(); - - // Call SetOwnsCopyingStream(true) to tell the CopyingOutputStreamAdaptor to - // delete the underlying CopyingOutputStream when it is destroyed. - void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; } - - // implements ZeroCopyOutputStream --------------------------------- - bool Next(void** data, int* size); - void BackUp(int count); - int64 ByteCount() const; - - private: - // Write the current buffer, if it is present. - bool WriteBuffer(); - // Insures that buffer_ is not NULL. - void AllocateBufferIfNeeded(); - // Frees the buffer. - void FreeBuffer(); - - // The underlying copying stream. - CopyingOutputStream* copying_stream_; - bool owns_copying_stream_; - - // True if we have seen a permenant error from the underlying stream. - bool failed_; - - // The current position of copying_stream_, relative to the point where - // we started writing. - int64 position_; - - // Data is written from this buffer. It may be NULL if no buffer is - // currently in use. Otherwise, it points to an array of size buffer_size_. - scoped_array buffer_; - const int buffer_size_; - - // Number of valid bytes currently in the buffer (i.e. the size last - // returned by Next()). When BackUp() is called, we just reduce this. - // 0 <= buffer_used_ <= buffer_size_. - int buffer_used_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor); -}; // =================================================================== diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc new file mode 100644 index 00000000..e8012510 --- /dev/null +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc @@ -0,0 +1,393 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace io { + +namespace { + +// Default block size for Copying{In,Out}putStreamAdaptor. +static const int kDefaultBlockSize = 8192; + +} // namespace + +// =================================================================== + +ArrayInputStream::ArrayInputStream(const void* data, int size, + int block_size) + : data_(reinterpret_cast(data)), + size_(size), + block_size_(block_size > 0 ? block_size : size), + position_(0), + last_returned_size_(0) { +} + +ArrayInputStream::~ArrayInputStream() { +} + +bool ArrayInputStream::Next(const void** data, int* size) { + if (position_ < size_) { + last_returned_size_ = min(block_size_, size_ - position_); + *data = data_ + position_; + *size = last_returned_size_; + position_ += last_returned_size_; + return true; + } else { + // We're at the end of the array. + last_returned_size_ = 0; // Don't let caller back up. + return false; + } +} + +void ArrayInputStream::BackUp(int count) { + GOOGLE_CHECK_GT(last_returned_size_, 0) + << "BackUp() can only be called after a successful Next()."; + GOOGLE_CHECK_LE(count, last_returned_size_); + GOOGLE_CHECK_GE(count, 0); + position_ -= count; + last_returned_size_ = 0; // Don't let caller back up further. +} + +bool ArrayInputStream::Skip(int count) { + GOOGLE_CHECK_GE(count, 0); + last_returned_size_ = 0; // Don't let caller back up. + if (count > size_ - position_) { + position_ = size_; + return false; + } else { + position_ += count; + return true; + } +} + +int64 ArrayInputStream::ByteCount() const { + return position_; +} + + +// =================================================================== + +ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size) + : data_(reinterpret_cast(data)), + size_(size), + block_size_(block_size > 0 ? block_size : size), + position_(0), + last_returned_size_(0) { +} + +ArrayOutputStream::~ArrayOutputStream() { +} + +bool ArrayOutputStream::Next(void** data, int* size) { + if (position_ < size_) { + last_returned_size_ = min(block_size_, size_ - position_); + *data = data_ + position_; + *size = last_returned_size_; + position_ += last_returned_size_; + return true; + } else { + // We're at the end of the array. + last_returned_size_ = 0; // Don't let caller back up. + return false; + } +} + +void ArrayOutputStream::BackUp(int count) { + GOOGLE_CHECK_GT(last_returned_size_, 0) + << "BackUp() can only be called after a successful Next()."; + GOOGLE_CHECK_LE(count, last_returned_size_); + GOOGLE_CHECK_GE(count, 0); + position_ -= count; + last_returned_size_ = 0; // Don't let caller back up further. +} + +int64 ArrayOutputStream::ByteCount() const { + return position_; +} + +// =================================================================== + +StringOutputStream::StringOutputStream(string* target) + : target_(target) { +} + +StringOutputStream::~StringOutputStream() { +} + +bool StringOutputStream::Next(void** data, int* size) { + int old_size = target_->size(); + + // Grow the string. + if (old_size < target_->capacity()) { + // Resize the string to match its capacity, since we can get away + // without a memory allocation this way. + STLStringResizeUninitialized(target_, target_->capacity()); + } else { + // Size has reached capacity, so double the size. Also make sure + // that the new size is at least kMinimumSize. + STLStringResizeUninitialized( + target_, + max(old_size * 2, + kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness. + } + + *data = string_as_array(target_) + old_size; + *size = target_->size() - old_size; + return true; +} + +void StringOutputStream::BackUp(int count) { + GOOGLE_CHECK_GE(count, 0); + GOOGLE_CHECK_LE(count, target_->size()); + target_->resize(target_->size() - count); +} + +int64 StringOutputStream::ByteCount() const { + return target_->size(); +} + +// =================================================================== + +CopyingInputStream::~CopyingInputStream() {} + +int CopyingInputStream::Skip(int count) { + char junk[4096]; + int skipped = 0; + while (skipped < count) { + int bytes = Read(junk, min(count - skipped, + implicit_cast(sizeof(junk)))); + if (bytes <= 0) { + // EOF or read error. + return skipped; + } + skipped += bytes; + } + return skipped; +} + +CopyingInputStreamAdaptor::CopyingInputStreamAdaptor( + CopyingInputStream* copying_stream, int block_size) + : copying_stream_(copying_stream), + owns_copying_stream_(false), + failed_(false), + position_(0), + buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize), + buffer_used_(0), + backup_bytes_(0) { +} + +CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() { + if (owns_copying_stream_) { + delete copying_stream_; + } +} + +bool CopyingInputStreamAdaptor::Next(const void** data, int* size) { + if (failed_) { + // Already failed on a previous read. + return false; + } + + AllocateBufferIfNeeded(); + + if (backup_bytes_ > 0) { + // We have data left over from a previous BackUp(), so just return that. + *data = buffer_.get() + buffer_used_ - backup_bytes_; + *size = backup_bytes_; + backup_bytes_ = 0; + return true; + } + + // Read new data into the buffer. + buffer_used_ = copying_stream_->Read(buffer_.get(), buffer_size_); + if (buffer_used_ <= 0) { + // EOF or read error. We don't need the buffer anymore. + if (buffer_used_ < 0) { + // Read error (not EOF). + failed_ = true; + } + FreeBuffer(); + return false; + } + position_ += buffer_used_; + + *size = buffer_used_; + *data = buffer_.get(); + return true; +} + +void CopyingInputStreamAdaptor::BackUp(int count) { + GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL) + << " BackUp() can only be called after Next()."; + GOOGLE_CHECK_LE(count, buffer_used_) + << " Can't back up over more bytes than were returned by the last call" + " to Next()."; + GOOGLE_CHECK_GE(count, 0) + << " Parameter to BackUp() can't be negative."; + + backup_bytes_ = count; +} + +bool CopyingInputStreamAdaptor::Skip(int count) { + GOOGLE_CHECK_GE(count, 0); + + if (failed_) { + // Already failed on a previous read. + return false; + } + + // First skip any bytes left over from a previous BackUp(). + if (backup_bytes_ >= count) { + // We have more data left over than we're trying to skip. Just chop it. + backup_bytes_ -= count; + return true; + } + + count -= backup_bytes_; + backup_bytes_ = 0; + + int skipped = copying_stream_->Skip(count); + position_ += skipped; + return skipped == count; +} + +int64 CopyingInputStreamAdaptor::ByteCount() const { + return position_ - backup_bytes_; +} + +void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() { + if (buffer_.get() == NULL) { + buffer_.reset(new uint8[buffer_size_]); + } +} + +void CopyingInputStreamAdaptor::FreeBuffer() { + GOOGLE_CHECK_EQ(backup_bytes_, 0); + buffer_used_ = 0; + buffer_.reset(); +} + +// =================================================================== + +CopyingOutputStream::~CopyingOutputStream() {} + +CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor( + CopyingOutputStream* copying_stream, int block_size) + : copying_stream_(copying_stream), + owns_copying_stream_(false), + failed_(false), + position_(0), + buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize), + buffer_used_(0) { +} + +CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() { + WriteBuffer(); + if (owns_copying_stream_) { + delete copying_stream_; + } +} + +bool CopyingOutputStreamAdaptor::Flush() { + return WriteBuffer(); +} + +bool CopyingOutputStreamAdaptor::Next(void** data, int* size) { + if (buffer_used_ == buffer_size_) { + if (!WriteBuffer()) return false; + } + + AllocateBufferIfNeeded(); + + *data = buffer_.get() + buffer_used_; + *size = buffer_size_ - buffer_used_; + buffer_used_ = buffer_size_; + return true; +} + +void CopyingOutputStreamAdaptor::BackUp(int count) { + GOOGLE_CHECK_GE(count, 0); + GOOGLE_CHECK_EQ(buffer_used_, buffer_size_) + << " BackUp() can only be called after Next()."; + GOOGLE_CHECK_LE(count, buffer_used_) + << " Can't back up over more bytes than were returned by the last call" + " to Next()."; + + buffer_used_ -= count; +} + +int64 CopyingOutputStreamAdaptor::ByteCount() const { + return position_ + buffer_used_; +} + +bool CopyingOutputStreamAdaptor::WriteBuffer() { + if (failed_) { + // Already failed on a previous write. + return false; + } + + if (buffer_used_ == 0) return true; + + if (copying_stream_->Write(buffer_.get(), buffer_used_)) { + position_ += buffer_used_; + buffer_used_ = 0; + return true; + } else { + failed_ = true; + FreeBuffer(); + return false; + } +} + +void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() { + if (buffer_ == NULL) { + buffer_.reset(new uint8[buffer_size_]); + } +} + +void CopyingOutputStreamAdaptor::FreeBuffer() { + buffer_used_ = 0; + buffer_.reset(); +} + +// =================================================================== + +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h new file mode 100644 index 00000000..59f18258 --- /dev/null +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h @@ -0,0 +1,338 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file contains common implementations of the interfaces defined in +// zero_copy_stream.h. These implementations cover I/O on raw arrays, +// strings, and file descriptors. Of course, many users will probably +// want to write their own implementations of these interfaces specific +// to the particular I/O abstractions they prefer to use, but these +// should cover the most common cases. + +#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ +#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ + +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace io { + +// =================================================================== + +// A ZeroCopyInputStream backed by an in-memory array of bytes. +class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream { + public: + // Create an InputStream that returns the bytes pointed to by "data". + // "data" remains the property of the caller but must remain valid until + // the stream is destroyed. If a block_size is given, calls to Next() + // will return data blocks no larger than the given size. Otherwise, the + // first call to Next() returns the entire array. block_size is mainly + // useful for testing; in production you would probably never want to set + // it. + ArrayInputStream(const void* data, int size, int block_size = -1); + ~ArrayInputStream(); + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size); + void BackUp(int count); + bool Skip(int count); + int64 ByteCount() const; + + + private: + const uint8* const data_; // The byte array. + const int size_; // Total size of the array. + const int block_size_; // How many bytes to return at a time. + + int position_; + int last_returned_size_; // How many bytes we returned last time Next() + // was called (used for error checking only). + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream); +}; + +// =================================================================== + +// A ZeroCopyOutputStream backed by an in-memory array of bytes. +class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream { + public: + // Create an OutputStream that writes to the bytes pointed to by "data". + // "data" remains the property of the caller but must remain valid until + // the stream is destroyed. If a block_size is given, calls to Next() + // will return data blocks no larger than the given size. Otherwise, the + // first call to Next() returns the entire array. block_size is mainly + // useful for testing; in production you would probably never want to set + // it. + ArrayOutputStream(void* data, int size, int block_size = -1); + ~ArrayOutputStream(); + + // implements ZeroCopyOutputStream --------------------------------- + bool Next(void** data, int* size); + void BackUp(int count); + int64 ByteCount() const; + + private: + uint8* const data_; // The byte array. + const int size_; // Total size of the array. + const int block_size_; // How many bytes to return at a time. + + int position_; + int last_returned_size_; // How many bytes we returned last time Next() + // was called (used for error checking only). + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream); +}; + +// =================================================================== + +// A ZeroCopyOutputStream which appends bytes to a string. +class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream { + public: + // Create a StringOutputStream which appends bytes to the given string. + // The string remains property of the caller, but it MUST NOT be accessed + // in any way until the stream is destroyed. + // + // Hint: If you call target->reserve(n) before creating the stream, + // the first call to Next() will return at least n bytes of buffer + // space. + explicit StringOutputStream(string* target); + ~StringOutputStream(); + + // implements ZeroCopyOutputStream --------------------------------- + bool Next(void** data, int* size); + void BackUp(int count); + int64 ByteCount() const; + + private: + static const int kMinimumSize = 16; + + string* target_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream); +}; + +// Note: There is no StringInputStream. Instead, just create an +// ArrayInputStream as follows: +// ArrayInputStream input(str.data(), str.size()); + +// =================================================================== + +// A generic traditional input stream interface. +// +// Lots of traditional input streams (e.g. file descriptors, C stdio +// streams, and C++ iostreams) expose an interface where every read +// involves copying bytes into a buffer. If you want to take such an +// interface and make a ZeroCopyInputStream based on it, simply implement +// CopyingInputStream and then use CopyingInputStreamAdaptor. +// +// CopyingInputStream implementations should avoid buffering if possible. +// CopyingInputStreamAdaptor does its own buffering and will read data +// in large blocks. +class LIBPROTOBUF_EXPORT CopyingInputStream { + public: + virtual ~CopyingInputStream(); + + // Reads up to "size" bytes into the given buffer. Returns the number of + // bytes read. Read() waits until at least one byte is available, or + // returns zero if no bytes will ever become available (EOF), or -1 if a + // permanent read error occurred. + virtual int Read(void* buffer, int size) = 0; + + // Skips the next "count" bytes of input. Returns the number of bytes + // actually skipped. This will always be exactly equal to "count" unless + // EOF was reached or a permanent read error occurred. + // + // The default implementation just repeatedly calls Read() into a scratch + // buffer. + virtual int Skip(int count); +}; + +// A ZeroCopyInputStream which reads from a CopyingInputStream. This is +// useful for implementing ZeroCopyInputStreams that read from traditional +// streams. Note that this class is not really zero-copy. +// +// If you want to read from file descriptors or C++ istreams, this is +// already implemented for you: use FileInputStream or IstreamInputStream +// respectively. +class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream { + public: + // Creates a stream that reads from the given CopyingInputStream. + // If a block_size is given, it specifies the number of bytes that + // should be read and returned with each call to Next(). Otherwise, + // a reasonable default is used. The caller retains ownership of + // copying_stream unless SetOwnsCopyingStream(true) is called. + explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream, + int block_size = -1); + ~CopyingInputStreamAdaptor(); + + // Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to + // delete the underlying CopyingInputStream when it is destroyed. + void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; } + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size); + void BackUp(int count); + bool Skip(int count); + int64 ByteCount() const; + + private: + // Insures that buffer_ is not NULL. + void AllocateBufferIfNeeded(); + // Frees the buffer and resets buffer_used_. + void FreeBuffer(); + + // The underlying copying stream. + CopyingInputStream* copying_stream_; + bool owns_copying_stream_; + + // True if we have seen a permenant error from the underlying stream. + bool failed_; + + // The current position of copying_stream_, relative to the point where + // we started reading. + int64 position_; + + // Data is read into this buffer. It may be NULL if no buffer is currently + // in use. Otherwise, it points to an array of size buffer_size_. + scoped_array buffer_; + const int buffer_size_; + + // Number of valid bytes currently in the buffer (i.e. the size last + // returned by Next()). 0 <= buffer_used_ <= buffer_size_. + int buffer_used_; + + // Number of bytes in the buffer which were backed up over by a call to + // BackUp(). These need to be returned again. + // 0 <= backup_bytes_ <= buffer_used_ + int backup_bytes_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor); +}; + +// =================================================================== + +// A generic traditional output stream interface. +// +// Lots of traditional output streams (e.g. file descriptors, C stdio +// streams, and C++ iostreams) expose an interface where every write +// involves copying bytes from a buffer. If you want to take such an +// interface and make a ZeroCopyOutputStream based on it, simply implement +// CopyingOutputStream and then use CopyingOutputStreamAdaptor. +// +// CopyingOutputStream implementations should avoid buffering if possible. +// CopyingOutputStreamAdaptor does its own buffering and will write data +// in large blocks. +class LIBPROTOBUF_EXPORT CopyingOutputStream { + public: + virtual ~CopyingOutputStream(); + + // Writes "size" bytes from the given buffer to the output. Returns true + // if successful, false on a write error. + virtual bool Write(const void* buffer, int size) = 0; +}; + +// A ZeroCopyOutputStream which writes to a CopyingOutputStream. This is +// useful for implementing ZeroCopyOutputStreams that write to traditional +// streams. Note that this class is not really zero-copy. +// +// If you want to write to file descriptors or C++ ostreams, this is +// already implemented for you: use FileOutputStream or OstreamOutputStream +// respectively. +class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream { + public: + // Creates a stream that writes to the given Unix file descriptor. + // If a block_size is given, it specifies the size of the buffers + // that should be returned by Next(). Otherwise, a reasonable default + // is used. + explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream, + int block_size = -1); + ~CopyingOutputStreamAdaptor(); + + // Writes all pending data to the underlying stream. Returns false if a + // write error occurred on the underlying stream. (The underlying + // stream itself is not necessarily flushed.) + bool Flush(); + + // Call SetOwnsCopyingStream(true) to tell the CopyingOutputStreamAdaptor to + // delete the underlying CopyingOutputStream when it is destroyed. + void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; } + + // implements ZeroCopyOutputStream --------------------------------- + bool Next(void** data, int* size); + void BackUp(int count); + int64 ByteCount() const; + + private: + // Write the current buffer, if it is present. + bool WriteBuffer(); + // Insures that buffer_ is not NULL. + void AllocateBufferIfNeeded(); + // Frees the buffer. + void FreeBuffer(); + + // The underlying copying stream. + CopyingOutputStream* copying_stream_; + bool owns_copying_stream_; + + // True if we have seen a permenant error from the underlying stream. + bool failed_; + + // The current position of copying_stream_, relative to the point where + // we started writing. + int64 position_; + + // Data is written from this buffer. It may be NULL if no buffer is + // currently in use. Otherwise, it points to an array of size buffer_size_. + scoped_array buffer_; + const int buffer_size_; + + // Number of valid bytes currently in the buffer (i.e. the size last + // returned by Next()). When BackUp() is called, we just reduce this. + // 0 <= buffer_used_ <= buffer_size_. + int buffer_used_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor); +}; + +// =================================================================== + +} // namespace io +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc index 9adef74d..5e3310ac 100644 --- a/src/google/protobuf/io/zero_copy_stream_unittest.cc +++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc @@ -61,6 +61,7 @@ #include #include + #if HAVE_ZLIB #include #endif diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc new file mode 100644 index 00000000..83932859 --- /dev/null +++ b/src/google/protobuf/lite_unittest.cc @@ -0,0 +1,112 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) + +#include +#include + +#include +#include + +using namespace std; + +int main(int argc, char* argv[]) { + string data, packed_data; + + { + protobuf_unittest::TestAllTypesLite message, message2, message3; + google::protobuf::TestUtilLite::ExpectClear(message); + google::protobuf::TestUtilLite::SetAllFields(&message); + message2.CopyFrom(message); + data = message.SerializeAsString(); + message3.ParseFromString(data); + google::protobuf::TestUtilLite::ExpectAllFieldsSet(message); + google::protobuf::TestUtilLite::ExpectAllFieldsSet(message2); + google::protobuf::TestUtilLite::ExpectAllFieldsSet(message3); + google::protobuf::TestUtilLite::ModifyRepeatedFields(&message); + google::protobuf::TestUtilLite::ExpectRepeatedFieldsModified(message); + message.Clear(); + google::protobuf::TestUtilLite::ExpectClear(message); + } + + { + protobuf_unittest::TestAllExtensionsLite message, message2, message3; + google::protobuf::TestUtilLite::ExpectExtensionsClear(message); + google::protobuf::TestUtilLite::SetAllExtensions(&message); + message2.CopyFrom(message); + string extensions_data = message.SerializeAsString(); + GOOGLE_CHECK(extensions_data == data); + message3.ParseFromString(extensions_data); + google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message); + google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message2); + google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message3); + google::protobuf::TestUtilLite::ModifyRepeatedExtensions(&message); + google::protobuf::TestUtilLite::ExpectRepeatedExtensionsModified(message); + message.Clear(); + google::protobuf::TestUtilLite::ExpectExtensionsClear(message); + } + + { + protobuf_unittest::TestPackedTypesLite message, message2, message3; + google::protobuf::TestUtilLite::ExpectPackedClear(message); + google::protobuf::TestUtilLite::SetPackedFields(&message); + message2.CopyFrom(message); + packed_data = message.SerializeAsString(); + message3.ParseFromString(packed_data); + google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message); + google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message2); + google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message3); + google::protobuf::TestUtilLite::ModifyPackedFields(&message); + google::protobuf::TestUtilLite::ExpectPackedFieldsModified(message); + message.Clear(); + google::protobuf::TestUtilLite::ExpectPackedClear(message); + } + + { + protobuf_unittest::TestPackedExtensionsLite message, message2, message3; + google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message); + google::protobuf::TestUtilLite::SetPackedExtensions(&message); + message2.CopyFrom(message); + string packed_extensions_data = message.SerializeAsString(); + GOOGLE_CHECK(packed_extensions_data == packed_data); + message3.ParseFromString(packed_extensions_data); + google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message); + google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message2); + google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message3); + google::protobuf::TestUtilLite::ModifyPackedExtensions(&message); + google::protobuf::TestUtilLite::ExpectPackedExtensionsModified(message); + message.Clear(); + google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message); + } + + cout << "PASS"; + return 0; +} diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index 9df3d394..f4519cd2 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -45,7 +45,6 @@ #include #include #include -#include #include #include @@ -55,15 +54,6 @@ namespace protobuf { using internal::WireFormat; using internal::ReflectionOps; -static string InitializationErrorMessage(const char* action, - const Message& message) { - return strings::Substitute( - "Can't $0 message of type \"$1\" because it is missing required " - "fields: $2", - action, message.GetDescriptor()->full_name(), - message.InitializationErrorString()); -} - Message::~Message() {} void Message::MergeFrom(const Message& from) { @@ -75,6 +65,10 @@ void Message::MergeFrom(const Message& from) { ReflectionOps::Merge(from, this); } +void Message::CheckTypeAndMergeFrom(const MessageLite& other) { + MergeFrom(*down_cast(&other)); +} + void Message::CopyFrom(const Message& from) { const Descriptor* descriptor = GetDescriptor(); GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor) @@ -84,6 +78,10 @@ void Message::CopyFrom(const Message& from) { ReflectionOps::Copy(from, this); } +string Message::GetTypeName() const { + return GetDescriptor()->full_name(); +} + void Message::Clear() { ReflectionOps::Clear(this); } @@ -116,74 +114,6 @@ bool Message::MergePartialFromCodedStream(io::CodedInputStream* input) { return WireFormat::ParseAndMergePartial(input, this); } -bool Message::MergeFromCodedStream(io::CodedInputStream* input) { - if (!MergePartialFromCodedStream(input)) return false; - if (!IsInitialized()) { - GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *this); - return false; - } - return true; -} - -bool Message::ParseFromCodedStream(io::CodedInputStream* input) { - Clear(); - return MergeFromCodedStream(input); -} - -bool Message::ParsePartialFromCodedStream(io::CodedInputStream* input) { - Clear(); - return MergePartialFromCodedStream(input); -} - -bool Message::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) { - io::CodedInputStream decoder(input); - return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage(); -} - -bool Message::ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input) { - io::CodedInputStream decoder(input); - return ParsePartialFromCodedStream(&decoder) && - decoder.ConsumedEntireMessage(); -} - -bool Message::ParseFromBoundedZeroCopyStream( - io::ZeroCopyInputStream* input, int size) { - io::CodedInputStream decoder(input); - decoder.PushLimit(size); - return ParseFromCodedStream(&decoder) && - decoder.ConsumedEntireMessage() && - decoder.BytesUntilLimit() == 0; -} - -bool Message::ParsePartialFromBoundedZeroCopyStream( - io::ZeroCopyInputStream* input, int size) { - io::CodedInputStream decoder(input); - decoder.PushLimit(size); - return ParsePartialFromCodedStream(&decoder) && - decoder.ConsumedEntireMessage() && - decoder.BytesUntilLimit() == 0; -} - -bool Message::ParseFromString(const string& data) { - io::ArrayInputStream input(data.data(), data.size()); - return ParseFromBoundedZeroCopyStream(&input, data.size()); -} - -bool Message::ParsePartialFromString(const string& data) { - io::ArrayInputStream input(data.data(), data.size()); - return ParsePartialFromBoundedZeroCopyStream(&input, data.size()); -} - -bool Message::ParseFromArray(const void* data, int size) { - io::ArrayInputStream input(data, size); - return ParseFromBoundedZeroCopyStream(&input, size); -} - -bool Message::ParsePartialFromArray(const void* data, int size) { - io::ArrayInputStream input(data, size); - return ParsePartialFromBoundedZeroCopyStream(&input, size); -} - bool Message::ParseFromFileDescriptor(int file_descriptor) { io::FileInputStream input(file_descriptor); return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0; @@ -205,22 +135,11 @@ bool Message::ParsePartialFromIstream(istream* input) { } - void Message::SerializeWithCachedSizes( io::CodedOutputStream* output) const { WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output); } -uint8* Message::SerializeWithCachedSizesToArray(uint8* target) const { - // We only optimize this when using optimize_for = SPEED. - int size = GetCachedSize(); - io::ArrayOutputStream out(target, size); - io::CodedOutputStream coded_out(&out); - SerializeWithCachedSizes(&coded_out); - GOOGLE_CHECK(!coded_out.HadError()); - return target + size; -} - int Message::ByteSize() const { int size = WireFormat::ByteSize(*this); SetCachedSize(size); @@ -237,69 +156,6 @@ int Message::SpaceUsed() const { return GetReflection()->SpaceUsed(*this); } -bool Message::SerializeToCodedStream(io::CodedOutputStream* output) const { - GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); - return SerializePartialToCodedStream(output); -} - -bool Message::SerializePartialToCodedStream( - io::CodedOutputStream* output) const { - ByteSize(); // Force size to be cached. - SerializeWithCachedSizes(output); - return !output->HadError(); -} - -bool Message::SerializeToZeroCopyStream( - io::ZeroCopyOutputStream* output) const { - io::CodedOutputStream encoder(output); - return SerializeToCodedStream(&encoder); -} - -bool Message::SerializePartialToZeroCopyStream( - io::ZeroCopyOutputStream* output) const { - io::CodedOutputStream encoder(output); - return SerializePartialToCodedStream(&encoder); -} - -bool Message::AppendToString(string* output) const { - GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); - return AppendPartialToString(output); -} - -bool Message::AppendPartialToString(string* output) const { - int old_size = output->size(); - int byte_size = ByteSize(); - STLStringResizeUninitialized(output, old_size + byte_size); - uint8* start = reinterpret_cast(string_as_array(output) + old_size); - uint8* end = SerializeWithCachedSizesToArray(start); - GOOGLE_CHECK_EQ(end, start + byte_size); - return true; -} - -bool Message::SerializeToString(string* output) const { - output->clear(); - return AppendToString(output); -} - -bool Message::SerializePartialToString(string* output) const { - output->clear(); - return AppendPartialToString(output); -} - -bool Message::SerializeToArray(void* data, int size) const { - GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); - return SerializePartialToArray(data, size); -} - -bool Message::SerializePartialToArray(void* data, int size) const { - int byte_size = ByteSize(); - if (size < byte_size) return false; - uint8* end = - SerializeWithCachedSizesToArray(reinterpret_cast(data)); - GOOGLE_CHECK_EQ(end, reinterpret_cast(data) + byte_size); - return true; -} - bool Message::SerializeToFileDescriptor(int file_descriptor) const { io::FileOutputStream output(file_descriptor); return SerializeToZeroCopyStream(&output); @@ -321,24 +177,6 @@ bool Message::SerializePartialToOstream(ostream* output) const { } -string Message::SerializeAsString() const { - // If the compiler implements the (Named) Return Value Optimization, - // the local variable 'result' will not actually reside on the stack - // of this function, but will be overlaid with the object that the - // caller supplied for the return value to be constructed in. - string output; - if (!AppendToString(&output)) - output.clear(); - return output; -} - -string Message::SerializePartialAsString() const { - string output; - if (!AppendPartialToString(&output)) - output.clear(); - return output; -} - Reflection::~Reflection() {} // =================================================================== @@ -355,7 +193,7 @@ class GeneratedMessageFactory : public MessageFactory { static GeneratedMessageFactory* singleton(); - typedef void RegistrationFunc(); + typedef void RegistrationFunc(const string&); void RegisterFile(const char* file, RegistrationFunc* registration_func); void RegisterType(const Descriptor* descriptor, const Message* prototype); @@ -378,8 +216,8 @@ GeneratedMessageFactory::~GeneratedMessageFactory() {} GeneratedMessageFactory* GeneratedMessageFactory::singleton() { // No need for thread-safety here because this will be called at static // initialization time. (And GCC4 makes this thread-safe anyway.) - static GeneratedMessageFactory singleton; - return &singleton; + static GeneratedMessageFactory* singleton = new GeneratedMessageFactory; + return singleton; } void GeneratedMessageFactory::RegisterFile( @@ -430,7 +268,7 @@ const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) { const Message* result = FindPtrOrNull(type_map_, type); if (result == NULL) { // Nope. OK, register everything. - registration_func(); + registration_func(type->file()->name()); // Should be here now. result = FindPtrOrNull(type_map_, type); } @@ -450,7 +288,7 @@ MessageFactory* MessageFactory::generated_factory() { } void MessageFactory::InternalRegisterGeneratedFile( - const char* filename, void (*register_messages)()) { + const char* filename, void (*register_messages)(const string&)) { GeneratedMessageFactory::singleton()->RegisterFile(filename, register_messages); } diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index 41716057..eecd91a7 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -98,9 +98,9 @@ // const Reflection* reflection = foo->GetReflection(); // assert(reflection->GetString(foo, text_field) == "Hello World!"); // assert(reflection->FieldSize(foo, numbers_field) == 3); -// assert(reflection->GetInt32(foo, numbers_field, 0) == 1); -// assert(reflection->GetInt32(foo, numbers_field, 1) == 5); -// assert(reflection->GetInt32(foo, numbers_field, 2) == 42); +// assert(reflection->GetRepeatedInt32(foo, numbers_field, 0) == 1); +// assert(reflection->GetRepeatedInt32(foo, numbers_field, 1) == 5); +// assert(reflection->GetRepeatedInt32(foo, numbers_field, 2) == 42); // // delete foo; // } @@ -118,6 +118,10 @@ #include #endif +#include + +#include + #if defined(_WIN32) && defined(GetMessage) // windows.h defines GetMessage() as a macro. Let's re-define it as an inline // function. This is necessary because Reflection has a method called @@ -136,10 +140,8 @@ inline BOOL GetMessage( } #endif -#include namespace google { - namespace protobuf { // Defined in this file. @@ -149,6 +151,7 @@ class Reflection; // Defined in other files. class Descriptor; // descriptor.h class FieldDescriptor; // descriptor.h +class EnumDescriptor; // descriptor.h class EnumValueDescriptor; // descriptor.h namespace io { class ZeroCopyInputStream; // zero_copy_stream.h @@ -158,14 +161,28 @@ namespace io { } class UnknownFieldSet; // unknown_field_set.h +// A container to hold message metadata. +struct Metadata { + const Descriptor* descriptor; + const Reflection* reflection; +}; + +// Returns the EnumDescriptor for enum type E, which must be a +// proto-declared enum type. +template +const EnumDescriptor* GetEnumDescriptor(); + // Abstract interface for protocol messages. // +// See also MessageLite, which contains most every-day operations. Message +// adds descriptors and reflection on top of that. +// // The methods of this class that are virtual but not pure-virtual have // default implementations based on reflection. Message classes which are // optimized for speed will want to override these with faster implementations, // but classes optimized for code size may be happy with keeping them. See // the optimize_for option in descriptor.proto. -class LIBPROTOBUF_EXPORT Message { +class LIBPROTOBUF_EXPORT Message : public MessageLite { public: inline Message() {} virtual ~Message(); @@ -173,7 +190,8 @@ class LIBPROTOBUF_EXPORT Message { // Basic Operations ------------------------------------------------ // Construct a new instance of the same type. Ownership is passed to the - // caller. + // caller. (This is also defined in MessageLite, but is defined again here + // for return-type covariance.) virtual Message* New() const = 0; // Make this message into a copy of the given message. The given message @@ -187,16 +205,6 @@ class LIBPROTOBUF_EXPORT Message { // must be of the same type as this message (i.e. the exact same class). virtual void MergeFrom(const Message& from); - // Clear all fields of the message and set them to their default values. - // Clear() avoids freeing memory, assuming that any memory allocated - // to hold parts of the message will be needed again to hold the next - // message. If you actually want to free the memory used by a Message, - // you must delete it. - virtual void Clear(); - - // Quickly check if all required fields have values set. - virtual bool IsInitialized() const; - // Verifies that IsInitialized() returns true. GOOGLE_CHECK-fails otherwise, with // a nice error message. void CheckInitialized() const; @@ -238,41 +246,9 @@ class LIBPROTOBUF_EXPORT Message { // Convenience function useful in GDB. Prints DebugString() to stdout. void PrintDebugString() const; - // Parsing --------------------------------------------------------- - // Methods for parsing in protocol buffer format. Most of these are - // just simple wrappers around MergeFromCodedStream(). - - // Fill the message with a protocol buffer parsed from the given input - // stream. Returns false on a read error or if the input is in the - // wrong format. - bool ParseFromCodedStream(io::CodedInputStream* input); - // Like ParseFromCodedStream(), but accepts messages that are missing - // required fields. - bool ParsePartialFromCodedStream(io::CodedInputStream* input); - // Read a protocol buffer from the given zero-copy input stream. If - // successful, the entire input will be consumed. - bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input); - // Like ParseFromZeroCopyStream(), but accepts messages that are missing - // required fields. - bool ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input); - // Read a protocol buffer from the given zero-copy input stream, expecting - // the message to be exactly "size" bytes long. If successful, exactly - // this many bytes will have been consumed from the input. - bool ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size); - // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are - // missing required fields. - bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, - int size); - // Parse a protocol buffer contained in a string. - bool ParseFromString(const string& data); - // Like ParseFromString(), but accepts messages that are missing - // required fields. - bool ParsePartialFromString(const string& data); - // Parse a protocol buffer contained in an array of bytes. - bool ParseFromArray(const void* data, int size); - // Like ParseFromArray(), but accepts messages that are missing - // required fields. - bool ParsePartialFromArray(const void* data, int size); + // Heavy I/O ------------------------------------------------------- + // Additional parsing and serialization methods not implemented by + // MessageLite because they are not supported by the lite library. // Parse a protocol buffer from a file descriptor. If successful, the entire // input will be consumed. @@ -287,53 +263,6 @@ class LIBPROTOBUF_EXPORT Message { // required fields. bool ParsePartialFromIstream(istream* input); - - // Reads a protocol buffer from the stream and merges it into this - // Message. Singular fields read from the input overwrite what is - // already in the Message and repeated fields are appended to those - // already present. - // - // It is the responsibility of the caller to call input->LastTagWas() - // (for groups) or input->ConsumedEntireMessage() (for non-groups) after - // this returns to verify that the message's end was delimited correctly. - // - // ParsefromCodedStream() is implemented as Clear() followed by - // MergeFromCodedStream(). - bool MergeFromCodedStream(io::CodedInputStream* input); - - // Like MergeFromCodedStream(), but succeeds even if required fields are - // missing in the input. - // - // MergeFromCodedStream() is just implemented as MergePartialFromCodedStream() - // followed by IsInitialized(). - virtual bool MergePartialFromCodedStream(io::CodedInputStream* input); - - // Serialization --------------------------------------------------- - // Methods for serializing in protocol buffer format. Most of these - // are just simple wrappers around ByteSize() and SerializeWithCachedSizes(). - - // Write a protocol buffer of this message to the given output. Returns - // false on a write error. If the message is missing required fields, - // this may GOOGLE_CHECK-fail. - bool SerializeToCodedStream(io::CodedOutputStream* output) const; - // Like SerializeToCodedStream(), but allows missing required fields. - bool SerializePartialToCodedStream(io::CodedOutputStream* output) const; - // Write the message to the given zero-copy output stream. All required - // fields must be set. - bool SerializeToZeroCopyStream(io::ZeroCopyOutputStream* output) const; - // Like SerializeToZeroCopyStream(), but allows missing required fields. - bool SerializePartialToZeroCopyStream(io::ZeroCopyOutputStream* output) const; - // Serialize the message and store it in the given string. All required - // fields must be set. - bool SerializeToString(string* output) const; - // Like SerializeToString(), but allows missing required fields. - bool SerializePartialToString(string* output) const; - // Serialize the message and store it in the given byte array. All required - // fields must be set. - bool SerializeToArray(void* data, int size) const; - // Like SerializeToArray(), but allows missing required fields. - bool SerializePartialToArray(void* data, int size) const; - // Serialize the message and write it to the given file descriptor. All // required fields must be set. bool SerializeToFileDescriptor(int file_descriptor) const; @@ -346,50 +275,18 @@ class LIBPROTOBUF_EXPORT Message { bool SerializePartialToOstream(ostream* output) const; - // Make a string encoding the message. Is equivalent to calling - // SerializeToString() on a string and using that. Returns the empty - // string if SerializeToString() would have returned an error. - // Note: If you intend to generate many such strings, you may - // reduce heap fragmentation by instead re-using the same string - // object with calls to SerializeToString(). - string SerializeAsString() const; - // Like SerializeAsString(), but allows missing required fields. - string SerializePartialAsString() const; - - // Like SerializeToString(), but appends to the data to the string's existing - // contents. All required fields must be set. - bool AppendToString(string* output) const; - // Like AppendToString(), but allows missing required fields. - bool AppendPartialToString(string* output) const; - - // Computes the serialized size of the message. This recursively calls - // ByteSize() on all embedded messages. If a subclass does not override - // this, it MUST override SetCachedSize(). - virtual int ByteSize() const; + // Reflection-based methods ---------------------------------------- + // These methods are pure-virtual in MessageLite, but Message provides + // reflection-based default implementations. - // Serializes the message without recomputing the size. The message must - // not have changed since the last call to ByteSize(); if it has, the results - // are undefined. + virtual string GetTypeName() const; + virtual void Clear(); + virtual bool IsInitialized() const; + virtual void CheckTypeAndMergeFrom(const MessageLite& other); + virtual bool MergePartialFromCodedStream(io::CodedInputStream* input); + virtual int ByteSize() const; virtual void SerializeWithCachedSizes(io::CodedOutputStream* output) const; - // Like SerializeWithCachedSizes, but writes directly to *target, returning - // a pointer to the byte immediately after the last byte written. "target" - // must point at a byte array of at least ByteSize() bytes. - virtual uint8* SerializeWithCachedSizesToArray(uint8* target) const; - - // Returns the result of the last call to ByteSize(). An embedded message's - // size is needed both to serialize it (because embedded messages are - // length-delimited) and to compute the outer message's size. Caching - // the size avoids computing it multiple times. - // - // ByteSize() does not automatically use the cached size when available - // because this would require invalidating it every time the message was - // modified, which would be too hard and expensive. (E.g. if a deeply-nested - // sub-message is changed, all of its parents' cached sizes would need to be - // invalidated, which is too much work for an otherwise inlined setter - // method.) - virtual int GetCachedSize() const = 0; - private: // This is called only by the default implementation of ByteSize(), to // update the cached size. If you override ByteSize(), you do not need @@ -409,13 +306,24 @@ class LIBPROTOBUF_EXPORT Message { // Get a Descriptor for this message's type. This describes what // fields the message contains, the types of those fields, etc. - virtual const Descriptor* GetDescriptor() const = 0; + const Descriptor* GetDescriptor() const { return GetMetadata().descriptor; } // Get the Reflection interface for this Message, which can be used to // read and modify the fields of the Message dynamically (in other words, // without knowing the message type at compile time). This object remains // property of the Message. - virtual const Reflection* GetReflection() const = 0; + // + // This method remains virtual in case a subclass does not implement + // reflection and wants to override the default behavior. + virtual const Reflection* GetReflection() const { + return GetMetadata().reflection; + } + + protected: + // Get a struct containing the metadata for the Message. Most subclasses only + // need to implement this method, rather than the GetDescriptor() and + // GetReflection() wrappers. + virtual Metadata GetMetadata() const = 0; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message); @@ -758,12 +666,13 @@ class LIBPROTOBUF_EXPORT MessageFactory { // For internal use only: Registers a .proto file at static initialization // time, to be placed in generated_factory. The first time GetPrototype() // is called with a descriptor from this file, |register_messages| will be - // called. It must call InternalRegisterGeneratedMessage() (below) to - // register each message type in the file. This strange mechanism is - // necessary because descriptors are built lazily, so we can't register - // types by their descriptor until we know that the descriptor exists. - static void InternalRegisterGeneratedFile(const char* filename, - void (*register_messages)()); + // called, with the file name as the parameter. It must call + // InternalRegisterGeneratedMessage() (below) to register each message type + // in the file. This strange mechanism is necessary because descriptors are + // built lazily, so we can't register types by their descriptor until we + // know that the descriptor exists. |filename| must be a permanent string. + static void InternalRegisterGeneratedFile( + const char* filename, void (*register_messages)(const string&)); // For internal use only: Registers a message type. Called only by the // functions which are registered with InternalRegisterGeneratedFile(), diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc new file mode 100644 index 00000000..5e156f25 --- /dev/null +++ b/src/google/protobuf/message_lite.cc @@ -0,0 +1,282 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Authors: wink@google.com (Wink Saville), +// kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + + +#include + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +MessageLite::~MessageLite() {} + +string MessageLite::InitializationErrorString() const { + return "(cannot determine missing fields for lite message)"; +} + +namespace { + +string InitializationErrorMessage(const char* action, + const MessageLite& message) { + return strings::Substitute( + "Can't $0 message of type \"$1\" because it is missing required " + "fields: $2", + action, message.GetTypeName(), + message.InitializationErrorString()); +} + +// Several of the Parse methods below just do one thing and then call another +// method. In a naive implementation, we might have ParseFromString() call +// ParseFromArray() which would call ParseFromZeroCopyStream() which would call +// ParseFromCodedStream() which would call MergeFromCodedStream() which would +// call MergePartialFromCodedStream(). However, when parsing very small +// messages, every function call introduces significant overhead. To avoid +// this without reproducing code, we use these forced-inline helpers. +// +// Note: GCC only allows GOOGLE_ATTRIBUTE_ALWAYS_INLINE on declarations, not +// definitions. +inline bool InlineMergeFromCodedStream(io::CodedInputStream* input, + MessageLite* message) + GOOGLE_ATTRIBUTE_ALWAYS_INLINE; +inline bool InlineParseFromCodedStream(io::CodedInputStream* input, + MessageLite* message) + GOOGLE_ATTRIBUTE_ALWAYS_INLINE; +inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input, + MessageLite* message) + GOOGLE_ATTRIBUTE_ALWAYS_INLINE; +inline bool InlineParseFromArray(const void* data, int size, + MessageLite* message) + GOOGLE_ATTRIBUTE_ALWAYS_INLINE; +inline bool InlineParsePartialFromArray(const void* data, int size, + MessageLite* message) + GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + +bool InlineMergeFromCodedStream(io::CodedInputStream* input, + MessageLite* message) { + if (!message->MergePartialFromCodedStream(input)) return false; + if (!message->IsInitialized()) { + GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message); + return false; + } + return true; +} + +bool InlineParseFromCodedStream(io::CodedInputStream* input, + MessageLite* message) { + message->Clear(); + return InlineMergeFromCodedStream(input, message); +} + +bool InlineParsePartialFromCodedStream(io::CodedInputStream* input, + MessageLite* message) { + message->Clear(); + return message->MergePartialFromCodedStream(input); +} + +bool InlineParseFromArray(const void* data, int size, MessageLite* message) { + io::CodedInputStream input(reinterpret_cast(data), size); + return InlineParseFromCodedStream(&input, message) && + input.ConsumedEntireMessage(); +} + +bool InlineParsePartialFromArray(const void* data, int size, + MessageLite* message) { + io::CodedInputStream input(reinterpret_cast(data), size); + return InlineParsePartialFromCodedStream(&input, message) && + input.ConsumedEntireMessage(); +} + +} // namespace + +bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) { + return InlineMergeFromCodedStream(input, this); +} + +bool MessageLite::ParseFromCodedStream(io::CodedInputStream* input) { + return InlineParseFromCodedStream(input, this); +} + +bool MessageLite::ParsePartialFromCodedStream(io::CodedInputStream* input) { + return InlineParsePartialFromCodedStream(input, this); +} + +bool MessageLite::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) { + io::CodedInputStream decoder(input); + return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage(); +} + +bool MessageLite::ParsePartialFromZeroCopyStream( + io::ZeroCopyInputStream* input) { + io::CodedInputStream decoder(input); + return ParsePartialFromCodedStream(&decoder) && + decoder.ConsumedEntireMessage(); +} + +bool MessageLite::ParseFromBoundedZeroCopyStream( + io::ZeroCopyInputStream* input, int size) { + io::CodedInputStream decoder(input); + decoder.PushLimit(size); + return ParseFromCodedStream(&decoder) && + decoder.ConsumedEntireMessage() && + decoder.BytesUntilLimit() == 0; +} + +bool MessageLite::ParsePartialFromBoundedZeroCopyStream( + io::ZeroCopyInputStream* input, int size) { + io::CodedInputStream decoder(input); + decoder.PushLimit(size); + return ParsePartialFromCodedStream(&decoder) && + decoder.ConsumedEntireMessage() && + decoder.BytesUntilLimit() == 0; +} + +bool MessageLite::ParseFromString(const string& data) { + return InlineParseFromArray(data.data(), data.size(), this); +} + +bool MessageLite::ParsePartialFromString(const string& data) { + return InlineParsePartialFromArray(data.data(), data.size(), this); +} + +bool MessageLite::ParseFromArray(const void* data, int size) { + return InlineParseFromArray(data, size, this); +} + +bool MessageLite::ParsePartialFromArray(const void* data, int size) { + return InlineParsePartialFromArray(data, size, this); +} + + +// =================================================================== + +uint8* MessageLite::SerializeWithCachedSizesToArray(uint8* target) const { + // We only optimize this when using optimize_for = SPEED. In other cases + // we just use the CodedOutputStream path. + int size = GetCachedSize(); + io::ArrayOutputStream out(target, size); + io::CodedOutputStream coded_out(&out); + SerializeWithCachedSizes(&coded_out); + GOOGLE_CHECK(!coded_out.HadError()); + return target + size; +} + +bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const { + GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); + return SerializePartialToCodedStream(output); +} + +bool MessageLite::SerializePartialToCodedStream( + io::CodedOutputStream* output) const { + ByteSize(); // Force size to be cached. + SerializeWithCachedSizes(output); + return !output->HadError(); +} + +bool MessageLite::SerializeToZeroCopyStream( + io::ZeroCopyOutputStream* output) const { + io::CodedOutputStream encoder(output); + return SerializeToCodedStream(&encoder); +} + +bool MessageLite::SerializePartialToZeroCopyStream( + io::ZeroCopyOutputStream* output) const { + io::CodedOutputStream encoder(output); + return SerializePartialToCodedStream(&encoder); +} + +bool MessageLite::AppendToString(string* output) const { + GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); + return AppendPartialToString(output); +} + +bool MessageLite::AppendPartialToString(string* output) const { + int old_size = output->size(); + int byte_size = ByteSize(); + STLStringResizeUninitialized(output, old_size + byte_size); + uint8* start = reinterpret_cast(string_as_array(output) + old_size); + uint8* end = SerializeWithCachedSizesToArray(start); + GOOGLE_CHECK_EQ(end - start, byte_size); + return true; +} + +bool MessageLite::SerializeToString(string* output) const { + output->clear(); + return AppendToString(output); +} + +bool MessageLite::SerializePartialToString(string* output) const { + output->clear(); + return AppendPartialToString(output); +} + +bool MessageLite::SerializeToArray(void* data, int size) const { + GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); + return SerializePartialToArray(data, size); +} + +bool MessageLite::SerializePartialToArray(void* data, int size) const { + int byte_size = ByteSize(); + if (size < byte_size) return false; + uint8* end = + SerializeWithCachedSizesToArray(reinterpret_cast(data)); + GOOGLE_CHECK_EQ(end, reinterpret_cast(data) + byte_size); + return true; +} + +string MessageLite::SerializeAsString() const { + // If the compiler implements the (Named) Return Value Optimization, + // the local variable 'result' will not actually reside on the stack + // of this function, but will be overlaid with the object that the + // caller supplied for the return value to be constructed in. + string output; + if (!AppendToString(&output)) + output.clear(); + return output; +} + +string MessageLite::SerializePartialAsString() const { + string output; + if (!AppendPartialToString(&output)) + output.clear(); + return output; +} + +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h new file mode 100644 index 00000000..d289d8c7 --- /dev/null +++ b/src/google/protobuf/message_lite.h @@ -0,0 +1,237 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Authors: wink@google.com (Wink Saville), +// kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// + +#ifndef GOOGLE_PROTOBUF_MESSAGE_LITE_H__ +#define GOOGLE_PROTOBUF_MESSAGE_LITE_H__ + +#include +#include + +namespace google { +namespace protobuf { + +// Interface to light weight protocol messages. +// +// This interface is implemented by all protocol message objects. Most +// users will be more interested in the Message interface, which is a +// subclass of MessageLite. Use MessageLite instead when you only need +// the subset of features which it supports -- namely, nothing that uses +// descriptors or reflection. You can instruct the protocol compiler +// to generate classes which implement only MessageLite, not the full +// Message interface, by adding the following line to the .proto file: +// +// option optimize_for = LITE_RUNTIME; +// +// This is particularly useful on resource-constrained systems where +// the full protocol buffers runtime library is too big. +// +// Note that on non-constrained systems (e.g. servers) when you need +// to link in lots of protocol definitions, a better way to reduce +// total code footprint is to use optimize_for = CODE_SIZE. This +// will make the generated code smaller while still supporting all the +// same features (at the expense of speed). optimize_for = LITE_RUNTIME +// is best when you only have a small number of message types linked +// into your binary, in which case the size of the protocol buffers +// runtime itself is the biggest problem. +class LIBPROTOBUF_EXPORT MessageLite { + public: + inline MessageLite() {} + virtual ~MessageLite(); + + // Basic Operations ------------------------------------------------ + + // Get the name of this message type, e.g. "foo.bar.BazProto". + virtual string GetTypeName() const = 0; + + // Construct a new instance of the same type. Ownership is passed to the + // caller. + virtual MessageLite* New() const = 0; + + // Clear all fields of the message and set them to their default values. + // Clear() avoids freeing memory, assuming that any memory allocated + // to hold parts of the message will be needed again to hold the next + // message. If you actually want to free the memory used by a Message, + // you must delete it. + virtual void Clear() = 0; + + // Quickly check if all required fields have values set. + virtual bool IsInitialized() const = 0; + + // This is not implemented for Lite messages -- it just returns "(cannot + // determine missing fields for lite message)". However, it is implemented + // for full messages. See message.h. + virtual string InitializationErrorString() const; + + // If |other| is the exact same class as this, calls MergeFrom(). Otherwise, + // results are undefined (probably crash). + virtual void CheckTypeAndMergeFrom(const MessageLite& other) = 0; + + // Parsing --------------------------------------------------------- + // Methods for parsing in protocol buffer format. Most of these are + // just simple wrappers around MergeFromCodedStream(). + + // Fill the message with a protocol buffer parsed from the given input + // stream. Returns false on a read error or if the input is in the + // wrong format. + bool ParseFromCodedStream(io::CodedInputStream* input); + // Like ParseFromCodedStream(), but accepts messages that are missing + // required fields. + bool ParsePartialFromCodedStream(io::CodedInputStream* input); + // Read a protocol buffer from the given zero-copy input stream. If + // successful, the entire input will be consumed. + bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input); + // Like ParseFromZeroCopyStream(), but accepts messages that are missing + // required fields. + bool ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input); + // Read a protocol buffer from the given zero-copy input stream, expecting + // the message to be exactly "size" bytes long. If successful, exactly + // this many bytes will have been consumed from the input. + bool ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size); + // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are + // missing required fields. + bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, + int size); + // Parse a protocol buffer contained in a string. + bool ParseFromString(const string& data); + // Like ParseFromString(), but accepts messages that are missing + // required fields. + bool ParsePartialFromString(const string& data); + // Parse a protocol buffer contained in an array of bytes. + bool ParseFromArray(const void* data, int size); + // Like ParseFromArray(), but accepts messages that are missing + // required fields. + bool ParsePartialFromArray(const void* data, int size); + + + // Reads a protocol buffer from the stream and merges it into this + // Message. Singular fields read from the input overwrite what is + // already in the Message and repeated fields are appended to those + // already present. + // + // It is the responsibility of the caller to call input->LastTagWas() + // (for groups) or input->ConsumedEntireMessage() (for non-groups) after + // this returns to verify that the message's end was delimited correctly. + // + // ParsefromCodedStream() is implemented as Clear() followed by + // MergeFromCodedStream(). + bool MergeFromCodedStream(io::CodedInputStream* input); + + // Like MergeFromCodedStream(), but succeeds even if required fields are + // missing in the input. + // + // MergeFromCodedStream() is just implemented as MergePartialFromCodedStream() + // followed by IsInitialized(). + virtual bool MergePartialFromCodedStream(io::CodedInputStream* input) = 0; + + // Serialization --------------------------------------------------- + // Methods for serializing in protocol buffer format. Most of these + // are just simple wrappers around ByteSize() and SerializeWithCachedSizes(). + + // Write a protocol buffer of this message to the given output. Returns + // false on a write error. If the message is missing required fields, + // this may GOOGLE_CHECK-fail. + bool SerializeToCodedStream(io::CodedOutputStream* output) const; + // Like SerializeToCodedStream(), but allows missing required fields. + bool SerializePartialToCodedStream(io::CodedOutputStream* output) const; + // Write the message to the given zero-copy output stream. All required + // fields must be set. + bool SerializeToZeroCopyStream(io::ZeroCopyOutputStream* output) const; + // Like SerializeToZeroCopyStream(), but allows missing required fields. + bool SerializePartialToZeroCopyStream(io::ZeroCopyOutputStream* output) const; + // Serialize the message and store it in the given string. All required + // fields must be set. + bool SerializeToString(string* output) const; + // Like SerializeToString(), but allows missing required fields. + bool SerializePartialToString(string* output) const; + // Serialize the message and store it in the given byte array. All required + // fields must be set. + bool SerializeToArray(void* data, int size) const; + // Like SerializeToArray(), but allows missing required fields. + bool SerializePartialToArray(void* data, int size) const; + + // Make a string encoding the message. Is equivalent to calling + // SerializeToString() on a string and using that. Returns the empty + // string if SerializeToString() would have returned an error. + // Note: If you intend to generate many such strings, you may + // reduce heap fragmentation by instead re-using the same string + // object with calls to SerializeToString(). + string SerializeAsString() const; + // Like SerializeAsString(), but allows missing required fields. + string SerializePartialAsString() const; + + // Like SerializeToString(), but appends to the data to the string's existing + // contents. All required fields must be set. + bool AppendToString(string* output) const; + // Like AppendToString(), but allows missing required fields. + bool AppendPartialToString(string* output) const; + + // Computes the serialized size of the message. This recursively calls + // ByteSize() on all embedded messages. If a subclass does not override + // this, it MUST override SetCachedSize(). + virtual int ByteSize() const = 0; + + // Serializes the message without recomputing the size. The message must + // not have changed since the last call to ByteSize(); if it has, the results + // are undefined. + virtual void SerializeWithCachedSizes( + io::CodedOutputStream* output) const = 0; + + // Like SerializeWithCachedSizes, but writes directly to *target, returning + // a pointer to the byte immediately after the last byte written. "target" + // must point at a byte array of at least ByteSize() bytes. + virtual uint8* SerializeWithCachedSizesToArray(uint8* target) const; + + // Returns the result of the last call to ByteSize(). An embedded message's + // size is needed both to serialize it (because embedded messages are + // length-delimited) and to compute the outer message's size. Caching + // the size avoids computing it multiple times. + // + // ByteSize() does not automatically use the cached size when available + // because this would require invalidating it every time the message was + // modified, which would be too hard and expensive. (E.g. if a deeply-nested + // sub-message is changed, all of its parents' cached sizes would need to be + // invalidated, which is too much work for an otherwise inlined setter + // method.) + virtual int GetCachedSize() const = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageLite); +}; + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_MESSAGE_LITE_H__ diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc index d0592de0..46e68446 100644 --- a/src/google/protobuf/message_unittest.cc +++ b/src/google/protobuf/message_unittest.cc @@ -248,36 +248,6 @@ TEST(MessageTest, ParseFailsOnInvalidMessageEnd) { EXPECT_FALSE(message.ParseFromArray("\014", 1)); } -TEST(MessageTest, FieldConstantValues) { - unittest::TestRequired message; - EXPECT_EQ(protobuf_unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1); - EXPECT_EQ(protobuf_unittest::TestAllTypes::kOptionalInt32FieldNumber, 1); - EXPECT_EQ(protobuf_unittest::TestAllTypes::kOptionalgroupFieldNumber, 16); - EXPECT_EQ(protobuf_unittest::TestAllTypes::kOptionalNestedMessageFieldNumber, - 18); - EXPECT_EQ(protobuf_unittest::TestAllTypes::kOptionalNestedEnumFieldNumber, - 21); - EXPECT_EQ(protobuf_unittest::TestAllTypes::kRepeatedInt32FieldNumber, 31); - EXPECT_EQ(protobuf_unittest::TestAllTypes::kRepeatedgroupFieldNumber, 46); - EXPECT_EQ(protobuf_unittest::TestAllTypes::kRepeatedNestedMessageFieldNumber, - 48); - EXPECT_EQ(protobuf_unittest::TestAllTypes::kRepeatedNestedEnumFieldNumber, - 51); -} - -TEST(MessageTest, ExtensionConstantValues) { - EXPECT_EQ(protobuf_unittest::TestRequired::kSingleFieldNumber, 1000); - EXPECT_EQ(protobuf_unittest::TestRequired::kMultiFieldNumber, 1001); - EXPECT_EQ(protobuf_unittest::kOptionalInt32ExtensionFieldNumber, 1); - EXPECT_EQ(protobuf_unittest::kOptionalgroupExtensionFieldNumber, 16); - EXPECT_EQ(protobuf_unittest::kOptionalNestedMessageExtensionFieldNumber, 18); - EXPECT_EQ(protobuf_unittest::kOptionalNestedEnumExtensionFieldNumber, 21); - EXPECT_EQ(protobuf_unittest::kRepeatedInt32ExtensionFieldNumber, 31); - EXPECT_EQ(protobuf_unittest::kRepeatedgroupExtensionFieldNumber, 46); - EXPECT_EQ(protobuf_unittest::kRepeatedNestedMessageExtensionFieldNumber, 48); - EXPECT_EQ(protobuf_unittest::kRepeatedNestedEnumExtensionFieldNumber, 51); -} - TEST(MessageFactoryTest, GeneratedFactoryLookup) { EXPECT_EQ( MessageFactory::generated_factory()->GetPrototype( diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc index 2d5cb0a4..270ef064 100644 --- a/src/google/protobuf/repeated_field.cc +++ b/src/google/protobuf/repeated_field.cc @@ -33,30 +33,51 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include +#include namespace google { namespace protobuf { - -// HP C++ on Tru64 can't handle the stuff below being defined out-of-line, so -// on that platform everything is defined in repeated_field.h. On other -// platforms, we want these to be out-of-line to avoid code bloat. -#if !defined(__DECCXX) || !defined(__osf__) - namespace internal { -GenericRepeatedField::~GenericRepeatedField() {} +void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) { + void** swap_elements = elements_; + int swap_current_size = current_size_; + int swap_allocated_size = allocated_size_; + int swap_total_size = total_size_; + // We may not be using initial_space_ but it's not worth checking. Just + // copy it anyway. + void* swap_initial_space[kInitialSize]; + memcpy(swap_initial_space, initial_space_, sizeof(initial_space_)); -} // namespace internal + elements_ = other->elements_; + current_size_ = other->current_size_; + allocated_size_ = other->allocated_size_; + total_size_ = other->total_size_; + memcpy(initial_space_, other->initial_space_, sizeof(initial_space_)); -template <> -void RepeatedPtrField::Clear() { - for (int i = 0; i < current_size_; i++) { - elements_[i]->clear(); + other->elements_ = swap_elements; + other->current_size_ = swap_current_size; + other->allocated_size_ = swap_allocated_size; + other->total_size_ = swap_total_size; + memcpy(other->initial_space_, swap_initial_space, sizeof(swap_initial_space)); + + if (elements_ == other->initial_space_) { + elements_ = initial_space_; + } + if (other->elements_ == initial_space_) { + other->elements_ = other->initial_space_; } - current_size_ = 0; } -#endif // !defined(__DECCXX) || !defined(__osf__) +string* StringTypeHandler::New() { + return new string; +} +void StringTypeHandler::Delete(string* value) { + delete value; +} + + +} // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index 4446eaf7..cbe26521 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -49,51 +49,15 @@ #include #include #include -#include +#include namespace google { namespace protobuf { -namespace internal { +class Message; -// DO NOT USE GenericRepeatedField; it should be considered a private detail -// of RepeatedField/RepeatedPtrField that may be removed in the future. -// GeneratedMessageReflection needs to manipulate repeated fields in a -// generic way, so we have them implement this interface. This should ONLY -// be used by GeneratedMessageReflection. This would normally be very bad -// design but GeneratedMessageReflection is a big efficiency hack anyway. -// -// TODO(kenton): Implement something like Jeff's ProtoVoidPtrArray change. -// Then, get rid of GenericRepeatedField. -class LIBPROTOBUF_EXPORT GenericRepeatedField { - public: - inline GenericRepeatedField() {} -#if defined(__DECCXX) && defined(__osf__) - // HP C++ on Tru64 has trouble when this is not defined inline. - virtual ~GenericRepeatedField() {} -#else - virtual ~GenericRepeatedField(); -#endif - - private: - // We only want GeneratedMessageReflection to see and use these, so we - // make them private. Yes, it is valid C++ for a subclass to implement - // a virtual method which is private in the superclass. Crazy, huh? - friend class GeneratedMessageReflection; - - virtual const void* GenericGet(int index) const = 0; - virtual void* GenericMutable(int index) = 0; - virtual void* GenericAdd() = 0; - virtual void GenericClear() = 0; - virtual void GenericRemoveLast() = 0; - virtual void GenericSwap(GenericRepeatedField *other) = 0; - virtual void GenericSwapElements(int index1, int index2) = 0; - virtual int GenericSize() const = 0; - virtual int GenericSpaceUsedExcludingSelf() const = 0; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GenericRepeatedField); -}; +namespace internal { // We need this (from generated_message_reflection.cc). LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str); @@ -105,7 +69,7 @@ LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str); // not ever use a RepeatedField directly; they will use the get-by-index, // set-by-index, and add accessors that are generated for all repeated fields. template -class RepeatedField : public internal::GenericRepeatedField { +class RepeatedField { public: RepeatedField(); ~RepeatedField(); @@ -138,7 +102,7 @@ class RepeatedField : public internal::GenericRepeatedField { // Swap entire contents with "other". void Swap(RepeatedField* other); - // Swap two elements of a repeated field. + // Swap two elements. void SwapElements(int index1, int index2); // STL-like iterator support @@ -154,18 +118,6 @@ class RepeatedField : public internal::GenericRepeatedField { // sizeof(*this) int SpaceUsedExcludingSelf() const; - private: // See GenericRepeatedField for why this is private. - // implements GenericRepeatedField --------------------------------- - const void* GenericGet(int index) const; - void* GenericMutable(int index); - void* GenericAdd(); - void GenericClear(); - void GenericRemoveLast(); - void GenericSwap(GenericRepeatedField *other); - void GenericSwapElements(int index1, int index2); - int GenericSize() const; - int GenericSpaceUsedExcludingSelf() const; - private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedField); @@ -182,25 +134,158 @@ namespace internal { template class RepeatedPtrIterator; } // namespace internal +namespace internal { + +// This is the common base class for RepeatedPtrFields. It deals only in void* +// pointers. Users should not use this interface directly. +// +// The methods of this interface correspond to the methods of RepeatedPtrField, +// but may have a template argument called TypeHandler. Its signature is: +// class TypeHandler { +// public: +// typedef MyType Type; +// static Type* New(); +// static void Delete(Type*); +// static void Clear(Type*); +// static void Merge(const Type& from, Type* to); +// +// // Only needs to be implemented if SpaceUsedExcludingSelf() is called. +// static int SpaceUsed(const Type&); +// }; +class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { + protected: + // The reflection implementation needs to call protected methods directly, + // reinterpreting pointers as being to Message instead of a specific Message + // subclass. + friend class GeneratedMessageReflection; + + // ExtensionSet stores repeated message extensions as + // RepeatedPtrField, but non-lite ExtensionSets need to + // implement SpaceUsed(), and thus need to call SpaceUsedExcludingSelf() + // reinterpreting MessageLite as Message. ExtensionSet also needs to make + // use of AddFromCleared(), which is not part of the public interface. + friend class ExtensionSet; + + RepeatedPtrFieldBase(); + + // Must be called from destructor. + template + void Destroy(); + + int size() const; + + template + const typename TypeHandler::Type& Get(int index) const; + template + typename TypeHandler::Type* Mutable(int index); + template + typename TypeHandler::Type* Add(); + template + void RemoveLast(); + template + void Clear(); + template + void MergeFrom(const RepeatedPtrFieldBase& other); + + void Reserve(int new_size); + + // Used for constructing iterators. + void* const* raw_data() const; + + template + typename TypeHandler::Type** mutable_data(); + template + const typename TypeHandler::Type* const* data() const; + + void Swap(RepeatedPtrFieldBase* other); + + void SwapElements(int index1, int index2); + + template + int SpaceUsedExcludingSelf() const; + + // Advanced memory management -------------------------------------- + + // Like Add(), but if there are no cleared objects to use, returns NULL. + template + typename TypeHandler::Type* AddFromCleared(); + + template + void AddAllocated(typename TypeHandler::Type* value); + template + typename TypeHandler::Type* ReleaseLast(); + + int ClearedCount(); + template + void AddCleared(typename TypeHandler::Type* value); + template + typename TypeHandler::Type* ReleaseCleared(); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase); + + static const int kInitialSize = 4; + + void** elements_; + int current_size_; + int allocated_size_; + int total_size_; + + void* initial_space_[kInitialSize]; + + template + static inline typename TypeHandler::Type* cast(void* element) { + return reinterpret_cast(element); + } + template + static inline const typename TypeHandler::Type* cast(const void* element) { + return reinterpret_cast(element); + } +}; + +template +class GenericTypeHandler { + public: + typedef GenericType Type; + static GenericType* New() { return new GenericType; } + static void Delete(GenericType* value) { delete value; } + static void Clear(GenericType* value) { value->Clear(); } + static void Merge(const GenericType& from, GenericType* to) { + to->MergeFrom(from); + } + static int SpaceUsed(const GenericType& value) { return value.SpaceUsed(); } +}; + +template <> +inline void GenericTypeHandler::Merge( + const MessageLite& from, MessageLite* to) { + to->CheckTypeAndMergeFrom(from); +} + +class LIBPROTOBUF_EXPORT StringTypeHandler { + public: + typedef string Type; + static string* New(); + static void Delete(string* value); + static void Clear(string* value) { value->clear(); } + static void Merge(const string& from, string* to) { *to = from; } + static int SpaceUsed(const string& value) { + return sizeof(value) + StringSpaceUsedExcludingSelf(value); + } +}; + + +} // namespace internal + // RepeatedPtrField is like RepeatedField, but used for repeated strings or // Messages. template -class RepeatedPtrField : public internal::GenericRepeatedField { +class RepeatedPtrField : public internal::RepeatedPtrFieldBase { public: RepeatedPtrField(); - // This constructor is only defined for RepeatedPtrField. - // When a RepeatedPtrField is created using this constructor, - // prototype->New() will be called to allocate new elements, rather than - // just using the "new" operator. This is useful for the implementation - // of DynamicMessage, but is not used by normal generated messages. - explicit RepeatedPtrField(const Message* prototype); - ~RepeatedPtrField(); - // Returns the prototype if one was passed to the constructor. - const Message* prototype() const; - int size() const; const Element& Get(int index) const; @@ -223,12 +308,12 @@ class RepeatedPtrField : public internal::GenericRepeatedField { // Swap entire contents with "other". void Swap(RepeatedPtrField* other); - // Swap two elements of a repeated field. + // Swap two elements. void SwapElements(int index1, int index2); // STL-like iterator support - typedef internal::RepeatedPtrIterator iterator; - typedef internal::RepeatedPtrIterator const_iterator; + typedef internal::RepeatedPtrIterator iterator; + typedef internal::RepeatedPtrIterator const_iterator; iterator begin(); const_iterator begin() const; @@ -239,6 +324,11 @@ class RepeatedPtrField : public internal::GenericRepeatedField { // excluding sizeof(*this). int SpaceUsedExcludingSelf() const; + // The spaced used just by the pointer array, not counting the objects pointed + // at. Returns zero if the array is inlined (i.e. initial_space_ is being + // used). + int SpaceUsedByArray() const; + // Advanced memory management -------------------------------------- // When hardcore memory management becomes necessary -- as it often // does here at Google -- the following methods may be useful. @@ -272,38 +362,16 @@ class RepeatedPtrField : public internal::GenericRepeatedField { // Requires: ClearedCount() > 0 Element* ReleaseCleared(); - private: // See GenericRepeatedField for why this is private. - // implements GenericRepeatedField --------------------------------- - const void* GenericGet(int index) const; - void* GenericMutable(int index); - void* GenericAdd(); - void GenericClear(); - void GenericRemoveLast(); - void GenericSwap(GenericRepeatedField *other); - void GenericSwapElements(int index1, int index2); - int GenericSize() const; - int GenericSpaceUsedExcludingSelf() const; - private: - // Returns (an estimate of) the number of bytes used by an individual - // element. - int ElementSpaceUsed(Element* element) const; + class TypeHandler; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrField); - static const int kInitialSize = 4; - - // prototype_ is used for RepeatedPtrField only (see constructor). - const Message* prototype_; - - Element** elements_; - int current_size_; - int allocated_size_; - int total_size_; - - Element* initial_space_[kInitialSize]; - - Element* NewElement(); + // prototype_ is used for RepeatedPtrField and + // RepeatedPtrField only (see constructor). + // TODO(kenton): Can we use some template magic to avoid wasting space on + // this field when it isn't used? + const Element* prototype_; }; // implementation ==================================================== @@ -412,7 +480,7 @@ void RepeatedField::Swap(RepeatedField* other) { template void RepeatedField::SwapElements(int index1, int index2) { - swap(*Mutable(index1), *Mutable(index2)); + swap(elements_[index1], elements_[index2]); } template @@ -441,53 +509,6 @@ inline int RepeatedField::SpaceUsedExcludingSelf() const { return (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0; } -template -const void* RepeatedField::GenericGet(int index) const { - GOOGLE_DCHECK_LT(index, size()); - return elements_ + index; -} - -template -void* RepeatedField::GenericMutable(int index) { - return Mutable(index); -} - -template -void* RepeatedField::GenericAdd() { - Add(Element()); - return Mutable(current_size_ - 1); -} - -template -void RepeatedField::GenericClear() { - Clear(); -} - -template -void RepeatedField::GenericRemoveLast() { - RemoveLast(); -} - -template -void RepeatedField::GenericSwap(GenericRepeatedField *other) { - Swap(down_cast*>(other)); -} - -template -void RepeatedField::GenericSwapElements(int index1, int index2) { - SwapElements(index1, index2); -} - -template -int RepeatedField::GenericSize() const { - return size(); -} - -template -int RepeatedField::GenericSpaceUsedExcludingSelf() const { - return SpaceUsedExcludingSelf(); -} - template inline void RepeatedField::Reserve(int new_size) { if (total_size_ >= new_size) return; @@ -503,188 +524,123 @@ inline void RepeatedField::Reserve(int new_size) { // ------------------------------------------------------------------- -template -inline RepeatedPtrField::RepeatedPtrField() - : prototype_(NULL), - elements_(initial_space_), - current_size_(0), - allocated_size_(0), - total_size_(kInitialSize) { -} +namespace internal { -template <> -inline RepeatedPtrField::RepeatedPtrField(const Message* prototype) - : prototype_(prototype), - elements_(initial_space_), +inline RepeatedPtrFieldBase::RepeatedPtrFieldBase() + : elements_(initial_space_), current_size_(0), allocated_size_(0), total_size_(kInitialSize) { } -template -RepeatedPtrField::~RepeatedPtrField() { +template +void RepeatedPtrFieldBase::Destroy() { for (int i = 0; i < allocated_size_; i++) { - delete elements_[i]; + TypeHandler::Delete(cast(elements_[i])); } if (elements_ != initial_space_) { delete [] elements_; } } -template <> -inline const Message* RepeatedPtrField::prototype() const { - return prototype_; -} - - -template -inline int RepeatedPtrField::size() const { +inline int RepeatedPtrFieldBase::size() const { return current_size_; } -template -inline const Element& RepeatedPtrField::Get(int index) const { +template +inline const typename TypeHandler::Type& +RepeatedPtrFieldBase::Get(int index) const { GOOGLE_DCHECK_LT(index, size()); - return *elements_[index]; + return *cast(elements_[index]); } -template -inline Element* RepeatedPtrField::Mutable(int index) { +template +inline typename TypeHandler::Type* +RepeatedPtrFieldBase::Mutable(int index) { GOOGLE_DCHECK_LT(index, size()); - return elements_[index]; + return cast(elements_[index]); } -template -inline Element* RepeatedPtrField::Add() { - if (current_size_ < allocated_size_) return elements_[current_size_++]; +template +inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add() { + if (current_size_ < allocated_size_) { + return cast(elements_[current_size_++]); + } if (allocated_size_ == total_size_) Reserve(total_size_ + 1); ++allocated_size_; - return elements_[current_size_++] = NewElement(); -} - -template -inline void RepeatedPtrField::RemoveLast() { - GOOGLE_DCHECK_GT(current_size_, 0); - elements_[--current_size_]->Clear(); + typename TypeHandler::Type* result = TypeHandler::New(); + elements_[current_size_++] = result; + return result; } -template <> -inline void RepeatedPtrField::RemoveLast() { +template +inline void RepeatedPtrFieldBase::RemoveLast() { GOOGLE_DCHECK_GT(current_size_, 0); - elements_[--current_size_]->clear(); + TypeHandler::Clear(cast(elements_[--current_size_])); } -template -void RepeatedPtrField::Clear() { +template +void RepeatedPtrFieldBase::Clear() { for (int i = 0; i < current_size_; i++) { - elements_[i]->Clear(); + TypeHandler::Clear(cast(elements_[i])); } current_size_ = 0; } -#if defined(__DECCXX) && defined(__osf__) -// HP C++ on Tru64 has trouble when this is not defined inline. -template <> -inline void RepeatedPtrField::Clear() { - for (int i = 0; i < current_size_; i++) { - elements_[i]->clear(); - } - current_size_ = 0; -} -#else -// Specialization defined in repeated_field.cc. -template <> -void LIBPROTOBUF_EXPORT RepeatedPtrField::Clear(); -#endif - -template -void RepeatedPtrField::MergeFrom(const RepeatedPtrField& other) { +template +void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) { Reserve(current_size_ + other.current_size_); for (int i = 0; i < other.current_size_; i++) { - Add()->MergeFrom(other.Get(i)); + TypeHandler::Merge(other.Get(i), Add()); } } -template <> -inline void RepeatedPtrField::MergeFrom(const RepeatedPtrField& other) { - Reserve(current_size_ + other.current_size_); - for (int i = 0; i < other.current_size_; i++) { - Add()->assign(other.Get(i)); - } -} - - -template -inline Element** RepeatedPtrField::mutable_data() { +inline void* const* RepeatedPtrFieldBase::raw_data() const { return elements_; } -template -inline const Element* const* RepeatedPtrField::data() const { - return elements_; +template +inline typename TypeHandler::Type** RepeatedPtrFieldBase::mutable_data() { + // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this + // method entirely. + return reinterpret_cast(elements_); } - -template -void RepeatedPtrField::Swap(RepeatedPtrField* other) { - Element** swap_elements = elements_; - int swap_current_size = current_size_; - int swap_allocated_size = allocated_size_; - int swap_total_size = total_size_; - // We may not be using initial_space_ but it's not worth checking. Just - // copy it anyway. - Element* swap_initial_space[kInitialSize]; - memcpy(swap_initial_space, initial_space_, sizeof(initial_space_)); - - elements_ = other->elements_; - current_size_ = other->current_size_; - allocated_size_ = other->allocated_size_; - total_size_ = other->total_size_; - memcpy(initial_space_, other->initial_space_, sizeof(initial_space_)); - - other->elements_ = swap_elements; - other->current_size_ = swap_current_size; - other->allocated_size_ = swap_allocated_size; - other->total_size_ = swap_total_size; - memcpy(other->initial_space_, swap_initial_space, sizeof(swap_initial_space)); - - if (elements_ == other->initial_space_) { - elements_ = initial_space_; - } - if (other->elements_ == initial_space_) { - other->elements_ = other->initial_space_; - } +template +inline const typename TypeHandler::Type* const* +RepeatedPtrFieldBase::data() const { + // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this + // method entirely. + return reinterpret_cast(elements_); } -template -void RepeatedPtrField::SwapElements(int index1, int index2) { +inline void RepeatedPtrFieldBase::SwapElements(int index1, int index2) { swap(elements_[index1], elements_[index2]); } -template -inline int RepeatedPtrField::SpaceUsedExcludingSelf() const { +template +inline int RepeatedPtrFieldBase::SpaceUsedExcludingSelf() const { int allocated_bytes = (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0; for (int i = 0; i < allocated_size_; ++i) { - allocated_bytes += ElementSpaceUsed(elements_[i]); + allocated_bytes += TypeHandler::SpaceUsed(*cast(elements_[i])); } return allocated_bytes; } -template -inline int RepeatedPtrField::ElementSpaceUsed(Element* e) const { - return e->SpaceUsed(); -} - -template <> -inline int RepeatedPtrField::ElementSpaceUsed(string* s) const { - return sizeof(*s) + internal::StringSpaceUsedExcludingSelf(*s); +template +inline typename TypeHandler::Type* RepeatedPtrFieldBase::AddFromCleared() { + if (current_size_ < allocated_size_) { + return cast(elements_[current_size_++]); + } else { + return NULL; + } } - -template -inline void RepeatedPtrField::AddAllocated(Element* value) { +template +inline void RepeatedPtrFieldBase::AddAllocated( + typename TypeHandler::Type* value) { if (allocated_size_ == total_size_) Reserve(total_size_ + 1); // We don't care about the order of cleared elements, so if there's one // in the way, just move it to the back of the array. @@ -695,10 +651,11 @@ inline void RepeatedPtrField::AddAllocated(Element* value) { elements_[current_size_++] = value; } -template -inline Element* RepeatedPtrField::ReleaseLast() { +template +inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseLast() { GOOGLE_DCHECK_GT(current_size_, 0); - Element* result = elements_[--current_size_]; + typename TypeHandler::Type* result = + cast(elements_[--current_size_]); --allocated_size_; if (current_size_ < allocated_size_) { // There are cleared elements on the end; replace the removed element @@ -709,93 +666,148 @@ inline Element* RepeatedPtrField::ReleaseLast() { } -template -inline int RepeatedPtrField::ClearedCount() { +inline int RepeatedPtrFieldBase::ClearedCount() { return allocated_size_ - current_size_; } -template -inline void RepeatedPtrField::AddCleared(Element* value) { +template +inline void RepeatedPtrFieldBase::AddCleared( + typename TypeHandler::Type* value) { if (allocated_size_ == total_size_) Reserve(total_size_ + 1); elements_[allocated_size_++] = value; } -template -inline Element* RepeatedPtrField::ReleaseCleared() { +template +inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseCleared() { GOOGLE_DCHECK_GT(allocated_size_, current_size_); - return elements_[--allocated_size_]; + return cast(elements_[--allocated_size_]); +} + +inline void RepeatedPtrFieldBase::Reserve(int new_size) { + if (total_size_ >= new_size) return; + + void** old_elements = elements_; + total_size_ = max(total_size_ * 2, new_size); + elements_ = new void*[total_size_]; + memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0])); + if (old_elements != initial_space_) { + delete [] old_elements; + } } +} // namespace internal + +// ------------------------------------------------------------------- template -const void* RepeatedPtrField::GenericGet(int index) const { - return &Get(index); +class RepeatedPtrField::TypeHandler + : public internal::GenericTypeHandler {}; + +template <> +class RepeatedPtrField::TypeHandler + : public internal::StringTypeHandler {}; + + +template +inline RepeatedPtrField::RepeatedPtrField() + : prototype_(NULL) { } template -void* RepeatedPtrField::GenericMutable(int index) { - return Mutable(index); +RepeatedPtrField::~RepeatedPtrField() { + Destroy(); } template -void* RepeatedPtrField::GenericAdd() { - return Add(); +inline int RepeatedPtrField::size() const { + return RepeatedPtrFieldBase::size(); } template -void RepeatedPtrField::GenericClear() { - Clear(); +inline const Element& RepeatedPtrField::Get(int index) const { + return RepeatedPtrFieldBase::Get(index); } template -void RepeatedPtrField::GenericRemoveLast() { - RemoveLast(); +inline Element* RepeatedPtrField::Mutable(int index) { + return RepeatedPtrFieldBase::Mutable(index); } template -void RepeatedPtrField::GenericSwap(GenericRepeatedField *other) { - Swap(down_cast*>(other)); +inline Element* RepeatedPtrField::Add() { + return RepeatedPtrFieldBase::Add(); } template -void RepeatedPtrField::GenericSwapElements(int index1, int index2) { - SwapElements(index1, index2); +inline void RepeatedPtrField::RemoveLast() { + RepeatedPtrFieldBase::RemoveLast(); } template -int RepeatedPtrField::GenericSize() const { - return size(); +inline void RepeatedPtrField::Clear() { + RepeatedPtrFieldBase::Clear(); } template -int RepeatedPtrField::GenericSpaceUsedExcludingSelf() const { - return SpaceUsedExcludingSelf(); +inline void RepeatedPtrField::MergeFrom( + const RepeatedPtrField& other) { + RepeatedPtrFieldBase::MergeFrom(other); } +template +inline Element** RepeatedPtrField::mutable_data() { + return RepeatedPtrFieldBase::mutable_data(); +} template -inline void RepeatedPtrField::Reserve(int new_size) { - if (total_size_ >= new_size) return; +inline const Element* const* RepeatedPtrField::data() const { + return RepeatedPtrFieldBase::data(); +} - Element** old_elements = elements_; - total_size_ = max(total_size_ * 2, new_size); - elements_ = new Element*[total_size_]; - memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0])); - if (old_elements != initial_space_) { - delete [] old_elements; - } +template +void RepeatedPtrField::Swap(RepeatedPtrField* other) { + RepeatedPtrFieldBase::Swap(other); } template -inline Element* RepeatedPtrField::NewElement() { - return new Element; +void RepeatedPtrField::SwapElements(int index1, int index2) { + RepeatedPtrFieldBase::SwapElements(index1, index2); } -// RepeatedPtrField is allowed but requires a prototype since Message -// is abstract. -template <> -inline Message* RepeatedPtrField::NewElement() { - return prototype_->New(); +template +inline int RepeatedPtrField::SpaceUsedExcludingSelf() const { + return RepeatedPtrFieldBase::SpaceUsedExcludingSelf(); +} + +template +inline void RepeatedPtrField::AddAllocated(Element* value) { + RepeatedPtrFieldBase::AddAllocated(value); +} + +template +inline Element* RepeatedPtrField::ReleaseLast() { + return RepeatedPtrFieldBase::ReleaseLast(); +} + + +template +inline int RepeatedPtrField::ClearedCount() { + return RepeatedPtrFieldBase::ClearedCount(); +} + +template +inline void RepeatedPtrField::AddCleared(Element* value) { + return RepeatedPtrFieldBase::AddCleared(value); +} + +template +inline Element* RepeatedPtrField::ReleaseCleared() { + return RepeatedPtrFieldBase::ReleaseCleared(); +} + +template +inline void RepeatedPtrField::Reserve(int new_size) { + return RepeatedPtrFieldBase::Reserve(new_size); } // ------------------------------------------------------------------- @@ -805,26 +817,22 @@ namespace internal { // STL-like iterator implementation for RepeatedPtrField. You should not // refer to this class directly; use RepeatedPtrField::iterator instead. // -// The iterator for RepeatedPtrField, RepeatedPtrIterator, is -// very similar to iterator_ptr<> in util/gtl/iterator_adaptors-inl.h, -// but adds random-access operators and is slightly more specialized -// for using T** as its base type. I didn't re-use the other class to -// avoid an extra dependency. +// The iterator for RepeatedPtrField, RepeatedPtrIterator, is +// very similar to iterator_ptr in util/gtl/iterator_adaptors-inl.h, +// but adds random-access operators and is modified to wrap a void** base +// iterator (since RepeatedPtrField stores its array as a void* array and +// casting void** to T** would violate C++ aliasing rules). // -// This code stolen from net/proto/proto-array-internal.h by Jeffrey Yasskin +// This code based on net/proto/proto-array-internal.h by Jeffrey Yasskin // (jyasskin@google.com). -template +template class RepeatedPtrIterator : public std::iterator< - std::random_access_iterator_tag, - typename internal::remove_pointer< - typename internal::remove_pointer::type>::type> { + std::random_access_iterator_tag, Element> { public: - typedef RepeatedPtrIterator iterator; + typedef RepeatedPtrIterator iterator; typedef std::iterator< - std::random_access_iterator_tag, - typename internal::remove_pointer< - typename internal::remove_pointer::type>::type> superclass; + std::random_access_iterator_tag, Element> superclass; // Let the compiler know that these are type names, so we don't have to // write "typename" in front of them everywhere. @@ -833,19 +841,21 @@ class RepeatedPtrIterator typedef typename superclass::difference_type difference_type; RepeatedPtrIterator() : it_(NULL) {} - explicit RepeatedPtrIterator(const It& it) : it_(it) {} + explicit RepeatedPtrIterator(void* const* it) : it_(it) {} // Allow "upcasting" from RepeatedPtrIterator to // RepeatedPtrIterator. - template - RepeatedPtrIterator(const RepeatedPtrIterator& other) - : it_(other.base()) {} - - // Provide access to the wrapped iterator. - const It& base() const { return it_; } + template + RepeatedPtrIterator(const RepeatedPtrIterator& other) + : it_(other.it_) { + // Force a compiler error if the other type is not convertable to ours. + if (false) { + implicit_cast(0); + } + } // dereferenceable - reference operator*() const { return **it_; } + reference operator*() const { return *reinterpret_cast(*it_); } pointer operator->() const { return &(operator*()); } // {inc,dec}rementable @@ -893,8 +903,11 @@ class RepeatedPtrIterator difference_type operator-(const iterator& x) const { return it_ - x.it_; } private: + template + friend class RepeatedPtrIterator; + // The internal iterator. - It it_; + void* const* it_; }; } // namespace internal @@ -902,22 +915,22 @@ class RepeatedPtrIterator template inline typename RepeatedPtrField::iterator RepeatedPtrField::begin() { - return iterator(elements_); + return iterator(raw_data()); } template inline typename RepeatedPtrField::const_iterator RepeatedPtrField::begin() const { - return iterator(elements_); + return iterator(raw_data()); } template inline typename RepeatedPtrField::iterator RepeatedPtrField::end() { - return iterator(elements_ + current_size_); + return iterator(raw_data() + size()); } template inline typename RepeatedPtrField::const_iterator RepeatedPtrField::end() const { - return iterator(elements_ + current_size_); + return iterator(raw_data() + size()); } // Iterators and helper functions that follow the spirit of the STL diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h index ace1077d..069f33e2 100644 --- a/src/google/protobuf/stubs/common.h +++ b/src/google/protobuf/stubs/common.h @@ -181,6 +181,14 @@ static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF); #define GOOGLE_ATTRIBUTE_ALWAYS_INLINE #endif +#undef GOOGLE_ATTRIBUTE_DEPRECATED +#ifdef __GNUC__ +// If the method/variable/type is used anywhere, produce a warning. +#define GOOGLE_ATTRIBUTE_DEPRECATED __attribute__((deprecated)) +#else +#define GOOGLE_ATTRIBUTE_DEPRECATED +#endif + // =================================================================== // from google3/base/basictypes.h @@ -642,24 +650,24 @@ class LIBPROTOBUF_EXPORT LogFinisher { #define GOOGLE_CHECK(EXPRESSION) \ GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": " -#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK(A == B) -#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK(A != B) -#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK(A < B) -#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK(A <= B) -#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK(A > B) -#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK(A >= B) +#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B)) +#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B)) +#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B)) +#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B)) +#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B)) +#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B)) #ifdef NDEBUG #define GOOGLE_DLOG GOOGLE_LOG_IF(false, INFO) #define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION) -#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK(A == B) -#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK(A != B) -#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK(A < B) -#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK(A <= B) -#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK(A > B) -#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK(A >= B) +#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B)) +#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B)) +#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) < (B)) +#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK((A) <= (B)) +#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK((A) > (B)) +#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK((A) >= (B)) #else // NDEBUG diff --git a/src/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc index e3e67f67..0637c0a5 100644 --- a/src/google/protobuf/test_util.cc +++ b/src/google/protobuf/test_util.cc @@ -33,7 +33,7 @@ // Sanjay Ghemawat, Jeff Dean, and others. #ifdef _WIN32 -// Verify that #icnluding windows.h does not break anything (e.g. because +// Verify that #including windows.h does not break anything (e.g. because // windows.h #defines GetMessage() as a macro). #include #endif @@ -86,7 +86,7 @@ void TestUtil::SetAllFields(unittest::TestAllTypes* message) { message, message->GetDescriptor()->FindFieldByName("optional_cord"), "125"); -#endif +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS // ----------------------------------------------------------------- @@ -124,7 +124,7 @@ void TestUtil::SetAllFields(unittest::TestAllTypes* message) { message, message->GetDescriptor()->FindFieldByName("repeated_cord"), "225"); -#endif +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS // Add a second one of each field. message->add_repeated_int32 (301); @@ -161,7 +161,7 @@ void TestUtil::SetAllFields(unittest::TestAllTypes* message) { message, message->GetDescriptor()->FindFieldByName("repeated_cord"), "325"); -#endif +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS // ----------------------------------------------------------------- @@ -194,7 +194,7 @@ void TestUtil::SetAllFields(unittest::TestAllTypes* message) { message, message->GetDescriptor()->FindFieldByName("default_cord"), "425"); -#endif +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS } // ------------------------------------------------------------------- @@ -234,7 +234,7 @@ void TestUtil::ModifyRepeatedFields(unittest::TestAllTypes* message) { message, message->GetDescriptor()->FindFieldByName("repeated_cord"), 1, "425"); -#endif +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS } // ------------------------------------------------------------------- diff --git a/src/google/protobuf/test_util.h b/src/google/protobuf/test_util.h index e581f419..5a6ec88f 100644 --- a/src/google/protobuf/test_util.h +++ b/src/google/protobuf/test_util.h @@ -102,7 +102,8 @@ class TestUtil { static void ExpectLastRepeatedExtensionsRemoved( const unittest::TestAllExtensions& message); - // Check that all repeated fields have had their first and last elements swapped. + // Check that all repeated fields have had their first and last elements + // swapped. static void ExpectRepeatedsSwapped(const unittest::TestAllTypes& message); static void ExpectRepeatedExtensionsSwapped( const unittest::TestAllExtensions& message); diff --git a/src/google/protobuf/test_util_lite.cc b/src/google/protobuf/test_util_lite.cc new file mode 100644 index 00000000..d7140e0c --- /dev/null +++ b/src/google/protobuf/test_util_lite.cc @@ -0,0 +1,1502 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include + + +#define EXPECT_TRUE GOOGLE_CHECK +#define ASSERT_TRUE GOOGLE_CHECK +#define EXPECT_FALSE(COND) GOOGLE_CHECK(!(COND)) +#define EXPECT_EQ GOOGLE_CHECK_EQ +#define ASSERT_EQ GOOGLE_CHECK_EQ + +namespace google { +namespace protobuf { + +void TestUtilLite::SetAllFields(unittest::TestAllTypesLite* message) { + message->set_optional_int32 (101); + message->set_optional_int64 (102); + message->set_optional_uint32 (103); + message->set_optional_uint64 (104); + message->set_optional_sint32 (105); + message->set_optional_sint64 (106); + message->set_optional_fixed32 (107); + message->set_optional_fixed64 (108); + message->set_optional_sfixed32(109); + message->set_optional_sfixed64(110); + message->set_optional_float (111); + message->set_optional_double (112); + message->set_optional_bool (true); + message->set_optional_string ("115"); + message->set_optional_bytes ("116"); + + message->mutable_optionalgroup ()->set_a(117); + message->mutable_optional_nested_message ()->set_bb(118); + message->mutable_optional_foreign_message()->set_c(119); + message->mutable_optional_import_message ()->set_d(120); + + message->set_optional_nested_enum (unittest::TestAllTypesLite::BAZ ); + message->set_optional_foreign_enum(unittest::FOREIGN_LITE_BAZ ); + message->set_optional_import_enum (unittest_import::IMPORT_LITE_BAZ); + + + // ----------------------------------------------------------------- + + message->add_repeated_int32 (201); + message->add_repeated_int64 (202); + message->add_repeated_uint32 (203); + message->add_repeated_uint64 (204); + message->add_repeated_sint32 (205); + message->add_repeated_sint64 (206); + message->add_repeated_fixed32 (207); + message->add_repeated_fixed64 (208); + message->add_repeated_sfixed32(209); + message->add_repeated_sfixed64(210); + message->add_repeated_float (211); + message->add_repeated_double (212); + message->add_repeated_bool (true); + message->add_repeated_string ("215"); + message->add_repeated_bytes ("216"); + + message->add_repeatedgroup ()->set_a(217); + message->add_repeated_nested_message ()->set_bb(218); + message->add_repeated_foreign_message()->set_c(219); + message->add_repeated_import_message ()->set_d(220); + + message->add_repeated_nested_enum (unittest::TestAllTypesLite::BAR ); + message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAR ); + message->add_repeated_import_enum (unittest_import::IMPORT_LITE_BAR); + + + // Add a second one of each field. + message->add_repeated_int32 (301); + message->add_repeated_int64 (302); + message->add_repeated_uint32 (303); + message->add_repeated_uint64 (304); + message->add_repeated_sint32 (305); + message->add_repeated_sint64 (306); + message->add_repeated_fixed32 (307); + message->add_repeated_fixed64 (308); + message->add_repeated_sfixed32(309); + message->add_repeated_sfixed64(310); + message->add_repeated_float (311); + message->add_repeated_double (312); + message->add_repeated_bool (false); + message->add_repeated_string ("315"); + message->add_repeated_bytes ("316"); + + message->add_repeatedgroup ()->set_a(317); + message->add_repeated_nested_message ()->set_bb(318); + message->add_repeated_foreign_message()->set_c(319); + message->add_repeated_import_message ()->set_d(320); + + message->add_repeated_nested_enum (unittest::TestAllTypesLite::BAZ ); + message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAZ ); + message->add_repeated_import_enum (unittest_import::IMPORT_LITE_BAZ); + + + // ----------------------------------------------------------------- + + message->set_default_int32 (401); + message->set_default_int64 (402); + message->set_default_uint32 (403); + message->set_default_uint64 (404); + message->set_default_sint32 (405); + message->set_default_sint64 (406); + message->set_default_fixed32 (407); + message->set_default_fixed64 (408); + message->set_default_sfixed32(409); + message->set_default_sfixed64(410); + message->set_default_float (411); + message->set_default_double (412); + message->set_default_bool (false); + message->set_default_string ("415"); + message->set_default_bytes ("416"); + + message->set_default_nested_enum (unittest::TestAllTypesLite::FOO ); + message->set_default_foreign_enum(unittest::FOREIGN_LITE_FOO ); + message->set_default_import_enum (unittest_import::IMPORT_LITE_FOO); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ModifyRepeatedFields(unittest::TestAllTypesLite* message) { + message->set_repeated_int32 (1, 501); + message->set_repeated_int64 (1, 502); + message->set_repeated_uint32 (1, 503); + message->set_repeated_uint64 (1, 504); + message->set_repeated_sint32 (1, 505); + message->set_repeated_sint64 (1, 506); + message->set_repeated_fixed32 (1, 507); + message->set_repeated_fixed64 (1, 508); + message->set_repeated_sfixed32(1, 509); + message->set_repeated_sfixed64(1, 510); + message->set_repeated_float (1, 511); + message->set_repeated_double (1, 512); + message->set_repeated_bool (1, true); + message->set_repeated_string (1, "515"); + message->set_repeated_bytes (1, "516"); + + message->mutable_repeatedgroup (1)->set_a(517); + message->mutable_repeated_nested_message (1)->set_bb(518); + message->mutable_repeated_foreign_message(1)->set_c(519); + message->mutable_repeated_import_message (1)->set_d(520); + + message->set_repeated_nested_enum (1, unittest::TestAllTypesLite::FOO ); + message->set_repeated_foreign_enum(1, unittest::FOREIGN_LITE_FOO ); + message->set_repeated_import_enum (1, unittest_import::IMPORT_LITE_FOO); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectAllFieldsSet( + const unittest::TestAllTypesLite& message) { + EXPECT_TRUE(message.has_optional_int32 ()); + EXPECT_TRUE(message.has_optional_int64 ()); + EXPECT_TRUE(message.has_optional_uint32 ()); + EXPECT_TRUE(message.has_optional_uint64 ()); + EXPECT_TRUE(message.has_optional_sint32 ()); + EXPECT_TRUE(message.has_optional_sint64 ()); + EXPECT_TRUE(message.has_optional_fixed32 ()); + EXPECT_TRUE(message.has_optional_fixed64 ()); + EXPECT_TRUE(message.has_optional_sfixed32()); + EXPECT_TRUE(message.has_optional_sfixed64()); + EXPECT_TRUE(message.has_optional_float ()); + EXPECT_TRUE(message.has_optional_double ()); + EXPECT_TRUE(message.has_optional_bool ()); + EXPECT_TRUE(message.has_optional_string ()); + EXPECT_TRUE(message.has_optional_bytes ()); + + EXPECT_TRUE(message.has_optionalgroup ()); + EXPECT_TRUE(message.has_optional_nested_message ()); + EXPECT_TRUE(message.has_optional_foreign_message()); + EXPECT_TRUE(message.has_optional_import_message ()); + + EXPECT_TRUE(message.optionalgroup ().has_a()); + EXPECT_TRUE(message.optional_nested_message ().has_bb()); + EXPECT_TRUE(message.optional_foreign_message().has_c()); + EXPECT_TRUE(message.optional_import_message ().has_d()); + + EXPECT_TRUE(message.has_optional_nested_enum ()); + EXPECT_TRUE(message.has_optional_foreign_enum()); + EXPECT_TRUE(message.has_optional_import_enum ()); + + + EXPECT_EQ(101 , message.optional_int32 ()); + EXPECT_EQ(102 , message.optional_int64 ()); + EXPECT_EQ(103 , message.optional_uint32 ()); + EXPECT_EQ(104 , message.optional_uint64 ()); + EXPECT_EQ(105 , message.optional_sint32 ()); + EXPECT_EQ(106 , message.optional_sint64 ()); + EXPECT_EQ(107 , message.optional_fixed32 ()); + EXPECT_EQ(108 , message.optional_fixed64 ()); + EXPECT_EQ(109 , message.optional_sfixed32()); + EXPECT_EQ(110 , message.optional_sfixed64()); + EXPECT_EQ(111 , message.optional_float ()); + EXPECT_EQ(112 , message.optional_double ()); + EXPECT_EQ(true , message.optional_bool ()); + EXPECT_EQ("115", message.optional_string ()); + EXPECT_EQ("116", message.optional_bytes ()); + + EXPECT_EQ(117, message.optionalgroup ().a()); + EXPECT_EQ(118, message.optional_nested_message ().bb()); + EXPECT_EQ(119, message.optional_foreign_message().c()); + EXPECT_EQ(120, message.optional_import_message ().d()); + + EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.optional_nested_enum ()); + EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.optional_foreign_enum()); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.optional_import_enum ()); + + + // ----------------------------------------------------------------- + + ASSERT_EQ(2, message.repeated_int32_size ()); + ASSERT_EQ(2, message.repeated_int64_size ()); + ASSERT_EQ(2, message.repeated_uint32_size ()); + ASSERT_EQ(2, message.repeated_uint64_size ()); + ASSERT_EQ(2, message.repeated_sint32_size ()); + ASSERT_EQ(2, message.repeated_sint64_size ()); + ASSERT_EQ(2, message.repeated_fixed32_size ()); + ASSERT_EQ(2, message.repeated_fixed64_size ()); + ASSERT_EQ(2, message.repeated_sfixed32_size()); + ASSERT_EQ(2, message.repeated_sfixed64_size()); + ASSERT_EQ(2, message.repeated_float_size ()); + ASSERT_EQ(2, message.repeated_double_size ()); + ASSERT_EQ(2, message.repeated_bool_size ()); + ASSERT_EQ(2, message.repeated_string_size ()); + ASSERT_EQ(2, message.repeated_bytes_size ()); + + ASSERT_EQ(2, message.repeatedgroup_size ()); + ASSERT_EQ(2, message.repeated_nested_message_size ()); + ASSERT_EQ(2, message.repeated_foreign_message_size()); + ASSERT_EQ(2, message.repeated_import_message_size ()); + ASSERT_EQ(2, message.repeated_nested_enum_size ()); + ASSERT_EQ(2, message.repeated_foreign_enum_size ()); + ASSERT_EQ(2, message.repeated_import_enum_size ()); + + + EXPECT_EQ(201 , message.repeated_int32 (0)); + EXPECT_EQ(202 , message.repeated_int64 (0)); + EXPECT_EQ(203 , message.repeated_uint32 (0)); + EXPECT_EQ(204 , message.repeated_uint64 (0)); + EXPECT_EQ(205 , message.repeated_sint32 (0)); + EXPECT_EQ(206 , message.repeated_sint64 (0)); + EXPECT_EQ(207 , message.repeated_fixed32 (0)); + EXPECT_EQ(208 , message.repeated_fixed64 (0)); + EXPECT_EQ(209 , message.repeated_sfixed32(0)); + EXPECT_EQ(210 , message.repeated_sfixed64(0)); + EXPECT_EQ(211 , message.repeated_float (0)); + EXPECT_EQ(212 , message.repeated_double (0)); + EXPECT_EQ(true , message.repeated_bool (0)); + EXPECT_EQ("215", message.repeated_string (0)); + EXPECT_EQ("216", message.repeated_bytes (0)); + + EXPECT_EQ(217, message.repeatedgroup (0).a()); + EXPECT_EQ(218, message.repeated_nested_message (0).bb()); + EXPECT_EQ(219, message.repeated_foreign_message(0).c()); + EXPECT_EQ(220, message.repeated_import_message (0).d()); + + + EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.repeated_nested_enum (0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.repeated_foreign_enum(0)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.repeated_import_enum (0)); + + EXPECT_EQ(301 , message.repeated_int32 (1)); + EXPECT_EQ(302 , message.repeated_int64 (1)); + EXPECT_EQ(303 , message.repeated_uint32 (1)); + EXPECT_EQ(304 , message.repeated_uint64 (1)); + EXPECT_EQ(305 , message.repeated_sint32 (1)); + EXPECT_EQ(306 , message.repeated_sint64 (1)); + EXPECT_EQ(307 , message.repeated_fixed32 (1)); + EXPECT_EQ(308 , message.repeated_fixed64 (1)); + EXPECT_EQ(309 , message.repeated_sfixed32(1)); + EXPECT_EQ(310 , message.repeated_sfixed64(1)); + EXPECT_EQ(311 , message.repeated_float (1)); + EXPECT_EQ(312 , message.repeated_double (1)); + EXPECT_EQ(false, message.repeated_bool (1)); + EXPECT_EQ("315", message.repeated_string (1)); + EXPECT_EQ("316", message.repeated_bytes (1)); + + EXPECT_EQ(317, message.repeatedgroup (1).a()); + EXPECT_EQ(318, message.repeated_nested_message (1).bb()); + EXPECT_EQ(319, message.repeated_foreign_message(1).c()); + EXPECT_EQ(320, message.repeated_import_message (1).d()); + + EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.repeated_nested_enum (1)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.repeated_foreign_enum(1)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.repeated_import_enum (1)); + + + // ----------------------------------------------------------------- + + EXPECT_TRUE(message.has_default_int32 ()); + EXPECT_TRUE(message.has_default_int64 ()); + EXPECT_TRUE(message.has_default_uint32 ()); + EXPECT_TRUE(message.has_default_uint64 ()); + EXPECT_TRUE(message.has_default_sint32 ()); + EXPECT_TRUE(message.has_default_sint64 ()); + EXPECT_TRUE(message.has_default_fixed32 ()); + EXPECT_TRUE(message.has_default_fixed64 ()); + EXPECT_TRUE(message.has_default_sfixed32()); + EXPECT_TRUE(message.has_default_sfixed64()); + EXPECT_TRUE(message.has_default_float ()); + EXPECT_TRUE(message.has_default_double ()); + EXPECT_TRUE(message.has_default_bool ()); + EXPECT_TRUE(message.has_default_string ()); + EXPECT_TRUE(message.has_default_bytes ()); + + EXPECT_TRUE(message.has_default_nested_enum ()); + EXPECT_TRUE(message.has_default_foreign_enum()); + EXPECT_TRUE(message.has_default_import_enum ()); + + + EXPECT_EQ(401 , message.default_int32 ()); + EXPECT_EQ(402 , message.default_int64 ()); + EXPECT_EQ(403 , message.default_uint32 ()); + EXPECT_EQ(404 , message.default_uint64 ()); + EXPECT_EQ(405 , message.default_sint32 ()); + EXPECT_EQ(406 , message.default_sint64 ()); + EXPECT_EQ(407 , message.default_fixed32 ()); + EXPECT_EQ(408 , message.default_fixed64 ()); + EXPECT_EQ(409 , message.default_sfixed32()); + EXPECT_EQ(410 , message.default_sfixed64()); + EXPECT_EQ(411 , message.default_float ()); + EXPECT_EQ(412 , message.default_double ()); + EXPECT_EQ(false, message.default_bool ()); + EXPECT_EQ("415", message.default_string ()); + EXPECT_EQ("416", message.default_bytes ()); + + EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.default_nested_enum ()); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.default_foreign_enum()); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.default_import_enum ()); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectClear(const unittest::TestAllTypesLite& message) { + // has_blah() should initially be false for all optional fields. + EXPECT_FALSE(message.has_optional_int32 ()); + EXPECT_FALSE(message.has_optional_int64 ()); + EXPECT_FALSE(message.has_optional_uint32 ()); + EXPECT_FALSE(message.has_optional_uint64 ()); + EXPECT_FALSE(message.has_optional_sint32 ()); + EXPECT_FALSE(message.has_optional_sint64 ()); + EXPECT_FALSE(message.has_optional_fixed32 ()); + EXPECT_FALSE(message.has_optional_fixed64 ()); + EXPECT_FALSE(message.has_optional_sfixed32()); + EXPECT_FALSE(message.has_optional_sfixed64()); + EXPECT_FALSE(message.has_optional_float ()); + EXPECT_FALSE(message.has_optional_double ()); + EXPECT_FALSE(message.has_optional_bool ()); + EXPECT_FALSE(message.has_optional_string ()); + EXPECT_FALSE(message.has_optional_bytes ()); + + EXPECT_FALSE(message.has_optionalgroup ()); + EXPECT_FALSE(message.has_optional_nested_message ()); + EXPECT_FALSE(message.has_optional_foreign_message()); + EXPECT_FALSE(message.has_optional_import_message ()); + + EXPECT_FALSE(message.has_optional_nested_enum ()); + EXPECT_FALSE(message.has_optional_foreign_enum()); + EXPECT_FALSE(message.has_optional_import_enum ()); + + + // Optional fields without defaults are set to zero or something like it. + EXPECT_EQ(0 , message.optional_int32 ()); + EXPECT_EQ(0 , message.optional_int64 ()); + EXPECT_EQ(0 , message.optional_uint32 ()); + EXPECT_EQ(0 , message.optional_uint64 ()); + EXPECT_EQ(0 , message.optional_sint32 ()); + EXPECT_EQ(0 , message.optional_sint64 ()); + EXPECT_EQ(0 , message.optional_fixed32 ()); + EXPECT_EQ(0 , message.optional_fixed64 ()); + EXPECT_EQ(0 , message.optional_sfixed32()); + EXPECT_EQ(0 , message.optional_sfixed64()); + EXPECT_EQ(0 , message.optional_float ()); + EXPECT_EQ(0 , message.optional_double ()); + EXPECT_EQ(false, message.optional_bool ()); + EXPECT_EQ("" , message.optional_string ()); + EXPECT_EQ("" , message.optional_bytes ()); + + // Embedded messages should also be clear. + EXPECT_FALSE(message.optionalgroup ().has_a()); + EXPECT_FALSE(message.optional_nested_message ().has_bb()); + EXPECT_FALSE(message.optional_foreign_message().has_c()); + EXPECT_FALSE(message.optional_import_message ().has_d()); + + EXPECT_EQ(0, message.optionalgroup ().a()); + EXPECT_EQ(0, message.optional_nested_message ().bb()); + EXPECT_EQ(0, message.optional_foreign_message().c()); + EXPECT_EQ(0, message.optional_import_message ().d()); + + // Enums without defaults are set to the first value in the enum. + EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.optional_nested_enum ()); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.optional_foreign_enum()); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.optional_import_enum ()); + + + // Repeated fields are empty. + EXPECT_EQ(0, message.repeated_int32_size ()); + EXPECT_EQ(0, message.repeated_int64_size ()); + EXPECT_EQ(0, message.repeated_uint32_size ()); + EXPECT_EQ(0, message.repeated_uint64_size ()); + EXPECT_EQ(0, message.repeated_sint32_size ()); + EXPECT_EQ(0, message.repeated_sint64_size ()); + EXPECT_EQ(0, message.repeated_fixed32_size ()); + EXPECT_EQ(0, message.repeated_fixed64_size ()); + EXPECT_EQ(0, message.repeated_sfixed32_size()); + EXPECT_EQ(0, message.repeated_sfixed64_size()); + EXPECT_EQ(0, message.repeated_float_size ()); + EXPECT_EQ(0, message.repeated_double_size ()); + EXPECT_EQ(0, message.repeated_bool_size ()); + EXPECT_EQ(0, message.repeated_string_size ()); + EXPECT_EQ(0, message.repeated_bytes_size ()); + + EXPECT_EQ(0, message.repeatedgroup_size ()); + EXPECT_EQ(0, message.repeated_nested_message_size ()); + EXPECT_EQ(0, message.repeated_foreign_message_size()); + EXPECT_EQ(0, message.repeated_import_message_size ()); + EXPECT_EQ(0, message.repeated_nested_enum_size ()); + EXPECT_EQ(0, message.repeated_foreign_enum_size ()); + EXPECT_EQ(0, message.repeated_import_enum_size ()); + + + // has_blah() should also be false for all default fields. + EXPECT_FALSE(message.has_default_int32 ()); + EXPECT_FALSE(message.has_default_int64 ()); + EXPECT_FALSE(message.has_default_uint32 ()); + EXPECT_FALSE(message.has_default_uint64 ()); + EXPECT_FALSE(message.has_default_sint32 ()); + EXPECT_FALSE(message.has_default_sint64 ()); + EXPECT_FALSE(message.has_default_fixed32 ()); + EXPECT_FALSE(message.has_default_fixed64 ()); + EXPECT_FALSE(message.has_default_sfixed32()); + EXPECT_FALSE(message.has_default_sfixed64()); + EXPECT_FALSE(message.has_default_float ()); + EXPECT_FALSE(message.has_default_double ()); + EXPECT_FALSE(message.has_default_bool ()); + EXPECT_FALSE(message.has_default_string ()); + EXPECT_FALSE(message.has_default_bytes ()); + + EXPECT_FALSE(message.has_default_nested_enum ()); + EXPECT_FALSE(message.has_default_foreign_enum()); + EXPECT_FALSE(message.has_default_import_enum ()); + + + // Fields with defaults have their default values (duh). + EXPECT_EQ( 41 , message.default_int32 ()); + EXPECT_EQ( 42 , message.default_int64 ()); + EXPECT_EQ( 43 , message.default_uint32 ()); + EXPECT_EQ( 44 , message.default_uint64 ()); + EXPECT_EQ(-45 , message.default_sint32 ()); + EXPECT_EQ( 46 , message.default_sint64 ()); + EXPECT_EQ( 47 , message.default_fixed32 ()); + EXPECT_EQ( 48 , message.default_fixed64 ()); + EXPECT_EQ( 49 , message.default_sfixed32()); + EXPECT_EQ(-50 , message.default_sfixed64()); + EXPECT_EQ( 51.5 , message.default_float ()); + EXPECT_EQ( 52e3 , message.default_double ()); + EXPECT_EQ(true , message.default_bool ()); + EXPECT_EQ("hello", message.default_string ()); + EXPECT_EQ("world", message.default_bytes ()); + + EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.default_nested_enum ()); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.default_foreign_enum()); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.default_import_enum ()); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectRepeatedFieldsModified( + const unittest::TestAllTypesLite& message) { + // ModifyRepeatedFields only sets the second repeated element of each + // field. In addition to verifying this, we also verify that the first + // element and size were *not* modified. + ASSERT_EQ(2, message.repeated_int32_size ()); + ASSERT_EQ(2, message.repeated_int64_size ()); + ASSERT_EQ(2, message.repeated_uint32_size ()); + ASSERT_EQ(2, message.repeated_uint64_size ()); + ASSERT_EQ(2, message.repeated_sint32_size ()); + ASSERT_EQ(2, message.repeated_sint64_size ()); + ASSERT_EQ(2, message.repeated_fixed32_size ()); + ASSERT_EQ(2, message.repeated_fixed64_size ()); + ASSERT_EQ(2, message.repeated_sfixed32_size()); + ASSERT_EQ(2, message.repeated_sfixed64_size()); + ASSERT_EQ(2, message.repeated_float_size ()); + ASSERT_EQ(2, message.repeated_double_size ()); + ASSERT_EQ(2, message.repeated_bool_size ()); + ASSERT_EQ(2, message.repeated_string_size ()); + ASSERT_EQ(2, message.repeated_bytes_size ()); + + ASSERT_EQ(2, message.repeatedgroup_size ()); + ASSERT_EQ(2, message.repeated_nested_message_size ()); + ASSERT_EQ(2, message.repeated_foreign_message_size()); + ASSERT_EQ(2, message.repeated_import_message_size ()); + ASSERT_EQ(2, message.repeated_nested_enum_size ()); + ASSERT_EQ(2, message.repeated_foreign_enum_size ()); + ASSERT_EQ(2, message.repeated_import_enum_size ()); + + + EXPECT_EQ(201 , message.repeated_int32 (0)); + EXPECT_EQ(202 , message.repeated_int64 (0)); + EXPECT_EQ(203 , message.repeated_uint32 (0)); + EXPECT_EQ(204 , message.repeated_uint64 (0)); + EXPECT_EQ(205 , message.repeated_sint32 (0)); + EXPECT_EQ(206 , message.repeated_sint64 (0)); + EXPECT_EQ(207 , message.repeated_fixed32 (0)); + EXPECT_EQ(208 , message.repeated_fixed64 (0)); + EXPECT_EQ(209 , message.repeated_sfixed32(0)); + EXPECT_EQ(210 , message.repeated_sfixed64(0)); + EXPECT_EQ(211 , message.repeated_float (0)); + EXPECT_EQ(212 , message.repeated_double (0)); + EXPECT_EQ(true , message.repeated_bool (0)); + EXPECT_EQ("215", message.repeated_string (0)); + EXPECT_EQ("216", message.repeated_bytes (0)); + + EXPECT_EQ(217, message.repeatedgroup (0).a()); + EXPECT_EQ(218, message.repeated_nested_message (0).bb()); + EXPECT_EQ(219, message.repeated_foreign_message(0).c()); + EXPECT_EQ(220, message.repeated_import_message (0).d()); + + EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.repeated_nested_enum (0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.repeated_foreign_enum(0)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.repeated_import_enum (0)); + + + // Actually verify the second (modified) elements now. + EXPECT_EQ(501 , message.repeated_int32 (1)); + EXPECT_EQ(502 , message.repeated_int64 (1)); + EXPECT_EQ(503 , message.repeated_uint32 (1)); + EXPECT_EQ(504 , message.repeated_uint64 (1)); + EXPECT_EQ(505 , message.repeated_sint32 (1)); + EXPECT_EQ(506 , message.repeated_sint64 (1)); + EXPECT_EQ(507 , message.repeated_fixed32 (1)); + EXPECT_EQ(508 , message.repeated_fixed64 (1)); + EXPECT_EQ(509 , message.repeated_sfixed32(1)); + EXPECT_EQ(510 , message.repeated_sfixed64(1)); + EXPECT_EQ(511 , message.repeated_float (1)); + EXPECT_EQ(512 , message.repeated_double (1)); + EXPECT_EQ(true , message.repeated_bool (1)); + EXPECT_EQ("515", message.repeated_string (1)); + EXPECT_EQ("516", message.repeated_bytes (1)); + + EXPECT_EQ(517, message.repeatedgroup (1).a()); + EXPECT_EQ(518, message.repeated_nested_message (1).bb()); + EXPECT_EQ(519, message.repeated_foreign_message(1).c()); + EXPECT_EQ(520, message.repeated_import_message (1).d()); + + EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.repeated_nested_enum (1)); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.repeated_foreign_enum(1)); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.repeated_import_enum (1)); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::SetPackedFields(unittest::TestPackedTypesLite* message) { + message->add_packed_int32 (601); + message->add_packed_int64 (602); + message->add_packed_uint32 (603); + message->add_packed_uint64 (604); + message->add_packed_sint32 (605); + message->add_packed_sint64 (606); + message->add_packed_fixed32 (607); + message->add_packed_fixed64 (608); + message->add_packed_sfixed32(609); + message->add_packed_sfixed64(610); + message->add_packed_float (611); + message->add_packed_double (612); + message->add_packed_bool (true); + message->add_packed_enum (unittest::FOREIGN_LITE_BAR); + // add a second one of each field + message->add_packed_int32 (701); + message->add_packed_int64 (702); + message->add_packed_uint32 (703); + message->add_packed_uint64 (704); + message->add_packed_sint32 (705); + message->add_packed_sint64 (706); + message->add_packed_fixed32 (707); + message->add_packed_fixed64 (708); + message->add_packed_sfixed32(709); + message->add_packed_sfixed64(710); + message->add_packed_float (711); + message->add_packed_double (712); + message->add_packed_bool (false); + message->add_packed_enum (unittest::FOREIGN_LITE_BAZ); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ModifyPackedFields(unittest::TestPackedTypesLite* message) { + message->set_packed_int32 (1, 801); + message->set_packed_int64 (1, 802); + message->set_packed_uint32 (1, 803); + message->set_packed_uint64 (1, 804); + message->set_packed_sint32 (1, 805); + message->set_packed_sint64 (1, 806); + message->set_packed_fixed32 (1, 807); + message->set_packed_fixed64 (1, 808); + message->set_packed_sfixed32(1, 809); + message->set_packed_sfixed64(1, 810); + message->set_packed_float (1, 811); + message->set_packed_double (1, 812); + message->set_packed_bool (1, true); + message->set_packed_enum (1, unittest::FOREIGN_LITE_FOO); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectPackedFieldsSet( + const unittest::TestPackedTypesLite& message) { + ASSERT_EQ(2, message.packed_int32_size ()); + ASSERT_EQ(2, message.packed_int64_size ()); + ASSERT_EQ(2, message.packed_uint32_size ()); + ASSERT_EQ(2, message.packed_uint64_size ()); + ASSERT_EQ(2, message.packed_sint32_size ()); + ASSERT_EQ(2, message.packed_sint64_size ()); + ASSERT_EQ(2, message.packed_fixed32_size ()); + ASSERT_EQ(2, message.packed_fixed64_size ()); + ASSERT_EQ(2, message.packed_sfixed32_size()); + ASSERT_EQ(2, message.packed_sfixed64_size()); + ASSERT_EQ(2, message.packed_float_size ()); + ASSERT_EQ(2, message.packed_double_size ()); + ASSERT_EQ(2, message.packed_bool_size ()); + ASSERT_EQ(2, message.packed_enum_size ()); + + EXPECT_EQ(601 , message.packed_int32 (0)); + EXPECT_EQ(602 , message.packed_int64 (0)); + EXPECT_EQ(603 , message.packed_uint32 (0)); + EXPECT_EQ(604 , message.packed_uint64 (0)); + EXPECT_EQ(605 , message.packed_sint32 (0)); + EXPECT_EQ(606 , message.packed_sint64 (0)); + EXPECT_EQ(607 , message.packed_fixed32 (0)); + EXPECT_EQ(608 , message.packed_fixed64 (0)); + EXPECT_EQ(609 , message.packed_sfixed32(0)); + EXPECT_EQ(610 , message.packed_sfixed64(0)); + EXPECT_EQ(611 , message.packed_float (0)); + EXPECT_EQ(612 , message.packed_double (0)); + EXPECT_EQ(true , message.packed_bool (0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR, message.packed_enum(0)); + + EXPECT_EQ(701 , message.packed_int32 (1)); + EXPECT_EQ(702 , message.packed_int64 (1)); + EXPECT_EQ(703 , message.packed_uint32 (1)); + EXPECT_EQ(704 , message.packed_uint64 (1)); + EXPECT_EQ(705 , message.packed_sint32 (1)); + EXPECT_EQ(706 , message.packed_sint64 (1)); + EXPECT_EQ(707 , message.packed_fixed32 (1)); + EXPECT_EQ(708 , message.packed_fixed64 (1)); + EXPECT_EQ(709 , message.packed_sfixed32(1)); + EXPECT_EQ(710 , message.packed_sfixed64(1)); + EXPECT_EQ(711 , message.packed_float (1)); + EXPECT_EQ(712 , message.packed_double (1)); + EXPECT_EQ(false, message.packed_bool (1)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAZ, message.packed_enum(1)); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectPackedClear( + const unittest::TestPackedTypesLite& message) { + // Packed repeated fields are empty. + EXPECT_EQ(0, message.packed_int32_size ()); + EXPECT_EQ(0, message.packed_int64_size ()); + EXPECT_EQ(0, message.packed_uint32_size ()); + EXPECT_EQ(0, message.packed_uint64_size ()); + EXPECT_EQ(0, message.packed_sint32_size ()); + EXPECT_EQ(0, message.packed_sint64_size ()); + EXPECT_EQ(0, message.packed_fixed32_size ()); + EXPECT_EQ(0, message.packed_fixed64_size ()); + EXPECT_EQ(0, message.packed_sfixed32_size()); + EXPECT_EQ(0, message.packed_sfixed64_size()); + EXPECT_EQ(0, message.packed_float_size ()); + EXPECT_EQ(0, message.packed_double_size ()); + EXPECT_EQ(0, message.packed_bool_size ()); + EXPECT_EQ(0, message.packed_enum_size ()); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectPackedFieldsModified( + const unittest::TestPackedTypesLite& message) { + // Do the same for packed repeated fields. + ASSERT_EQ(2, message.packed_int32_size ()); + ASSERT_EQ(2, message.packed_int64_size ()); + ASSERT_EQ(2, message.packed_uint32_size ()); + ASSERT_EQ(2, message.packed_uint64_size ()); + ASSERT_EQ(2, message.packed_sint32_size ()); + ASSERT_EQ(2, message.packed_sint64_size ()); + ASSERT_EQ(2, message.packed_fixed32_size ()); + ASSERT_EQ(2, message.packed_fixed64_size ()); + ASSERT_EQ(2, message.packed_sfixed32_size()); + ASSERT_EQ(2, message.packed_sfixed64_size()); + ASSERT_EQ(2, message.packed_float_size ()); + ASSERT_EQ(2, message.packed_double_size ()); + ASSERT_EQ(2, message.packed_bool_size ()); + ASSERT_EQ(2, message.packed_enum_size ()); + + EXPECT_EQ(601 , message.packed_int32 (0)); + EXPECT_EQ(602 , message.packed_int64 (0)); + EXPECT_EQ(603 , message.packed_uint32 (0)); + EXPECT_EQ(604 , message.packed_uint64 (0)); + EXPECT_EQ(605 , message.packed_sint32 (0)); + EXPECT_EQ(606 , message.packed_sint64 (0)); + EXPECT_EQ(607 , message.packed_fixed32 (0)); + EXPECT_EQ(608 , message.packed_fixed64 (0)); + EXPECT_EQ(609 , message.packed_sfixed32(0)); + EXPECT_EQ(610 , message.packed_sfixed64(0)); + EXPECT_EQ(611 , message.packed_float (0)); + EXPECT_EQ(612 , message.packed_double (0)); + EXPECT_EQ(true , message.packed_bool (0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR, message.packed_enum(0)); + // Actually verify the second (modified) elements now. + EXPECT_EQ(801 , message.packed_int32 (1)); + EXPECT_EQ(802 , message.packed_int64 (1)); + EXPECT_EQ(803 , message.packed_uint32 (1)); + EXPECT_EQ(804 , message.packed_uint64 (1)); + EXPECT_EQ(805 , message.packed_sint32 (1)); + EXPECT_EQ(806 , message.packed_sint64 (1)); + EXPECT_EQ(807 , message.packed_fixed32 (1)); + EXPECT_EQ(808 , message.packed_fixed64 (1)); + EXPECT_EQ(809 , message.packed_sfixed32(1)); + EXPECT_EQ(810 , message.packed_sfixed64(1)); + EXPECT_EQ(811 , message.packed_float (1)); + EXPECT_EQ(812 , message.packed_double (1)); + EXPECT_EQ(true , message.packed_bool (1)); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO, message.packed_enum(1)); +} + +// =================================================================== +// Extensions +// +// All this code is exactly equivalent to the above code except that it's +// manipulating extension fields instead of normal ones. +// +// I gave up on the 80-char limit here. Sorry. + +void TestUtilLite::SetAllExtensions(unittest::TestAllExtensionsLite* message) { + message->SetExtension(unittest::optional_int32_extension_lite , 101); + message->SetExtension(unittest::optional_int64_extension_lite , 102); + message->SetExtension(unittest::optional_uint32_extension_lite , 103); + message->SetExtension(unittest::optional_uint64_extension_lite , 104); + message->SetExtension(unittest::optional_sint32_extension_lite , 105); + message->SetExtension(unittest::optional_sint64_extension_lite , 106); + message->SetExtension(unittest::optional_fixed32_extension_lite , 107); + message->SetExtension(unittest::optional_fixed64_extension_lite , 108); + message->SetExtension(unittest::optional_sfixed32_extension_lite, 109); + message->SetExtension(unittest::optional_sfixed64_extension_lite, 110); + message->SetExtension(unittest::optional_float_extension_lite , 111); + message->SetExtension(unittest::optional_double_extension_lite , 112); + message->SetExtension(unittest::optional_bool_extension_lite , true); + message->SetExtension(unittest::optional_string_extension_lite , "115"); + message->SetExtension(unittest::optional_bytes_extension_lite , "116"); + + message->MutableExtension(unittest::optionalgroup_extension_lite )->set_a(117); + message->MutableExtension(unittest::optional_nested_message_extension_lite )->set_bb(118); + message->MutableExtension(unittest::optional_foreign_message_extension_lite)->set_c(119); + message->MutableExtension(unittest::optional_import_message_extension_lite )->set_d(120); + + message->SetExtension(unittest::optional_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ ); + message->SetExtension(unittest::optional_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ ); + message->SetExtension(unittest::optional_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAZ); + + + // ----------------------------------------------------------------- + + message->AddExtension(unittest::repeated_int32_extension_lite , 201); + message->AddExtension(unittest::repeated_int64_extension_lite , 202); + message->AddExtension(unittest::repeated_uint32_extension_lite , 203); + message->AddExtension(unittest::repeated_uint64_extension_lite , 204); + message->AddExtension(unittest::repeated_sint32_extension_lite , 205); + message->AddExtension(unittest::repeated_sint64_extension_lite , 206); + message->AddExtension(unittest::repeated_fixed32_extension_lite , 207); + message->AddExtension(unittest::repeated_fixed64_extension_lite , 208); + message->AddExtension(unittest::repeated_sfixed32_extension_lite, 209); + message->AddExtension(unittest::repeated_sfixed64_extension_lite, 210); + message->AddExtension(unittest::repeated_float_extension_lite , 211); + message->AddExtension(unittest::repeated_double_extension_lite , 212); + message->AddExtension(unittest::repeated_bool_extension_lite , true); + message->AddExtension(unittest::repeated_string_extension_lite , "215"); + message->AddExtension(unittest::repeated_bytes_extension_lite , "216"); + + message->AddExtension(unittest::repeatedgroup_extension_lite )->set_a(217); + message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(218); + message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(219); + message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(220); + + message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAR ); + message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAR ); + message->AddExtension(unittest::repeated_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAR); + + + // Add a second one of each field. + message->AddExtension(unittest::repeated_int32_extension_lite , 301); + message->AddExtension(unittest::repeated_int64_extension_lite , 302); + message->AddExtension(unittest::repeated_uint32_extension_lite , 303); + message->AddExtension(unittest::repeated_uint64_extension_lite , 304); + message->AddExtension(unittest::repeated_sint32_extension_lite , 305); + message->AddExtension(unittest::repeated_sint64_extension_lite , 306); + message->AddExtension(unittest::repeated_fixed32_extension_lite , 307); + message->AddExtension(unittest::repeated_fixed64_extension_lite , 308); + message->AddExtension(unittest::repeated_sfixed32_extension_lite, 309); + message->AddExtension(unittest::repeated_sfixed64_extension_lite, 310); + message->AddExtension(unittest::repeated_float_extension_lite , 311); + message->AddExtension(unittest::repeated_double_extension_lite , 312); + message->AddExtension(unittest::repeated_bool_extension_lite , false); + message->AddExtension(unittest::repeated_string_extension_lite , "315"); + message->AddExtension(unittest::repeated_bytes_extension_lite , "316"); + + message->AddExtension(unittest::repeatedgroup_extension_lite )->set_a(317); + message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(318); + message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(319); + message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(320); + + message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ ); + message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ ); + message->AddExtension(unittest::repeated_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAZ); + + + // ----------------------------------------------------------------- + + message->SetExtension(unittest::default_int32_extension_lite , 401); + message->SetExtension(unittest::default_int64_extension_lite , 402); + message->SetExtension(unittest::default_uint32_extension_lite , 403); + message->SetExtension(unittest::default_uint64_extension_lite , 404); + message->SetExtension(unittest::default_sint32_extension_lite , 405); + message->SetExtension(unittest::default_sint64_extension_lite , 406); + message->SetExtension(unittest::default_fixed32_extension_lite , 407); + message->SetExtension(unittest::default_fixed64_extension_lite , 408); + message->SetExtension(unittest::default_sfixed32_extension_lite, 409); + message->SetExtension(unittest::default_sfixed64_extension_lite, 410); + message->SetExtension(unittest::default_float_extension_lite , 411); + message->SetExtension(unittest::default_double_extension_lite , 412); + message->SetExtension(unittest::default_bool_extension_lite , false); + message->SetExtension(unittest::default_string_extension_lite , "415"); + message->SetExtension(unittest::default_bytes_extension_lite , "416"); + + message->SetExtension(unittest::default_nested_enum_extension_lite , unittest::TestAllTypesLite::FOO ); + message->SetExtension(unittest::default_foreign_enum_extension_lite, unittest::FOREIGN_LITE_FOO ); + message->SetExtension(unittest::default_import_enum_extension_lite , unittest_import::IMPORT_LITE_FOO); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ModifyRepeatedExtensions( + unittest::TestAllExtensionsLite* message) { + message->SetExtension(unittest::repeated_int32_extension_lite , 1, 501); + message->SetExtension(unittest::repeated_int64_extension_lite , 1, 502); + message->SetExtension(unittest::repeated_uint32_extension_lite , 1, 503); + message->SetExtension(unittest::repeated_uint64_extension_lite , 1, 504); + message->SetExtension(unittest::repeated_sint32_extension_lite , 1, 505); + message->SetExtension(unittest::repeated_sint64_extension_lite , 1, 506); + message->SetExtension(unittest::repeated_fixed32_extension_lite , 1, 507); + message->SetExtension(unittest::repeated_fixed64_extension_lite , 1, 508); + message->SetExtension(unittest::repeated_sfixed32_extension_lite, 1, 509); + message->SetExtension(unittest::repeated_sfixed64_extension_lite, 1, 510); + message->SetExtension(unittest::repeated_float_extension_lite , 1, 511); + message->SetExtension(unittest::repeated_double_extension_lite , 1, 512); + message->SetExtension(unittest::repeated_bool_extension_lite , 1, true); + message->SetExtension(unittest::repeated_string_extension_lite , 1, "515"); + message->SetExtension(unittest::repeated_bytes_extension_lite , 1, "516"); + + message->MutableExtension(unittest::repeatedgroup_extension_lite , 1)->set_a(517); + message->MutableExtension(unittest::repeated_nested_message_extension_lite , 1)->set_bb(518); + message->MutableExtension(unittest::repeated_foreign_message_extension_lite, 1)->set_c(519); + message->MutableExtension(unittest::repeated_import_message_extension_lite , 1)->set_d(520); + + message->SetExtension(unittest::repeated_nested_enum_extension_lite , 1, unittest::TestAllTypesLite::FOO ); + message->SetExtension(unittest::repeated_foreign_enum_extension_lite, 1, unittest::FOREIGN_LITE_FOO ); + message->SetExtension(unittest::repeated_import_enum_extension_lite , 1, unittest_import::IMPORT_LITE_FOO); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectAllExtensionsSet( + const unittest::TestAllExtensionsLite& message) { + EXPECT_TRUE(message.HasExtension(unittest::optional_int32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_int64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_uint32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_uint64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_sint32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_sint64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_fixed32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_fixed64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_sfixed32_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_sfixed64_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_float_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_double_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_bool_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_bytes_extension_lite )); + + EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension_lite )); + + EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension_lite ).has_a()); + EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb()); + EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension_lite).has_c()); + EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d()); + + EXPECT_TRUE(message.HasExtension(unittest::optional_nested_enum_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_enum_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_import_enum_extension_lite )); + + + EXPECT_EQ(101 , message.GetExtension(unittest::optional_int32_extension_lite )); + EXPECT_EQ(102 , message.GetExtension(unittest::optional_int64_extension_lite )); + EXPECT_EQ(103 , message.GetExtension(unittest::optional_uint32_extension_lite )); + EXPECT_EQ(104 , message.GetExtension(unittest::optional_uint64_extension_lite )); + EXPECT_EQ(105 , message.GetExtension(unittest::optional_sint32_extension_lite )); + EXPECT_EQ(106 , message.GetExtension(unittest::optional_sint64_extension_lite )); + EXPECT_EQ(107 , message.GetExtension(unittest::optional_fixed32_extension_lite )); + EXPECT_EQ(108 , message.GetExtension(unittest::optional_fixed64_extension_lite )); + EXPECT_EQ(109 , message.GetExtension(unittest::optional_sfixed32_extension_lite)); + EXPECT_EQ(110 , message.GetExtension(unittest::optional_sfixed64_extension_lite)); + EXPECT_EQ(111 , message.GetExtension(unittest::optional_float_extension_lite )); + EXPECT_EQ(112 , message.GetExtension(unittest::optional_double_extension_lite )); + EXPECT_EQ(true , message.GetExtension(unittest::optional_bool_extension_lite )); + EXPECT_EQ("115", message.GetExtension(unittest::optional_string_extension_lite )); + EXPECT_EQ("116", message.GetExtension(unittest::optional_bytes_extension_lite )); + + EXPECT_EQ(117, message.GetExtension(unittest::optionalgroup_extension_lite ).a()); + EXPECT_EQ(118, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb()); + EXPECT_EQ(119, message.GetExtension(unittest::optional_foreign_message_extension_lite).c()); + EXPECT_EQ(120, message.GetExtension(unittest::optional_import_message_extension_lite ).d()); + + EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::optional_nested_enum_extension_lite )); + EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.GetExtension(unittest::optional_foreign_enum_extension_lite)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.GetExtension(unittest::optional_import_enum_extension_lite )); + + + // ----------------------------------------------------------------- + + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension_lite )); + + ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite )); + + + EXPECT_EQ(201 , message.GetExtension(unittest::repeated_int32_extension_lite , 0)); + EXPECT_EQ(202 , message.GetExtension(unittest::repeated_int64_extension_lite , 0)); + EXPECT_EQ(203 , message.GetExtension(unittest::repeated_uint32_extension_lite , 0)); + EXPECT_EQ(204 , message.GetExtension(unittest::repeated_uint64_extension_lite , 0)); + EXPECT_EQ(205 , message.GetExtension(unittest::repeated_sint32_extension_lite , 0)); + EXPECT_EQ(206 , message.GetExtension(unittest::repeated_sint64_extension_lite , 0)); + EXPECT_EQ(207 , message.GetExtension(unittest::repeated_fixed32_extension_lite , 0)); + EXPECT_EQ(208 , message.GetExtension(unittest::repeated_fixed64_extension_lite , 0)); + EXPECT_EQ(209 , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 0)); + EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 0)); + EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension_lite , 0)); + EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension_lite , 0)); + EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite , 0)); + EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension_lite , 0)); + EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension_lite , 0)); + + EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension_lite , 0).a()); + EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb()); + EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c()); + EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d()); + + EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::repeated_import_enum_extension_lite , 0)); + + + EXPECT_EQ(301 , message.GetExtension(unittest::repeated_int32_extension_lite , 1)); + EXPECT_EQ(302 , message.GetExtension(unittest::repeated_int64_extension_lite , 1)); + EXPECT_EQ(303 , message.GetExtension(unittest::repeated_uint32_extension_lite , 1)); + EXPECT_EQ(304 , message.GetExtension(unittest::repeated_uint64_extension_lite , 1)); + EXPECT_EQ(305 , message.GetExtension(unittest::repeated_sint32_extension_lite , 1)); + EXPECT_EQ(306 , message.GetExtension(unittest::repeated_sint64_extension_lite , 1)); + EXPECT_EQ(307 , message.GetExtension(unittest::repeated_fixed32_extension_lite , 1)); + EXPECT_EQ(308 , message.GetExtension(unittest::repeated_fixed64_extension_lite , 1)); + EXPECT_EQ(309 , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 1)); + EXPECT_EQ(310 , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 1)); + EXPECT_EQ(311 , message.GetExtension(unittest::repeated_float_extension_lite , 1)); + EXPECT_EQ(312 , message.GetExtension(unittest::repeated_double_extension_lite , 1)); + EXPECT_EQ(false, message.GetExtension(unittest::repeated_bool_extension_lite , 1)); + EXPECT_EQ("315", message.GetExtension(unittest::repeated_string_extension_lite , 1)); + EXPECT_EQ("316", message.GetExtension(unittest::repeated_bytes_extension_lite , 1)); + + EXPECT_EQ(317, message.GetExtension(unittest::repeatedgroup_extension_lite , 1).a()); + EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb()); + EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c()); + EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d()); + + EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.GetExtension(unittest::repeated_import_enum_extension_lite , 1)); + + + // ----------------------------------------------------------------- + + EXPECT_TRUE(message.HasExtension(unittest::default_int32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_int64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_uint32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_uint64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_sint32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_sint64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_fixed32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_fixed64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_sfixed32_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_sfixed64_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_float_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_double_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_bool_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_string_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_bytes_extension_lite )); + + EXPECT_TRUE(message.HasExtension(unittest::default_nested_enum_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_foreign_enum_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_import_enum_extension_lite )); + + + EXPECT_EQ(401 , message.GetExtension(unittest::default_int32_extension_lite )); + EXPECT_EQ(402 , message.GetExtension(unittest::default_int64_extension_lite )); + EXPECT_EQ(403 , message.GetExtension(unittest::default_uint32_extension_lite )); + EXPECT_EQ(404 , message.GetExtension(unittest::default_uint64_extension_lite )); + EXPECT_EQ(405 , message.GetExtension(unittest::default_sint32_extension_lite )); + EXPECT_EQ(406 , message.GetExtension(unittest::default_sint64_extension_lite )); + EXPECT_EQ(407 , message.GetExtension(unittest::default_fixed32_extension_lite )); + EXPECT_EQ(408 , message.GetExtension(unittest::default_fixed64_extension_lite )); + EXPECT_EQ(409 , message.GetExtension(unittest::default_sfixed32_extension_lite)); + EXPECT_EQ(410 , message.GetExtension(unittest::default_sfixed64_extension_lite)); + EXPECT_EQ(411 , message.GetExtension(unittest::default_float_extension_lite )); + EXPECT_EQ(412 , message.GetExtension(unittest::default_double_extension_lite )); + EXPECT_EQ(false, message.GetExtension(unittest::default_bool_extension_lite )); + EXPECT_EQ("415", message.GetExtension(unittest::default_string_extension_lite )); + EXPECT_EQ("416", message.GetExtension(unittest::default_bytes_extension_lite )); + + EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::default_nested_enum_extension_lite )); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.GetExtension(unittest::default_foreign_enum_extension_lite)); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::default_import_enum_extension_lite )); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectExtensionsClear( + const unittest::TestAllExtensionsLite& message) { + string serialized; + ASSERT_TRUE(message.SerializeToString(&serialized)); + EXPECT_EQ("", serialized); + EXPECT_EQ(0, message.ByteSize()); + + // has_blah() should initially be false for all optional fields. + EXPECT_FALSE(message.HasExtension(unittest::optional_int32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_int64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_uint32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_uint64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_sint32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_sint64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_fixed32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_fixed64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_sfixed32_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_sfixed64_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_float_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_double_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_bool_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_string_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_bytes_extension_lite )); + + EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension_lite )); + + EXPECT_FALSE(message.HasExtension(unittest::optional_nested_enum_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_enum_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_import_enum_extension_lite )); + + + // Optional fields without defaults are set to zero or something like it. + EXPECT_EQ(0 , message.GetExtension(unittest::optional_int32_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_int64_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_uint32_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_uint64_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_sint32_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_sint64_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_fixed32_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_fixed64_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_sfixed32_extension_lite)); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_sfixed64_extension_lite)); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_float_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_double_extension_lite )); + EXPECT_EQ(false, message.GetExtension(unittest::optional_bool_extension_lite )); + EXPECT_EQ("" , message.GetExtension(unittest::optional_string_extension_lite )); + EXPECT_EQ("" , message.GetExtension(unittest::optional_bytes_extension_lite )); + + // Embedded messages should also be clear. + EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension_lite ).has_a()); + EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb()); + EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension_lite).has_c()); + EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d()); + + EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension_lite ).a()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension_lite).c()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension_lite ).d()); + + // Enums without defaults are set to the first value in the enum. + EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::optional_nested_enum_extension_lite )); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.GetExtension(unittest::optional_foreign_enum_extension_lite)); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::optional_import_enum_extension_lite )); + + + // Repeated fields are empty. + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_fixed32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_fixed64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_float_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_double_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bool_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_string_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bytes_extension_lite )); + + EXPECT_EQ(0, message.ExtensionSize(unittest::repeatedgroup_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_message_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_message_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_enum_extension_lite )); + + + // has_blah() should also be false for all default fields. + EXPECT_FALSE(message.HasExtension(unittest::default_int32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_int64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_uint32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_uint64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_sint32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_sint64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_fixed32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_fixed64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_sfixed32_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_sfixed64_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_float_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_double_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_bool_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_string_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_bytes_extension_lite )); + + EXPECT_FALSE(message.HasExtension(unittest::default_nested_enum_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_foreign_enum_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_import_enum_extension_lite )); + + + // Fields with defaults have their default values (duh). + EXPECT_EQ( 41 , message.GetExtension(unittest::default_int32_extension_lite )); + EXPECT_EQ( 42 , message.GetExtension(unittest::default_int64_extension_lite )); + EXPECT_EQ( 43 , message.GetExtension(unittest::default_uint32_extension_lite )); + EXPECT_EQ( 44 , message.GetExtension(unittest::default_uint64_extension_lite )); + EXPECT_EQ(-45 , message.GetExtension(unittest::default_sint32_extension_lite )); + EXPECT_EQ( 46 , message.GetExtension(unittest::default_sint64_extension_lite )); + EXPECT_EQ( 47 , message.GetExtension(unittest::default_fixed32_extension_lite )); + EXPECT_EQ( 48 , message.GetExtension(unittest::default_fixed64_extension_lite )); + EXPECT_EQ( 49 , message.GetExtension(unittest::default_sfixed32_extension_lite)); + EXPECT_EQ(-50 , message.GetExtension(unittest::default_sfixed64_extension_lite)); + EXPECT_EQ( 51.5 , message.GetExtension(unittest::default_float_extension_lite )); + EXPECT_EQ( 52e3 , message.GetExtension(unittest::default_double_extension_lite )); + EXPECT_EQ(true , message.GetExtension(unittest::default_bool_extension_lite )); + EXPECT_EQ("hello", message.GetExtension(unittest::default_string_extension_lite )); + EXPECT_EQ("world", message.GetExtension(unittest::default_bytes_extension_lite )); + + EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::default_nested_enum_extension_lite )); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::default_foreign_enum_extension_lite)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::default_import_enum_extension_lite )); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectRepeatedExtensionsModified( + const unittest::TestAllExtensionsLite& message) { + // ModifyRepeatedFields only sets the second repeated element of each + // field. In addition to verifying this, we also verify that the first + // element and size were *not* modified. + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension_lite )); + + ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite )); + + + EXPECT_EQ(201 , message.GetExtension(unittest::repeated_int32_extension_lite , 0)); + EXPECT_EQ(202 , message.GetExtension(unittest::repeated_int64_extension_lite , 0)); + EXPECT_EQ(203 , message.GetExtension(unittest::repeated_uint32_extension_lite , 0)); + EXPECT_EQ(204 , message.GetExtension(unittest::repeated_uint64_extension_lite , 0)); + EXPECT_EQ(205 , message.GetExtension(unittest::repeated_sint32_extension_lite , 0)); + EXPECT_EQ(206 , message.GetExtension(unittest::repeated_sint64_extension_lite , 0)); + EXPECT_EQ(207 , message.GetExtension(unittest::repeated_fixed32_extension_lite , 0)); + EXPECT_EQ(208 , message.GetExtension(unittest::repeated_fixed64_extension_lite , 0)); + EXPECT_EQ(209 , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 0)); + EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 0)); + EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension_lite , 0)); + EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension_lite , 0)); + EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite , 0)); + EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension_lite , 0)); + EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension_lite , 0)); + + EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension_lite , 0).a()); + EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb()); + EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c()); + EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d()); + + EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::repeated_import_enum_extension_lite , 0)); + + + // Actually verify the second (modified) elements now. + EXPECT_EQ(501 , message.GetExtension(unittest::repeated_int32_extension_lite , 1)); + EXPECT_EQ(502 , message.GetExtension(unittest::repeated_int64_extension_lite , 1)); + EXPECT_EQ(503 , message.GetExtension(unittest::repeated_uint32_extension_lite , 1)); + EXPECT_EQ(504 , message.GetExtension(unittest::repeated_uint64_extension_lite , 1)); + EXPECT_EQ(505 , message.GetExtension(unittest::repeated_sint32_extension_lite , 1)); + EXPECT_EQ(506 , message.GetExtension(unittest::repeated_sint64_extension_lite , 1)); + EXPECT_EQ(507 , message.GetExtension(unittest::repeated_fixed32_extension_lite , 1)); + EXPECT_EQ(508 , message.GetExtension(unittest::repeated_fixed64_extension_lite , 1)); + EXPECT_EQ(509 , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 1)); + EXPECT_EQ(510 , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 1)); + EXPECT_EQ(511 , message.GetExtension(unittest::repeated_float_extension_lite , 1)); + EXPECT_EQ(512 , message.GetExtension(unittest::repeated_double_extension_lite , 1)); + EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite , 1)); + EXPECT_EQ("515", message.GetExtension(unittest::repeated_string_extension_lite , 1)); + EXPECT_EQ("516", message.GetExtension(unittest::repeated_bytes_extension_lite , 1)); + + EXPECT_EQ(517, message.GetExtension(unittest::repeatedgroup_extension_lite , 1).a()); + EXPECT_EQ(518, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb()); + EXPECT_EQ(519, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c()); + EXPECT_EQ(520, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d()); + + EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1)); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1)); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::repeated_import_enum_extension_lite , 1)); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::SetPackedExtensions( + unittest::TestPackedExtensionsLite* message) { + message->AddExtension(unittest::packed_int32_extension_lite , 601); + message->AddExtension(unittest::packed_int64_extension_lite , 602); + message->AddExtension(unittest::packed_uint32_extension_lite , 603); + message->AddExtension(unittest::packed_uint64_extension_lite , 604); + message->AddExtension(unittest::packed_sint32_extension_lite , 605); + message->AddExtension(unittest::packed_sint64_extension_lite , 606); + message->AddExtension(unittest::packed_fixed32_extension_lite , 607); + message->AddExtension(unittest::packed_fixed64_extension_lite , 608); + message->AddExtension(unittest::packed_sfixed32_extension_lite, 609); + message->AddExtension(unittest::packed_sfixed64_extension_lite, 610); + message->AddExtension(unittest::packed_float_extension_lite , 611); + message->AddExtension(unittest::packed_double_extension_lite , 612); + message->AddExtension(unittest::packed_bool_extension_lite , true); + message->AddExtension(unittest::packed_enum_extension_lite, unittest::FOREIGN_LITE_BAR); + // add a second one of each field + message->AddExtension(unittest::packed_int32_extension_lite , 701); + message->AddExtension(unittest::packed_int64_extension_lite , 702); + message->AddExtension(unittest::packed_uint32_extension_lite , 703); + message->AddExtension(unittest::packed_uint64_extension_lite , 704); + message->AddExtension(unittest::packed_sint32_extension_lite , 705); + message->AddExtension(unittest::packed_sint64_extension_lite , 706); + message->AddExtension(unittest::packed_fixed32_extension_lite , 707); + message->AddExtension(unittest::packed_fixed64_extension_lite , 708); + message->AddExtension(unittest::packed_sfixed32_extension_lite, 709); + message->AddExtension(unittest::packed_sfixed64_extension_lite, 710); + message->AddExtension(unittest::packed_float_extension_lite , 711); + message->AddExtension(unittest::packed_double_extension_lite , 712); + message->AddExtension(unittest::packed_bool_extension_lite , false); + message->AddExtension(unittest::packed_enum_extension_lite, unittest::FOREIGN_LITE_BAZ); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ModifyPackedExtensions( + unittest::TestPackedExtensionsLite* message) { + message->SetExtension(unittest::packed_int32_extension_lite , 1, 801); + message->SetExtension(unittest::packed_int64_extension_lite , 1, 802); + message->SetExtension(unittest::packed_uint32_extension_lite , 1, 803); + message->SetExtension(unittest::packed_uint64_extension_lite , 1, 804); + message->SetExtension(unittest::packed_sint32_extension_lite , 1, 805); + message->SetExtension(unittest::packed_sint64_extension_lite , 1, 806); + message->SetExtension(unittest::packed_fixed32_extension_lite , 1, 807); + message->SetExtension(unittest::packed_fixed64_extension_lite , 1, 808); + message->SetExtension(unittest::packed_sfixed32_extension_lite, 1, 809); + message->SetExtension(unittest::packed_sfixed64_extension_lite, 1, 810); + message->SetExtension(unittest::packed_float_extension_lite , 1, 811); + message->SetExtension(unittest::packed_double_extension_lite , 1, 812); + message->SetExtension(unittest::packed_bool_extension_lite , 1, true); + message->SetExtension(unittest::packed_enum_extension_lite , 1, + unittest::FOREIGN_LITE_FOO); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectPackedExtensionsSet( + const unittest::TestPackedExtensionsLite& message) { + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension_lite )); + + EXPECT_EQ(601 , message.GetExtension(unittest::packed_int32_extension_lite , 0)); + EXPECT_EQ(602 , message.GetExtension(unittest::packed_int64_extension_lite , 0)); + EXPECT_EQ(603 , message.GetExtension(unittest::packed_uint32_extension_lite , 0)); + EXPECT_EQ(604 , message.GetExtension(unittest::packed_uint64_extension_lite , 0)); + EXPECT_EQ(605 , message.GetExtension(unittest::packed_sint32_extension_lite , 0)); + EXPECT_EQ(606 , message.GetExtension(unittest::packed_sint64_extension_lite , 0)); + EXPECT_EQ(607 , message.GetExtension(unittest::packed_fixed32_extension_lite , 0)); + EXPECT_EQ(608 , message.GetExtension(unittest::packed_fixed64_extension_lite , 0)); + EXPECT_EQ(609 , message.GetExtension(unittest::packed_sfixed32_extension_lite, 0)); + EXPECT_EQ(610 , message.GetExtension(unittest::packed_sfixed64_extension_lite, 0)); + EXPECT_EQ(611 , message.GetExtension(unittest::packed_float_extension_lite , 0)); + EXPECT_EQ(612 , message.GetExtension(unittest::packed_double_extension_lite , 0)); + EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite , 0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR, + message.GetExtension(unittest::packed_enum_extension_lite, 0)); + EXPECT_EQ(701 , message.GetExtension(unittest::packed_int32_extension_lite , 1)); + EXPECT_EQ(702 , message.GetExtension(unittest::packed_int64_extension_lite , 1)); + EXPECT_EQ(703 , message.GetExtension(unittest::packed_uint32_extension_lite , 1)); + EXPECT_EQ(704 , message.GetExtension(unittest::packed_uint64_extension_lite , 1)); + EXPECT_EQ(705 , message.GetExtension(unittest::packed_sint32_extension_lite , 1)); + EXPECT_EQ(706 , message.GetExtension(unittest::packed_sint64_extension_lite , 1)); + EXPECT_EQ(707 , message.GetExtension(unittest::packed_fixed32_extension_lite , 1)); + EXPECT_EQ(708 , message.GetExtension(unittest::packed_fixed64_extension_lite , 1)); + EXPECT_EQ(709 , message.GetExtension(unittest::packed_sfixed32_extension_lite, 1)); + EXPECT_EQ(710 , message.GetExtension(unittest::packed_sfixed64_extension_lite, 1)); + EXPECT_EQ(711 , message.GetExtension(unittest::packed_float_extension_lite , 1)); + EXPECT_EQ(712 , message.GetExtension(unittest::packed_double_extension_lite , 1)); + EXPECT_EQ(false, message.GetExtension(unittest::packed_bool_extension_lite , 1)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAZ, + message.GetExtension(unittest::packed_enum_extension_lite, 1)); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectPackedExtensionsClear( + const unittest::TestPackedExtensionsLite& message) { + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed32_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed64_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_float_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_double_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_bool_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_enum_extension_lite )); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectPackedExtensionsModified( + const unittest::TestPackedExtensionsLite& message) { + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension_lite )); + EXPECT_EQ(601 , message.GetExtension(unittest::packed_int32_extension_lite , 0)); + EXPECT_EQ(602 , message.GetExtension(unittest::packed_int64_extension_lite , 0)); + EXPECT_EQ(603 , message.GetExtension(unittest::packed_uint32_extension_lite , 0)); + EXPECT_EQ(604 , message.GetExtension(unittest::packed_uint64_extension_lite , 0)); + EXPECT_EQ(605 , message.GetExtension(unittest::packed_sint32_extension_lite , 0)); + EXPECT_EQ(606 , message.GetExtension(unittest::packed_sint64_extension_lite , 0)); + EXPECT_EQ(607 , message.GetExtension(unittest::packed_fixed32_extension_lite , 0)); + EXPECT_EQ(608 , message.GetExtension(unittest::packed_fixed64_extension_lite , 0)); + EXPECT_EQ(609 , message.GetExtension(unittest::packed_sfixed32_extension_lite, 0)); + EXPECT_EQ(610 , message.GetExtension(unittest::packed_sfixed64_extension_lite, 0)); + EXPECT_EQ(611 , message.GetExtension(unittest::packed_float_extension_lite , 0)); + EXPECT_EQ(612 , message.GetExtension(unittest::packed_double_extension_lite , 0)); + EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite , 0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR, + message.GetExtension(unittest::packed_enum_extension_lite, 0)); + + // Actually verify the second (modified) elements now. + EXPECT_EQ(801 , message.GetExtension(unittest::packed_int32_extension_lite , 1)); + EXPECT_EQ(802 , message.GetExtension(unittest::packed_int64_extension_lite , 1)); + EXPECT_EQ(803 , message.GetExtension(unittest::packed_uint32_extension_lite , 1)); + EXPECT_EQ(804 , message.GetExtension(unittest::packed_uint64_extension_lite , 1)); + EXPECT_EQ(805 , message.GetExtension(unittest::packed_sint32_extension_lite , 1)); + EXPECT_EQ(806 , message.GetExtension(unittest::packed_sint64_extension_lite , 1)); + EXPECT_EQ(807 , message.GetExtension(unittest::packed_fixed32_extension_lite , 1)); + EXPECT_EQ(808 , message.GetExtension(unittest::packed_fixed64_extension_lite , 1)); + EXPECT_EQ(809 , message.GetExtension(unittest::packed_sfixed32_extension_lite, 1)); + EXPECT_EQ(810 , message.GetExtension(unittest::packed_sfixed64_extension_lite, 1)); + EXPECT_EQ(811 , message.GetExtension(unittest::packed_float_extension_lite , 1)); + EXPECT_EQ(812 , message.GetExtension(unittest::packed_double_extension_lite , 1)); + EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite , 1)); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO, + message.GetExtension(unittest::packed_enum_extension_lite, 1)); +} + +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/test_util_lite.h b/src/google/protobuf/test_util_lite.h new file mode 100644 index 00000000..ca35aaa4 --- /dev/null +++ b/src/google/protobuf/test_util_lite.h @@ -0,0 +1,101 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_TEST_UTIL_LITE_H__ +#define GOOGLE_PROTOBUF_TEST_UTIL_LITE_H__ + +#include + +namespace google { +namespace protobuf { + +namespace unittest = protobuf_unittest; +namespace unittest_import = protobuf_unittest_import; + +class TestUtilLite { + public: + // Set every field in the message to a unique value. + static void SetAllFields(unittest::TestAllTypesLite* message); + static void SetAllExtensions(unittest::TestAllExtensionsLite* message); + static void SetPackedFields(unittest::TestPackedTypesLite* message); + static void SetPackedExtensions(unittest::TestPackedExtensionsLite* message); + + // Use the repeated versions of the set_*() accessors to modify all the + // repeated fields of the messsage (which should already have been + // initialized with Set*Fields()). Set*Fields() itself only tests + // the add_*() accessors. + static void ModifyRepeatedFields(unittest::TestAllTypesLite* message); + static void ModifyRepeatedExtensions( + unittest::TestAllExtensionsLite* message); + static void ModifyPackedFields(unittest::TestPackedTypesLite* message); + static void ModifyPackedExtensions( + unittest::TestPackedExtensionsLite* message); + + // Check that all fields have the values that they should have after + // Set*Fields() is called. + static void ExpectAllFieldsSet(const unittest::TestAllTypesLite& message); + static void ExpectAllExtensionsSet( + const unittest::TestAllExtensionsLite& message); + static void ExpectPackedFieldsSet( + const unittest::TestPackedTypesLite& message); + static void ExpectPackedExtensionsSet( + const unittest::TestPackedExtensionsLite& message); + + // Expect that the message is modified as would be expected from + // Modify*Fields(). + static void ExpectRepeatedFieldsModified( + const unittest::TestAllTypesLite& message); + static void ExpectRepeatedExtensionsModified( + const unittest::TestAllExtensionsLite& message); + static void ExpectPackedFieldsModified( + const unittest::TestPackedTypesLite& message); + static void ExpectPackedExtensionsModified( + const unittest::TestPackedExtensionsLite& message); + + // Check that all fields have their default values. + static void ExpectClear(const unittest::TestAllTypesLite& message); + static void ExpectExtensionsClear( + const unittest::TestAllExtensionsLite& message); + static void ExpectPackedClear(const unittest::TestPackedTypesLite& message); + static void ExpectPackedExtensionsClear( + const unittest::TestPackedExtensionsLite& message); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TestUtilLite); +}; + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_TEST_UTIL_LITE_H__ diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index ae88cdff..cf754024 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -142,6 +142,16 @@ class TextFormat::Parser::ParserImpl { } } + bool ParseField(const FieldDescriptor* field, Message* output) { + bool suc; + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + suc = ConsumeFieldMessage(output, output->GetReflection(), field); + } else { + suc = ConsumeFieldValue(output, output->GetReflection(), field); + } + return suc && LookingAtType(io::Tokenizer::TYPE_END); + } + void ReportError(int line, int col, const string& message) { had_errors_ = true; if (error_collector_ == NULL) { @@ -252,24 +262,9 @@ class TextFormat::Parser::ParserImpl { // Perform special handling for embedded message types. if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - string delimeter; - // ':' is optional here. TryConsume(":"); - - if (TryConsume("<")) { - delimeter = ">"; - } else { - DO(Consume("{")); - delimeter = "}"; - } - - if (field->is_repeated()) { - DO(ConsumeMessage(reflection->AddMessage(message, field), delimeter)); - } else { - DO(ConsumeMessage(reflection->MutableMessage(message, field), - delimeter)); - } + DO(ConsumeFieldMessage(message, reflection, field)); } else { DO(Consume(":")); DO(ConsumeFieldValue(message, reflection, field)); @@ -278,6 +273,26 @@ class TextFormat::Parser::ParserImpl { return true; } + bool ConsumeFieldMessage(Message* message, + const Reflection* reflection, + const FieldDescriptor* field) { + string delimeter; + if (TryConsume("<")) { + delimeter = ">"; + } else { + DO(Consume("{")); + delimeter = "}"; + } + + if (field->is_repeated()) { + DO(ConsumeMessage(reflection->AddMessage(message, field), delimeter)); + } else { + DO(ConsumeMessage(reflection->MutableMessage(message, field), + delimeter)); + } + return true; + } + bool ConsumeFieldValue(Message* message, const Reflection* reflection, const FieldDescriptor* field) { @@ -750,6 +765,16 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input, return true; } +bool TextFormat::Parser::ParseFieldValueFromString( + const string& input, + const FieldDescriptor* field, + Message* output) { + io::ArrayInputStream input_stream(input.data(), input.size()); + ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_, + ParserImpl::ALLOW_SINGULAR_OVERWRITES); + return parser.ParseField(field, output); +} + /* static */ bool TextFormat::Parse(io::ZeroCopyInputStream* input, Message* output) { return Parser().Parse(input, output); @@ -1008,6 +1033,13 @@ void TextFormat::Printer::PrintFieldValue( return Printer().PrintFieldValueToString(message, field, index, output); } +/* static */ bool TextFormat::ParseFieldValueFromString( + const string& input, + const FieldDescriptor* field, + Message* message) { + return Parser().ParseFieldValueFromString(input, field, message); +} + // Prints an integer as hex with a fixed number of digits dependent on the // integer type. template diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h index e2b27c68..39a039d9 100644 --- a/src/google/protobuf/text_format.h +++ b/src/google/protobuf/text_format.h @@ -165,6 +165,13 @@ class LIBPROTOBUF_EXPORT TextFormat { // Like Merge(), but reads directly from a string. static bool MergeFromString(const string& input, Message* output); + // Parse the given text as a single field value and store it into the + // given field of the given message. If the field is a repeated field, + // the new value will be added to the end + static bool ParseFieldValueFromString(const string& input, + const FieldDescriptor* field, + Message* message); + // For more control over parsing, use this class. class LIBPROTOBUF_EXPORT Parser { public: @@ -192,6 +199,11 @@ class LIBPROTOBUF_EXPORT TextFormat { allow_partial_ = allow; } + // Like TextFormat::ParseFieldValueFromString + bool ParseFieldValueFromString(const string& input, + const FieldDescriptor* field, + Message* output); + private: // Forward declaration of an internal class used to parse text // representations (see text_format.cc for implementation). diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc index eaa278bc..7c31e80f 100644 --- a/src/google/protobuf/text_format_unittest.cc +++ b/src/google/protobuf/text_format_unittest.cc @@ -597,8 +597,8 @@ class TextFormatParserTest : public testing::Test { protected: void ExpectFailure(const string& input, const string& message, int line, int col) { - unittest::TestAllTypes proto; - ExpectFailure(input, message, line, col, &proto); + scoped_ptr proto(new unittest::TestAllTypes); + ExpectFailure(input, message, line, col, proto.get()); } void ExpectFailure(const string& input, const string& message, int line, @@ -628,6 +628,120 @@ class TextFormatParserTest : public testing::Test { }; }; +TEST_F(TextFormatParserTest, ParseFieldValueFromString) { + scoped_ptr message(new unittest::TestAllTypes); + const Descriptor* d = message->GetDescriptor(); + +#define EXPECT_FIELD(name, value, valuestring) \ + EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ + valuestring, d->FindFieldByName("optional_" #name), message.get())); \ + EXPECT_EQ(value, message->optional_##name()); \ + EXPECT_TRUE(message->has_optional_##name()); + +#define EXPECT_FLOAT_FIELD(name, value, valuestring) \ + EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ + valuestring, d->FindFieldByName("optional_" #name), message.get())); \ + EXPECT_FLOAT_EQ(value, message->optional_##name()); \ + EXPECT_TRUE(message->has_optional_##name()); + +#define EXPECT_DOUBLE_FIELD(name, value, valuestring) \ + EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ + valuestring, d->FindFieldByName("optional_" #name), message.get())); \ + EXPECT_DOUBLE_EQ(value, message->optional_##name()); \ + EXPECT_TRUE(message->has_optional_##name()); + +#define EXPECT_INVALID(name, valuestring) \ + EXPECT_FALSE(TextFormat::ParseFieldValueFromString( \ + valuestring, d->FindFieldByName("optional_" #name), message.get())); + + // int32 + EXPECT_FIELD(int32, 1, "1"); + EXPECT_FIELD(int32, -1, "-1"); + EXPECT_FIELD(int32, 0x1234, "0x1234"); + EXPECT_INVALID(int32, "a"); + EXPECT_INVALID(int32, "999999999999999999999999999999999999"); + EXPECT_INVALID(int32, "1,2"); + + // int64 + EXPECT_FIELD(int64, 1, "1"); + EXPECT_FIELD(int64, -1, "-1"); + EXPECT_FIELD(int64, 0x1234567812345678LL, "0x1234567812345678"); + EXPECT_INVALID(int64, "a"); + EXPECT_INVALID(int64, "999999999999999999999999999999999999"); + EXPECT_INVALID(int64, "1,2"); + + // uint64 + EXPECT_FIELD(uint64, 1, "1"); + EXPECT_FIELD(uint64, 0xf234567812345678ULL, "0xf234567812345678"); + EXPECT_INVALID(uint64, "-1"); + EXPECT_INVALID(uint64, "a"); + EXPECT_INVALID(uint64, "999999999999999999999999999999999999"); + EXPECT_INVALID(uint64, "1,2"); + + // fixed32 + EXPECT_FIELD(fixed32, 1, "1"); + EXPECT_FIELD(fixed32, 0x12345678, "0x12345678"); + EXPECT_INVALID(fixed32, "-1"); + EXPECT_INVALID(fixed32, "a"); + EXPECT_INVALID(fixed32, "999999999999999999999999999999999999"); + EXPECT_INVALID(fixed32, "1,2"); + + // fixed64 + EXPECT_FIELD(fixed64, 1, "1"); + EXPECT_FIELD(fixed64, 0x1234567812345678ULL, "0x1234567812345678"); + EXPECT_INVALID(fixed64, "-1"); + EXPECT_INVALID(fixed64, "a"); + EXPECT_INVALID(fixed64, "999999999999999999999999999999999999"); + EXPECT_INVALID(fixed64, "1,2"); + + // bool + EXPECT_FIELD(bool, true, "true"); + EXPECT_FIELD(bool, false, "false"); + EXPECT_INVALID(bool, "1"); + EXPECT_INVALID(bool, "on"); + EXPECT_INVALID(bool, "a"); + EXPECT_INVALID(bool, "True"); + + // float + EXPECT_FIELD(float, 1, "1"); + EXPECT_FLOAT_FIELD(float, 1.5, "1.5"); + EXPECT_FLOAT_FIELD(float, 1.5e3, "1.5e3"); + EXPECT_FLOAT_FIELD(float, -4.55, "-4.55"); + EXPECT_INVALID(float, "a"); + EXPECT_INVALID(float, "1,2"); + + // double + EXPECT_FIELD(double, 1, "1"); + EXPECT_FIELD(double, -1, "-1"); + EXPECT_DOUBLE_FIELD(double, 2.3, "2.3"); + EXPECT_DOUBLE_FIELD(double, 3e5, "3e5"); + EXPECT_INVALID(double, "a"); + EXPECT_INVALID(double, "1,2"); + + // string + EXPECT_FIELD(string, "hello", "\"hello\""); + EXPECT_FIELD(string, "-1.87", "'-1.87'"); + EXPECT_INVALID(string, "hello"); // without quote for value + + // enum + EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAR, "BAR"); + EXPECT_INVALID(nested_enum, "1"); // number not supported + EXPECT_INVALID(nested_enum, "FOOBAR"); + + // message + EXPECT_TRUE(TextFormat::ParseFieldValueFromString( + "", d->FindFieldByName("optional_nested_message"), message.get())); + EXPECT_EQ(12, message->optional_nested_message().bb()); \ + EXPECT_TRUE(message->has_optional_nested_message()); + EXPECT_INVALID(nested_message, "any"); + +#undef EXPECT_FIELD +#undef EXPECT_FLOAT_FIELD +#undef EXPECT_DOUBLE_FIELD +#undef EXPECT_INVALID +} + + TEST_F(TextFormatParserTest, InvalidToken) { ExpectFailure("optional_bool: true\n-5\n", "Expected identifier.", 2, 1); @@ -735,7 +849,7 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { "Unknown enumeration value of \"grah\" for field " "\"optional_nested_enum\".", 2, 1); - ExpectFailure( + ExpectFailure( "optional_nested_enum {\n \n}\n", "Expected \":\", found \"{\".", 1, 22); } diff --git a/src/google/protobuf/unittest_custom_options.proto b/src/google/protobuf/unittest_custom_options.proto index 88f6f1f7..b6ee03da 100644 --- a/src/google/protobuf/unittest_custom_options.proto +++ b/src/google/protobuf/unittest_custom_options.proto @@ -204,6 +204,8 @@ message SettingRealsFromNegativeInts { message ComplexOptionType1 { optional int32 foo = 1; + optional int32 foo2 = 2; + optional int32 foo3 = 3; extensions 100 to max; } diff --git a/src/google/protobuf/unittest_import_lite.proto b/src/google/protobuf/unittest_import_lite.proto new file mode 100644 index 00000000..ebaab5c0 --- /dev/null +++ b/src/google/protobuf/unittest_import_lite.proto @@ -0,0 +1,49 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// +// This is like unittest_import.proto but with optimize_for = LITE_RUNTIME. + +package protobuf_unittest_import; + +option optimize_for = LITE_RUNTIME; + +option java_package = "com.google.protobuf"; + +message ImportMessageLite { + optional int32 d = 1; +} + +enum ImportEnumLite { + IMPORT_LITE_FOO = 7; + IMPORT_LITE_BAR = 8; + IMPORT_LITE_BAZ = 9; +} diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto new file mode 100644 index 00000000..cca6b497 --- /dev/null +++ b/src/google/protobuf/unittest_lite.proto @@ -0,0 +1,312 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// +// This is like unittest.proto but with optimize_for = LITE_RUNTIME. + +package protobuf_unittest; + +import "google/protobuf/unittest_import_lite.proto"; + +option optimize_for = LITE_RUNTIME; + +option java_package = "com.google.protobuf"; + +// Same as TestAllTypes but with the lite runtime. +message TestAllTypesLite { + message NestedMessage { + optional int32 bb = 1; + } + + enum NestedEnum { + FOO = 1; + BAR = 2; + BAZ = 3; + } + + // Singular + optional int32 optional_int32 = 1; + optional int64 optional_int64 = 2; + optional uint32 optional_uint32 = 3; + optional uint64 optional_uint64 = 4; + optional sint32 optional_sint32 = 5; + optional sint64 optional_sint64 = 6; + optional fixed32 optional_fixed32 = 7; + optional fixed64 optional_fixed64 = 8; + optional sfixed32 optional_sfixed32 = 9; + optional sfixed64 optional_sfixed64 = 10; + optional float optional_float = 11; + optional double optional_double = 12; + optional bool optional_bool = 13; + optional string optional_string = 14; + optional bytes optional_bytes = 15; + + optional group OptionalGroup = 16 { + optional int32 a = 17; + } + + optional NestedMessage optional_nested_message = 18; + optional ForeignMessageLite optional_foreign_message = 19; + optional protobuf_unittest_import.ImportMessageLite + optional_import_message = 20; + + optional NestedEnum optional_nested_enum = 21; + optional ForeignEnumLite optional_foreign_enum = 22; + optional protobuf_unittest_import.ImportEnumLite optional_import_enum = 23; + + optional string optional_string_piece = 24 [ctype=STRING_PIECE]; + optional string optional_cord = 25 [ctype=CORD]; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated group RepeatedGroup = 46 { + optional int32 a = 47; + } + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessageLite repeated_foreign_message = 49; + repeated protobuf_unittest_import.ImportMessageLite + repeated_import_message = 50; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnumLite repeated_foreign_enum = 52; + repeated protobuf_unittest_import.ImportEnumLite repeated_import_enum = 53; + + repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; + repeated string repeated_cord = 55 [ctype=CORD]; + + // Singular with defaults + optional int32 default_int32 = 61 [default = 41 ]; + optional int64 default_int64 = 62 [default = 42 ]; + optional uint32 default_uint32 = 63 [default = 43 ]; + optional uint64 default_uint64 = 64 [default = 44 ]; + optional sint32 default_sint32 = 65 [default = -45 ]; + optional sint64 default_sint64 = 66 [default = 46 ]; + optional fixed32 default_fixed32 = 67 [default = 47 ]; + optional fixed64 default_fixed64 = 68 [default = 48 ]; + optional sfixed32 default_sfixed32 = 69 [default = 49 ]; + optional sfixed64 default_sfixed64 = 70 [default = -50 ]; + optional float default_float = 71 [default = 51.5 ]; + optional double default_double = 72 [default = 52e3 ]; + optional bool default_bool = 73 [default = true ]; + optional string default_string = 74 [default = "hello"]; + optional bytes default_bytes = 75 [default = "world"]; + + optional NestedEnum default_nested_enum = 81 [default = BAR]; + optional ForeignEnumLite default_foreign_enum = 82 + [default = FOREIGN_LITE_BAR]; + optional protobuf_unittest_import.ImportEnumLite + default_import_enum = 83 [default = IMPORT_LITE_BAR]; + + optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"]; + optional string default_cord = 85 [ctype=CORD,default="123"]; +} + +message ForeignMessageLite { + optional int32 c = 1; +} + +enum ForeignEnumLite { + FOREIGN_LITE_FOO = 4; + FOREIGN_LITE_BAR = 5; + FOREIGN_LITE_BAZ = 6; +} + +message TestPackedTypesLite { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnumLite packed_enum = 103 [packed = true]; +} + +message TestAllExtensionsLite { + extensions 1 to max; +} + +extend TestAllExtensionsLite { + // Singular + optional int32 optional_int32_extension_lite = 1; + optional int64 optional_int64_extension_lite = 2; + optional uint32 optional_uint32_extension_lite = 3; + optional uint64 optional_uint64_extension_lite = 4; + optional sint32 optional_sint32_extension_lite = 5; + optional sint64 optional_sint64_extension_lite = 6; + optional fixed32 optional_fixed32_extension_lite = 7; + optional fixed64 optional_fixed64_extension_lite = 8; + optional sfixed32 optional_sfixed32_extension_lite = 9; + optional sfixed64 optional_sfixed64_extension_lite = 10; + optional float optional_float_extension_lite = 11; + optional double optional_double_extension_lite = 12; + optional bool optional_bool_extension_lite = 13; + optional string optional_string_extension_lite = 14; + optional bytes optional_bytes_extension_lite = 15; + + optional group OptionalGroup_extension_lite = 16 { + optional int32 a = 17; + } + + optional TestAllTypesLite.NestedMessage optional_nested_message_extension_lite + = 18; + optional ForeignMessageLite optional_foreign_message_extension_lite = 19; + optional protobuf_unittest_import.ImportMessageLite + optional_import_message_extension_lite = 20; + + optional TestAllTypesLite.NestedEnum optional_nested_enum_extension_lite = 21; + optional ForeignEnumLite optional_foreign_enum_extension_lite = 22; + optional protobuf_unittest_import.ImportEnumLite + optional_import_enum_extension_lite = 23; + + optional string optional_string_piece_extension_lite = 24 + [ctype=STRING_PIECE]; + optional string optional_cord_extension_lite = 25 [ctype=CORD]; + + // Repeated + repeated int32 repeated_int32_extension_lite = 31; + repeated int64 repeated_int64_extension_lite = 32; + repeated uint32 repeated_uint32_extension_lite = 33; + repeated uint64 repeated_uint64_extension_lite = 34; + repeated sint32 repeated_sint32_extension_lite = 35; + repeated sint64 repeated_sint64_extension_lite = 36; + repeated fixed32 repeated_fixed32_extension_lite = 37; + repeated fixed64 repeated_fixed64_extension_lite = 38; + repeated sfixed32 repeated_sfixed32_extension_lite = 39; + repeated sfixed64 repeated_sfixed64_extension_lite = 40; + repeated float repeated_float_extension_lite = 41; + repeated double repeated_double_extension_lite = 42; + repeated bool repeated_bool_extension_lite = 43; + repeated string repeated_string_extension_lite = 44; + repeated bytes repeated_bytes_extension_lite = 45; + + repeated group RepeatedGroup_extension_lite = 46 { + optional int32 a = 47; + } + + repeated TestAllTypesLite.NestedMessage repeated_nested_message_extension_lite + = 48; + repeated ForeignMessageLite repeated_foreign_message_extension_lite = 49; + repeated protobuf_unittest_import.ImportMessageLite + repeated_import_message_extension_lite = 50; + + repeated TestAllTypesLite.NestedEnum repeated_nested_enum_extension_lite = 51; + repeated ForeignEnumLite repeated_foreign_enum_extension_lite = 52; + repeated protobuf_unittest_import.ImportEnumLite + repeated_import_enum_extension_lite = 53; + + repeated string repeated_string_piece_extension_lite = 54 + [ctype=STRING_PIECE]; + repeated string repeated_cord_extension_lite = 55 [ctype=CORD]; + + // Singular with defaults + optional int32 default_int32_extension_lite = 61 [default = 41 ]; + optional int64 default_int64_extension_lite = 62 [default = 42 ]; + optional uint32 default_uint32_extension_lite = 63 [default = 43 ]; + optional uint64 default_uint64_extension_lite = 64 [default = 44 ]; + optional sint32 default_sint32_extension_lite = 65 [default = -45 ]; + optional sint64 default_sint64_extension_lite = 66 [default = 46 ]; + optional fixed32 default_fixed32_extension_lite = 67 [default = 47 ]; + optional fixed64 default_fixed64_extension_lite = 68 [default = 48 ]; + optional sfixed32 default_sfixed32_extension_lite = 69 [default = 49 ]; + optional sfixed64 default_sfixed64_extension_lite = 70 [default = -50 ]; + optional float default_float_extension_lite = 71 [default = 51.5 ]; + optional double default_double_extension_lite = 72 [default = 52e3 ]; + optional bool default_bool_extension_lite = 73 [default = true ]; + optional string default_string_extension_lite = 74 [default = "hello"]; + optional bytes default_bytes_extension_lite = 75 [default = "world"]; + + optional TestAllTypesLite.NestedEnum + default_nested_enum_extension_lite = 81 [default = BAR]; + optional ForeignEnumLite + default_foreign_enum_extension_lite = 82 [default = FOREIGN_LITE_BAR]; + optional protobuf_unittest_import.ImportEnumLite + default_import_enum_extension_lite = 83 [default = IMPORT_LITE_BAR]; + + optional string default_string_piece_extension_lite = 84 [ctype=STRING_PIECE, + default="abc"]; + optional string default_cord_extension_lite = 85 [ctype=CORD, default="123"]; +} + +message TestPackedExtensionsLite { + extensions 1 to max; +} + +extend TestPackedExtensionsLite { + repeated int32 packed_int32_extension_lite = 90 [packed = true]; + repeated int64 packed_int64_extension_lite = 91 [packed = true]; + repeated uint32 packed_uint32_extension_lite = 92 [packed = true]; + repeated uint64 packed_uint64_extension_lite = 93 [packed = true]; + repeated sint32 packed_sint32_extension_lite = 94 [packed = true]; + repeated sint64 packed_sint64_extension_lite = 95 [packed = true]; + repeated fixed32 packed_fixed32_extension_lite = 96 [packed = true]; + repeated fixed64 packed_fixed64_extension_lite = 97 [packed = true]; + repeated sfixed32 packed_sfixed32_extension_lite = 98 [packed = true]; + repeated sfixed64 packed_sfixed64_extension_lite = 99 [packed = true]; + repeated float packed_float_extension_lite = 100 [packed = true]; + repeated double packed_double_extension_lite = 101 [packed = true]; + repeated bool packed_bool_extension_lite = 102 [packed = true]; + repeated ForeignEnumLite packed_enum_extension_lite = 103 [packed = true]; +} + +message TestNestedExtensionLite { + extend TestAllExtensionsLite { + optional int32 nested_extension = 12345; + } +} + +// Test that deprecated fields work. We only verify that they compile (at one +// point this failed). +message TestDeprecatedLite { + optional int32 deprecated_field = 1 [deprecated = true]; +} diff --git a/src/google/protobuf/unittest_lite_imports_nonlite.proto b/src/google/protobuf/unittest_lite_imports_nonlite.proto new file mode 100644 index 00000000..d52cb8cc --- /dev/null +++ b/src/google/protobuf/unittest_lite_imports_nonlite.proto @@ -0,0 +1,43 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// +// Tests that a "lite" message can import a regular message. + +package protobuf_unittest; + +import "google/protobuf/unittest.proto"; + +option optimize_for = LITE_RUNTIME; + +message TestLiteImportsNonlite { + optional TestAllTypes message = 1; +} diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc index dbd39b83..5aa67727 100644 --- a/src/google/protobuf/wire_format.cc +++ b/src/google/protobuf/wire_format.cc @@ -36,20 +36,24 @@ #include #include -#include +#include #include #include +#include #include #include #include #include #include + namespace google { namespace protobuf { namespace internal { +using internal::WireFormatLite; + namespace { // This function turns out to be convenient when using some macros later. @@ -57,74 +61,42 @@ inline int GetEnumNumber(const EnumValueDescriptor* descriptor) { return descriptor->number(); } -// These are the tags for the old MessageSet format, which was defined as: -// message MessageSet { -// repeated group Item = 1 { -// required int32 type_id = 2; -// required string message = 3; -// } -// } -const int kMessageSetItemStartTag = - GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(1, WireFormat::WIRETYPE_START_GROUP); -const int kMessageSetItemEndTag = - GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(1, WireFormat::WIRETYPE_END_GROUP); -const int kMessageSetTypeIdTag = - GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(2, WireFormat::WIRETYPE_VARINT); -const int kMessageSetMessageTag = - GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(3, WireFormat::WIRETYPE_LENGTH_DELIMITED); - -// Byte size of all tags of a MessageSet::Item combined. -static const int kMessageSetItemTagsSize = - io::CodedOutputStream::VarintSize32(kMessageSetItemStartTag) + - io::CodedOutputStream::VarintSize32(kMessageSetItemEndTag) + - io::CodedOutputStream::VarintSize32(kMessageSetTypeIdTag) + - io::CodedOutputStream::VarintSize32(kMessageSetMessageTag); - } // anonymous namespace -const WireFormat::WireType -WireFormat::kWireTypeForFieldType[FieldDescriptor::MAX_TYPE + 1] = { - static_cast(-1), // invalid - WIRETYPE_FIXED64, // TYPE_DOUBLE - WIRETYPE_FIXED32, // TYPE_FLOAT - WIRETYPE_VARINT, // TYPE_INT64 - WIRETYPE_VARINT, // TYPE_UINT64 - WIRETYPE_VARINT, // TYPE_INT32 - WIRETYPE_FIXED64, // TYPE_FIXED64 - WIRETYPE_FIXED32, // TYPE_FIXED32 - WIRETYPE_VARINT, // TYPE_BOOL - WIRETYPE_LENGTH_DELIMITED, // TYPE_STRING - WIRETYPE_START_GROUP, // TYPE_GROUP - WIRETYPE_LENGTH_DELIMITED, // TYPE_MESSAGE - WIRETYPE_LENGTH_DELIMITED, // TYPE_BYTES - WIRETYPE_VARINT, // TYPE_UINT32 - WIRETYPE_VARINT, // TYPE_ENUM - WIRETYPE_FIXED32, // TYPE_SFIXED32 - WIRETYPE_FIXED64, // TYPE_SFIXED64 - WIRETYPE_VARINT, // TYPE_SINT32 - WIRETYPE_VARINT, // TYPE_SINT64 -}; - // =================================================================== +bool UnknownFieldSetFieldSkipper::SkipField( + io::CodedInputStream* input, uint32 tag) { + return WireFormat::SkipField(input, tag, unknown_fields_); +} + +bool UnknownFieldSetFieldSkipper::SkipMessage(io::CodedInputStream* input) { + return WireFormat::SkipMessage(input, unknown_fields_); +} + +void UnknownFieldSetFieldSkipper::SkipUnknownEnum( + int field_number, int value) { + unknown_fields_->AddVarint(field_number, value); +} + bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag, UnknownFieldSet* unknown_fields) { - int number = GetTagFieldNumber(tag); + int number = WireFormatLite::GetTagFieldNumber(tag); - switch (GetTagWireType(tag)) { - case WIRETYPE_VARINT: { + switch (WireFormatLite::GetTagWireType(tag)) { + case WireFormatLite::WIRETYPE_VARINT: { uint64 value; if (!input->ReadVarint64(&value)) return false; if (unknown_fields != NULL) unknown_fields->AddVarint(number, value); return true; } - case WIRETYPE_FIXED64: { + case WireFormatLite::WIRETYPE_FIXED64: { uint64 value; if (!input->ReadLittleEndian64(&value)) return false; if (unknown_fields != NULL) unknown_fields->AddFixed64(number, value); return true; } - case WIRETYPE_LENGTH_DELIMITED: { + case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: { uint32 length; if (!input->ReadVarint32(&length)) return false; if (unknown_fields == NULL) { @@ -137,7 +109,7 @@ bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag, } return true; } - case WIRETYPE_START_GROUP: { + case WireFormatLite::WIRETYPE_START_GROUP: { if (!input->IncrementRecursionDepth()) return false; if (!SkipMessage(input, (unknown_fields == NULL) ? NULL : unknown_fields->AddGroup(number))) { @@ -145,16 +117,17 @@ bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag, } input->DecrementRecursionDepth(); // Check that the ending tag matched the starting tag. - if (!input->LastTagWas( - MakeTag(GetTagFieldNumber(tag), WIRETYPE_END_GROUP))) { + if (!input->LastTagWas(WireFormatLite::MakeTag( + WireFormatLite::GetTagFieldNumber(tag), + WireFormatLite::WIRETYPE_END_GROUP))) { return false; } return true; } - case WIRETYPE_END_GROUP: { + case WireFormatLite::WIRETYPE_END_GROUP: { return false; } - case WIRETYPE_FIXED32: { + case WireFormatLite::WIRETYPE_FIXED32: { uint32 value; if (!input->ReadLittleEndian32(&value)) return false; if (unknown_fields != NULL) unknown_fields->AddFixed32(number, value); @@ -175,9 +148,9 @@ bool WireFormat::SkipMessage(io::CodedInputStream* input, return true; } - WireType wire_type = GetTagWireType(tag); + WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); - if (wire_type == WIRETYPE_END_GROUP) { + if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) { // Must be the end of the message. return true; } @@ -192,27 +165,32 @@ void WireFormat::SerializeUnknownFields(const UnknownFieldSet& unknown_fields, const UnknownField& field = unknown_fields.field(i); switch (field.type()) { case UnknownField::TYPE_VARINT: - output->WriteVarint32(MakeTag(field.number(), WIRETYPE_VARINT)); + output->WriteVarint32(WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_VARINT)); output->WriteVarint64(field.varint()); break; case UnknownField::TYPE_FIXED32: - output->WriteVarint32(MakeTag(field.number(), WIRETYPE_FIXED32)); + output->WriteVarint32(WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_FIXED32)); output->WriteLittleEndian32(field.fixed32()); break; case UnknownField::TYPE_FIXED64: - output->WriteVarint32(MakeTag(field.number(), WIRETYPE_FIXED64)); + output->WriteVarint32(WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_FIXED64)); output->WriteLittleEndian64(field.fixed64()); break; case UnknownField::TYPE_LENGTH_DELIMITED: - output->WriteVarint32( - MakeTag(field.number(), WIRETYPE_LENGTH_DELIMITED)); + output->WriteVarint32(WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); output->WriteVarint32(field.length_delimited().size()); output->WriteString(field.length_delimited()); break; case UnknownField::TYPE_GROUP: - output->WriteVarint32(MakeTag(field.number(),WIRETYPE_START_GROUP)); + output->WriteVarint32(WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_START_GROUP)); SerializeUnknownFields(field.group(), output); - output->WriteVarint32(MakeTag(field.number(), WIRETYPE_END_GROUP)); + output->WriteVarint32(WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_END_GROUP)); break; } } @@ -226,22 +204,27 @@ uint8* WireFormat::SerializeUnknownFieldsToArray( switch (field.type()) { case UnknownField::TYPE_VARINT: - target = WriteInt64ToArray(field.number(), field.varint(), target); + target = WireFormatLite::WriteInt64ToArray( + field.number(), field.varint(), target); break; case UnknownField::TYPE_FIXED32: - target = WriteFixed32ToArray(field.number(), field.fixed32(), target); + target = WireFormatLite::WriteFixed32ToArray( + field.number(), field.fixed32(), target); break; case UnknownField::TYPE_FIXED64: - target = WriteFixed64ToArray(field.number(), field.fixed64(), target); + target = WireFormatLite::WriteFixed64ToArray( + field.number(), field.fixed64(), target); break; case UnknownField::TYPE_LENGTH_DELIMITED: - target = - WriteBytesToArray(field.number(), field.length_delimited(), target); + target = WireFormatLite::WriteBytesToArray( + field.number(), field.length_delimited(), target); break; case UnknownField::TYPE_GROUP: - target = WriteTagToArray(field.number(), WIRETYPE_START_GROUP, target); + target = WireFormatLite::WriteTagToArray( + field.number(), WireFormatLite::WIRETYPE_START_GROUP, target); target = SerializeUnknownFieldsToArray(field.group(), target); - target = WriteTagToArray(field.number(), WIRETYPE_END_GROUP, target); + target = WireFormatLite::WriteTagToArray( + field.number(), WireFormatLite::WIRETYPE_END_GROUP, target); break; } } @@ -259,19 +242,19 @@ void WireFormat::SerializeUnknownMessageSetItems( const string& data = field.length_delimited(); // Start group. - output->WriteVarint32(kMessageSetItemStartTag); + output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag); // Write type ID. - output->WriteVarint32(kMessageSetTypeIdTag); + output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag); output->WriteVarint32(field.number()); // Write message. - output->WriteVarint32(kMessageSetMessageTag); + output->WriteVarint32(WireFormatLite::kMessageSetMessageTag); output->WriteVarint32(data.size()); output->WriteString(data); // End group. - output->WriteVarint32(kMessageSetItemEndTag); + output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag); } } } @@ -288,24 +271,24 @@ uint8* WireFormat::SerializeUnknownMessageSetItemsToArray( const string& data = field.length_delimited(); // Start group. - target = - io::CodedOutputStream::WriteTagToArray(kMessageSetItemStartTag, target); + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetItemStartTag, target); // Write type ID. - target = - io::CodedOutputStream::WriteTagToArray(kMessageSetTypeIdTag, target); - target = - io::CodedOutputStream::WriteVarint32ToArray(field.number(), target); + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetTypeIdTag, target); + target = io::CodedOutputStream::WriteVarint32ToArray( + field.number(), target); // Write message. - target = - io::CodedOutputStream::WriteTagToArray(kMessageSetMessageTag, target); + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetMessageTag, target); target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target); target = io::CodedOutputStream::WriteStringToArray(data, target); // End group. - target = - io::CodedOutputStream::WriteTagToArray(kMessageSetItemEndTag, target); + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetItemEndTag, target); } } @@ -321,32 +304,38 @@ int WireFormat::ComputeUnknownFieldsSize( switch (field.type()) { case UnknownField::TYPE_VARINT: size += io::CodedOutputStream::VarintSize32( - MakeTag(field.number(), WIRETYPE_VARINT)); + WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_VARINT)); size += io::CodedOutputStream::VarintSize64(field.varint()); break; case UnknownField::TYPE_FIXED32: size += io::CodedOutputStream::VarintSize32( - MakeTag(field.number(), WIRETYPE_FIXED32)); + WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_FIXED32)); size += sizeof(int32); break; case UnknownField::TYPE_FIXED64: size += io::CodedOutputStream::VarintSize32( - MakeTag(field.number(), WIRETYPE_FIXED64)); + WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_FIXED64)); size += sizeof(int64); break; case UnknownField::TYPE_LENGTH_DELIMITED: size += io::CodedOutputStream::VarintSize32( - MakeTag(field.number(), WIRETYPE_LENGTH_DELIMITED)); + WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); size += io::CodedOutputStream::VarintSize32( - field.length_delimited().size()); + field.length_delimited().size()); size += field.length_delimited().size(); break; case UnknownField::TYPE_GROUP: size += io::CodedOutputStream::VarintSize32( - MakeTag(field.number(), WIRETYPE_START_GROUP)); + WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_START_GROUP)); size += ComputeUnknownFieldsSize(field.group()); size += io::CodedOutputStream::VarintSize32( - MakeTag(field.number(), WIRETYPE_END_GROUP)); + WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_END_GROUP)); break; } } @@ -363,7 +352,7 @@ int WireFormat::ComputeUnknownMessageSetItemsSize( // The only unknown fields that are allowed to exist in a MessageSet are // messages, which are length-delimited. if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) { - size += kMessageSetItemTagsSize; + size += WireFormatLite::kMessageSetItemTagsSize; size += io::CodedOutputStream::VarintSize32(field.number()); size += io::CodedOutputStream::VarintSize32( field.length_delimited().size()); @@ -388,7 +377,8 @@ bool WireFormat::ParseAndMergePartial(io::CodedInputStream* input, return true; } - if (GetTagWireType(tag) == WIRETYPE_END_GROUP) { + if (WireFormatLite::GetTagWireType(tag) == + WireFormatLite::WIRETYPE_END_GROUP) { // Must be the end of the message. return true; } @@ -396,7 +386,7 @@ bool WireFormat::ParseAndMergePartial(io::CodedInputStream* input, const FieldDescriptor* field = NULL; if (descriptor != NULL) { - int field_number = GetTagFieldNumber(tag); + int field_number = WireFormatLite::GetTagFieldNumber(tag); field = descriptor->FindFieldByNumber(field_number); // If that failed, check if the field is an extension. @@ -408,7 +398,7 @@ bool WireFormat::ParseAndMergePartial(io::CodedInputStream* input, // MessageSet item, then parse that. if (field == NULL && descriptor->options().message_set_wire_format() && - tag == kMessageSetItemStartTag) { + tag == WireFormatLite::kMessageSetItemStartTag) { if (!ParseAndMergeMessageSetItem(input, message)) { return false; } @@ -430,7 +420,7 @@ bool WireFormat::ParseAndMergeField( const Reflection* message_reflection = message->GetReflection(); if (field == NULL || - GetTagWireType(tag) != WireTypeForField(field)) { + WireFormatLite::GetTagWireType(tag) != WireTypeForField(field)) { // We don't recognize this field. Either the field number is unknown // or the wire type doesn't match. Put it in our unknown field set. return SkipField(input, tag, @@ -443,14 +433,14 @@ bool WireFormat::ParseAndMergeField( io::CodedInputStream::Limit limit = input->PushLimit(length); switch (field->type()) { -#define HANDLE_PACKED_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD) \ - case FieldDescriptor::TYPE_##TYPE: { \ - while (input->BytesUntilLimit() > 0) { \ - CPPTYPE value; \ - if (!Read##TYPE_METHOD(input, &value)) return false; \ - message_reflection->Add##CPPTYPE_METHOD(message, field, value); \ - } \ - break; \ +#define HANDLE_PACKED_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: { \ + while (input->BytesUntilLimit() > 0) { \ + CPPTYPE value; \ + if (!WireFormatLite::Read##TYPE_METHOD(input, &value)) return false; \ + message_reflection->Add##CPPTYPE_METHOD(message, field, value); \ + } \ + break; \ } HANDLE_PACKED_TYPE( INT32, Int32, int32, Int32) @@ -474,7 +464,7 @@ bool WireFormat::ParseAndMergeField( case FieldDescriptor::TYPE_ENUM: { while (input->BytesUntilLimit() > 0) { int value; - if (!ReadEnum(input, &value)) return false; + if (!WireFormatLite::ReadEnum(input, &value)) return false; const EnumValueDescriptor* enum_value = field->enum_type()->FindValueByNumber(value); if (enum_value != NULL) { @@ -498,16 +488,16 @@ bool WireFormat::ParseAndMergeField( input->PopLimit(limit); } else { switch (field->type()) { -#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD) \ - case FieldDescriptor::TYPE_##TYPE: { \ - CPPTYPE value; \ - if (!Read##TYPE_METHOD(input, &value)) return false; \ - if (field->is_repeated()) { \ - message_reflection->Add##CPPTYPE_METHOD(message, field, value); \ - } else { \ - message_reflection->Set##CPPTYPE_METHOD(message, field, value); \ - } \ - break; \ +#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: { \ + CPPTYPE value; \ + if (!WireFormatLite::Read##TYPE_METHOD(input, &value)) return false; \ + if (field->is_repeated()) { \ + message_reflection->Add##CPPTYPE_METHOD(message, field, value); \ + } else { \ + message_reflection->Set##CPPTYPE_METHOD(message, field, value); \ + } \ + break; \ } HANDLE_TYPE( INT32, Int32, int32, Int32) @@ -534,7 +524,7 @@ bool WireFormat::ParseAndMergeField( case FieldDescriptor::TYPE_ENUM: { int value; - if (!ReadEnum(input, &value)) return false; + if (!WireFormatLite::ReadEnum(input, &value)) return false; const EnumValueDescriptor* enum_value = field->enum_type()->FindValueByNumber(value); if (enum_value != NULL) { @@ -548,7 +538,7 @@ bool WireFormat::ParseAndMergeField( // UnknownFieldSet. int64 sign_extended_value = static_cast(value); message_reflection->MutableUnknownFields(message) - ->AddVarint(GetTagFieldNumber(tag), + ->AddVarint(WireFormatLite::GetTagFieldNumber(tag), sign_extended_value); } break; @@ -563,7 +553,8 @@ bool WireFormat::ParseAndMergeField( sub_message = message_reflection->MutableMessage(message, field); } - if (!ReadGroup(GetTagFieldNumber(tag), input, sub_message)) + if (!WireFormatLite::ReadGroup(WireFormatLite::GetTagFieldNumber(tag), + input, sub_message)) return false; break; } @@ -576,7 +567,7 @@ bool WireFormat::ParseAndMergeField( sub_message = message_reflection->MutableMessage(message, field); } - if (!ReadMessage(input, sub_message)) return false; + if (!WireFormatLite::ReadMessage(input, sub_message)) return false; break; } } @@ -615,10 +606,11 @@ bool WireFormat::ParseAndMergeMessageSetItem( if (tag == 0) return false; switch (tag) { - case kMessageSetTypeIdTag: { + case WireFormatLite::kMessageSetTypeIdTag: { uint32 type_id; if (!input->ReadVarint32(&type_id)) return false; - fake_tag = MakeTag(type_id, WIRETYPE_LENGTH_DELIMITED); + fake_tag = WireFormatLite::MakeTag( + type_id, WireFormatLite::WIRETYPE_LENGTH_DELIMITED); field = message_reflection->FindKnownExtensionByNumber(type_id); if (!message_data.empty()) { @@ -637,7 +629,7 @@ bool WireFormat::ParseAndMergeMessageSetItem( break; } - case kMessageSetMessageTag: { + case WireFormatLite::kMessageSetMessageTag: { if (fake_tag == 0) { // We haven't seen a type_id yet. Append this data to message_data. string temp; @@ -655,7 +647,7 @@ bool WireFormat::ParseAndMergeMessageSetItem( break; } - case kMessageSetItemEndTag: { + case WireFormatLite::kMessageSetItemEndTag: { return true; } @@ -719,7 +711,8 @@ void WireFormat::SerializeFieldWithCachedSizes( const bool is_packed = field->options().packed(); if (is_packed && count > 0) { - WriteTag(field->number(), WIRETYPE_LENGTH_DELIMITED, output); + WireFormatLite::WriteTag(field->number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); const int data_size = FieldDataOnlyByteSize(field, message); output->WriteVarint32(data_size); } @@ -734,9 +727,9 @@ void WireFormat::SerializeFieldWithCachedSizes( message_reflection->Get##CPPTYPE_METHOD( \ message, field); \ if (is_packed) { \ - Write##TYPE_METHOD##NoTag(value, output); \ + WireFormatLite::Write##TYPE_METHOD##NoTag(value, output); \ } else { \ - Write##TYPE_METHOD(field->number(), value, output); \ + WireFormatLite::Write##TYPE_METHOD(field->number(), value, output); \ } \ break; \ } @@ -761,7 +754,7 @@ void WireFormat::SerializeFieldWithCachedSizes( #define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD) \ case FieldDescriptor::TYPE_##TYPE: \ - Write##TYPE_METHOD( \ + WireFormatLite::Write##TYPE_METHOD( \ field->number(), \ field->is_repeated() ? \ message_reflection->GetRepeated##CPPTYPE_METHOD( \ @@ -779,9 +772,9 @@ void WireFormat::SerializeFieldWithCachedSizes( message_reflection->GetRepeatedEnum(message, field, j) : message_reflection->GetEnum(message, field); if (is_packed) { - WriteEnumNoTag(value->number(), output); + WireFormatLite::WriteEnumNoTag(value->number(), output); } else { - WriteEnum(field->number(), value->number(), output); + WireFormatLite::WriteEnum(field->number(), value->number(), output); } break; } @@ -794,7 +787,8 @@ void WireFormat::SerializeFieldWithCachedSizes( message_reflection->GetRepeatedStringReference( message, field, j, &scratch) : message_reflection->GetStringReference(message, field, &scratch); - WriteString(field->number(), value, output); + VerifyUTF8String(value.data(), value.length(), SERIALIZE); + WireFormatLite::WriteString(field->number(), value, output); break; } @@ -804,7 +798,7 @@ void WireFormat::SerializeFieldWithCachedSizes( message_reflection->GetRepeatedStringReference( message, field, j, &scratch) : message_reflection->GetStringReference(message, field, &scratch); - WriteBytes(field->number(), value, output); + WireFormatLite::WriteBytes(field->number(), value, output); break; } } @@ -818,21 +812,21 @@ void WireFormat::SerializeMessageSetItemWithCachedSizes( const Reflection* message_reflection = message.GetReflection(); // Start group. - output->WriteVarint32(kMessageSetItemStartTag); + output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag); // Write type ID. - output->WriteVarint32(kMessageSetTypeIdTag); + output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag); output->WriteVarint32(field->number()); // Write message. - output->WriteVarint32(kMessageSetMessageTag); + output->WriteVarint32(WireFormatLite::kMessageSetMessageTag); const Message& sub_message = message_reflection->GetMessage(message, field); output->WriteVarint32(sub_message.GetCachedSize()); sub_message.SerializeWithCachedSizes(output); // End group. - output->WriteVarint32(kMessageSetItemEndTag); + output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag); } // =================================================================== @@ -913,19 +907,19 @@ int WireFormat::FieldDataOnlyByteSize( case FieldDescriptor::TYPE_##TYPE: \ if (field->is_repeated()) { \ for (int j = 0; j < count; j++) { \ - data_size += TYPE_METHOD##Size( \ + data_size += WireFormatLite::TYPE_METHOD##Size( \ message_reflection->GetRepeated##CPPTYPE_METHOD( \ message, field, j)); \ } \ } else { \ - data_size += TYPE_METHOD##Size( \ + data_size += WireFormatLite::TYPE_METHOD##Size( \ message_reflection->Get##CPPTYPE_METHOD(message, field)); \ } \ break; #define HANDLE_FIXED_TYPE(TYPE, TYPE_METHOD) \ case FieldDescriptor::TYPE_##TYPE: \ - data_size += count * k##TYPE_METHOD##Size; \ + data_size += count * WireFormatLite::k##TYPE_METHOD##Size; \ break; HANDLE_TYPE( INT32, Int32, Int32) @@ -953,11 +947,11 @@ int WireFormat::FieldDataOnlyByteSize( case FieldDescriptor::TYPE_ENUM: { if (field->is_repeated()) { for (int j = 0; j < count; j++) { - data_size += EnumSize( + data_size += WireFormatLite::EnumSize( message_reflection->GetRepeatedEnum(message, field, j)->number()); } } else { - data_size += EnumSize( + data_size += WireFormatLite::EnumSize( message_reflection->GetEnum(message, field)->number()); } break; @@ -973,7 +967,7 @@ int WireFormat::FieldDataOnlyByteSize( message_reflection->GetRepeatedStringReference( message, field, j, &scratch) : message_reflection->GetStringReference(message, field, &scratch); - data_size += StringSize(value); + data_size += WireFormatLite::StringSize(value); } break; } @@ -986,7 +980,7 @@ int WireFormat::MessageSetItemByteSize( const Message& message) { const Reflection* message_reflection = message.GetReflection(); - int our_size = kMessageSetItemTagsSize; + int our_size = WireFormatLite::kMessageSetItemTagsSize; // type_id our_size += io::CodedOutputStream::VarintSize32(field->number()); @@ -1001,6 +995,28 @@ int WireFormat::MessageSetItemByteSize( return our_size; } +void WireFormat::VerifyUTF8StringFallback(const char* data, + int size, + Operation op) { + if (!IsStructurallyValidUTF8(data, size)) { + const char* operation_str = NULL; + switch (op) { + case PARSE: + operation_str = "parsing"; + break; + case SERIALIZE: + operation_str = "serializing"; + break; + // no default case: have the compiler warn if a case is not covered. + } + GOOGLE_LOG(ERROR) << "Encountered string containing invalid UTF-8 data while " + << operation_str + << " protocol buffer. Strings must contain only UTF-8; " + "use the 'bytes' type for raw bytes."; + } +} + + } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h index 963f427a..c7539250 100644 --- a/src/google/protobuf/wire_format.h +++ b/src/google/protobuf/wire_format.h @@ -40,17 +40,23 @@ #define GOOGLE_PROTOBUF_WIRE_FORMAT_H__ #include -#include +#include #include +#include +#include -namespace google { +// Do UTF-8 validation on string type in Debug build only +#ifndef NDEBUG +#define GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED +#endif +namespace google { namespace protobuf { namespace io { class CodedInputStream; // coded_stream.h class CodedOutputStream; // coded_stream.h } - class UnknownFieldSet; // unknown_field_set.h + class UnknownFieldSet; // unknown_field_set.h } namespace protobuf { @@ -60,13 +66,26 @@ namespace internal { // protocol-complier-generated message classes. It must not be called // directly by clients. // -// This class contains helpers for implementing the binary protocol buffer -// wire format. These helpers are called primarily by generated code. The -// class also contains reflection-based implementations of the wire format. +// This class contains code for implementing the binary protocol buffer +// wire format via reflection. The WireFormatLite class implements the +// non-reflection based routines. // -// This class is really a namespace that contains only static methods. +// This class is really a namespace that contains only static methods class LIBPROTOBUF_EXPORT WireFormat { public: + + // Given a field return its WireType + static inline WireFormatLite::WireType WireTypeForField( + const FieldDescriptor* field); + + // Given a FieldSescriptor::Type return its WireType + static inline WireFormatLite::WireType WireTypeForFieldType( + FieldDescriptor::Type type); + + // Compute the byte size of a tag. For groups, this includes both the start + // and end tags. + static inline int TagSize(int field_number, FieldDescriptor::Type type); + // These procedures can be used to implement the methods of Message which // handle parsing and serialization of the protocol buffer wire format // using only the Reflection interface. When you ask the protocol @@ -152,41 +171,6 @@ class LIBPROTOBUF_EXPORT WireFormat { static int ComputeUnknownMessageSetItemsSize( const UnknownFieldSet& unknown_fields); - // ----------------------------------------------------------------- - // Helper constants and functions related to the format. These are - // mostly meant for internal and generated code to use. - - // The wire format is composed of a sequence of tag/value pairs, each - // of which contains the value of one field (or one element of a repeated - // field). Each tag is encoded as a varint. The lower bits of the tag - // identify its wire type, which specifies the format of the data to follow. - // The rest of the bits contain the field number. Each type of field (as - // declared by FieldDescriptor::Type, in descriptor.h) maps to one of - // these wire types. Immediately following each tag is the field's value, - // encoded in the format specified by the wire type. Because the tag - // identifies the encoding of this data, it is possible to skip - // unrecognized fields for forwards compatibility. - - enum WireType { - WIRETYPE_VARINT = 0, - WIRETYPE_FIXED64 = 1, - WIRETYPE_LENGTH_DELIMITED = 2, - WIRETYPE_START_GROUP = 3, - WIRETYPE_END_GROUP = 4, - WIRETYPE_FIXED32 = 5, - }; - - static inline WireType WireTypeForFieldType(FieldDescriptor::Type type) { - return kWireTypeForFieldType[type]; - } - // This is different from WireTypeForFieldType(field->type()) in the case of - // packed repeated fields. - static inline WireType WireTypeForField(const FieldDescriptor* field); - - // Number of bits in a tag which identify the wire type. - static const int kTagTypeBits = 3; - // Mask for those bits. - static const uint32 kTagTypeMask = (1 << kTagTypeBits) - 1; // Helper functions for encoding and decoding tags. (Inlined below and in // _inl.h) @@ -194,28 +178,6 @@ class LIBPROTOBUF_EXPORT WireFormat { // This is different from MakeTag(field->number(), field->type()) in the case // of packed repeated fields. static uint32 MakeTag(const FieldDescriptor* field); - static uint32 MakeTag(int field_number, WireType type); - static WireType GetTagWireType(uint32 tag); - static int GetTagFieldNumber(uint32 tag); - - // Helper functions for converting between floats/doubles and IEEE-754 - // uint32s/uint64s so that they can be written. (Assumes your platform - // uses IEEE-754 floats.) - static uint32 EncodeFloat(float value); - static float DecodeFloat(uint32 value); - static uint64 EncodeDouble(double value); - static double DecodeDouble(uint64 value); - - // Helper functions for mapping signed integers to unsigned integers in - // such a way that numbers with small magnitudes will encode to smaller - // varints. If you simply static_cast a negative number to an unsigned - // number and varint-encode it, it will always take 10 bytes, defeating - // the purpose of varint. So, for the "sint32" and "sint64" field types, - // we ZigZag-encode the values. - static uint32 ZigZagEncode32(int32 n); - static int32 ZigZagDecode32(uint32 n); - static uint64 ZigZagEncode64(int64 n); - static int64 ZigZagDecode64(uint64 n); // Parse a single field. The input should start out positioned immidately // after the tag. @@ -238,223 +200,6 @@ class LIBPROTOBUF_EXPORT WireFormat { const FieldDescriptor* field, // Cannot be NULL const Message& message); - // ================================================================= - // Methods for reading/writing individual field. The implementations - // of these methods are defined in wire_format_inl.h; you must #include - // that file to use these. - -// Avoid ugly line wrapping -#define input io::CodedInputStream* input -#define output io::CodedOutputStream* output -#define field_number int field_number -#define INL GOOGLE_ATTRIBUTE_ALWAYS_INLINE - - // Read fields, not including tags. The assumption is that you already - // read the tag to determine what field to read. - static inline bool ReadInt32 (input, int32* value); - static inline bool ReadInt64 (input, int64* value); - static inline bool ReadUInt32 (input, uint32* value); - static inline bool ReadUInt64 (input, uint64* value); - static inline bool ReadSInt32 (input, int32* value); - static inline bool ReadSInt64 (input, int64* value); - static inline bool ReadFixed32 (input, uint32* value); - static inline bool ReadFixed64 (input, uint64* value); - static inline bool ReadSFixed32(input, int32* value); - static inline bool ReadSFixed64(input, int64* value); - static inline bool ReadFloat (input, float* value); - static inline bool ReadDouble (input, double* value); - static inline bool ReadBool (input, bool* value); - static inline bool ReadEnum (input, int* value); - - static inline bool ReadString(input, string* value); - static inline bool ReadBytes (input, string* value); - - static inline bool ReadGroup (field_number, input, Message* value); - static inline bool ReadMessage(input, Message* value); - - // Like above, but de-virtualize the call to MergePartialFromCodedStream(). - // The pointer must point at an instance of MessageType, *not* a subclass (or - // the subclass must not override MergePartialFromCodedStream()). - template - static inline bool ReadGroupNoVirtual(field_number, input, - MessageType* value); - template - static inline bool ReadMessageNoVirtual(input, MessageType* value); - - // Write a tag. The Write*() functions typically include the tag, so - // normally there's no need to call this unless using the Write*NoTag() - // variants. - static inline void WriteTag(field_number, WireType type, output) INL; - - // Write fields, without tags. - static inline void WriteInt32NoTag (int32 value, output) INL; - static inline void WriteInt64NoTag (int64 value, output) INL; - static inline void WriteUInt32NoTag (uint32 value, output) INL; - static inline void WriteUInt64NoTag (uint64 value, output) INL; - static inline void WriteSInt32NoTag (int32 value, output) INL; - static inline void WriteSInt64NoTag (int64 value, output) INL; - static inline void WriteFixed32NoTag (uint32 value, output) INL; - static inline void WriteFixed64NoTag (uint64 value, output) INL; - static inline void WriteSFixed32NoTag(int32 value, output) INL; - static inline void WriteSFixed64NoTag(int64 value, output) INL; - static inline void WriteFloatNoTag (float value, output) INL; - static inline void WriteDoubleNoTag (double value, output) INL; - static inline void WriteBoolNoTag (bool value, output) INL; - static inline void WriteEnumNoTag (int value, output) INL; - - // Write fields, including tags. - static inline void WriteInt32 (field_number, int32 value, output) INL; - static inline void WriteInt64 (field_number, int64 value, output) INL; - static inline void WriteUInt32 (field_number, uint32 value, output) INL; - static inline void WriteUInt64 (field_number, uint64 value, output) INL; - static inline void WriteSInt32 (field_number, int32 value, output) INL; - static inline void WriteSInt64 (field_number, int64 value, output) INL; - static inline void WriteFixed32 (field_number, uint32 value, output) INL; - static inline void WriteFixed64 (field_number, uint64 value, output) INL; - static inline void WriteSFixed32(field_number, int32 value, output) INL; - static inline void WriteSFixed64(field_number, int64 value, output) INL; - static inline void WriteFloat (field_number, float value, output) INL; - static inline void WriteDouble (field_number, double value, output) INL; - static inline void WriteBool (field_number, bool value, output) INL; - static inline void WriteEnum (field_number, int value, output) INL; - - static inline void WriteString(field_number, const string& value, output) INL; - static inline void WriteBytes (field_number, const string& value, output) INL; - - static inline void WriteGroup(field_number, const Message& value, output) INL; - static inline void WriteMessage( - field_number, const Message& value, output) INL; - - // Like above, but de-virtualize the call to SerializeWithCachedSizes(). The - // pointer must point at an instance of MessageType, *not* a subclass (or - // the subclass must not override SerializeWithCachedSizes()). - template - static inline void WriteGroupNoVirtual( - field_number, const MessageType& value, output) INL; - template - static inline void WriteMessageNoVirtual( - field_number, const MessageType& value, output) INL; - -#undef output -#define output uint8* target - - // Like above, but use only *ToArray methods of CodedOutputStream. - static inline uint8* WriteTagToArray(field_number, WireType type, output) INL; - - // Write fields, without tags. - static inline uint8* WriteInt32NoTagToArray (int32 value, output) INL; - static inline uint8* WriteInt64NoTagToArray (int64 value, output) INL; - static inline uint8* WriteUInt32NoTagToArray (uint32 value, output) INL; - static inline uint8* WriteUInt64NoTagToArray (uint64 value, output) INL; - static inline uint8* WriteSInt32NoTagToArray (int32 value, output) INL; - static inline uint8* WriteSInt64NoTagToArray (int64 value, output) INL; - static inline uint8* WriteFixed32NoTagToArray (uint32 value, output) INL; - static inline uint8* WriteFixed64NoTagToArray (uint64 value, output) INL; - static inline uint8* WriteSFixed32NoTagToArray(int32 value, output) INL; - static inline uint8* WriteSFixed64NoTagToArray(int64 value, output) INL; - static inline uint8* WriteFloatNoTagToArray (float value, output) INL; - static inline uint8* WriteDoubleNoTagToArray (double value, output) INL; - static inline uint8* WriteBoolNoTagToArray (bool value, output) INL; - static inline uint8* WriteEnumNoTagToArray (int value, output) INL; - - // Write fields, including tags. - static inline uint8* WriteInt32ToArray( - field_number, int32 value, output) INL; - static inline uint8* WriteInt64ToArray( - field_number, int64 value, output) INL; - static inline uint8* WriteUInt32ToArray( - field_number, uint32 value, output) INL; - static inline uint8* WriteUInt64ToArray( - field_number, uint64 value, output) INL; - static inline uint8* WriteSInt32ToArray( - field_number, int32 value, output) INL; - static inline uint8* WriteSInt64ToArray( - field_number, int64 value, output) INL; - static inline uint8* WriteFixed32ToArray( - field_number, uint32 value, output) INL; - static inline uint8* WriteFixed64ToArray( - field_number, uint64 value, output) INL; - static inline uint8* WriteSFixed32ToArray( - field_number, int32 value, output) INL; - static inline uint8* WriteSFixed64ToArray( - field_number, int64 value, output) INL; - static inline uint8* WriteFloatToArray( - field_number, float value, output) INL; - static inline uint8* WriteDoubleToArray( - field_number, double value, output) INL; - static inline uint8* WriteBoolToArray( - field_number, bool value, output) INL; - static inline uint8* WriteEnumToArray( - field_number, int value, output) INL; - - static inline uint8* WriteStringToArray( - field_number, const string& value, output) INL; - static inline uint8* WriteBytesToArray( - field_number, const string& value, output) INL; - - static inline uint8* WriteGroupToArray( - field_number, const Message& value, output) INL; - static inline uint8* WriteMessageToArray( - field_number, const Message& value, output) INL; - - // Like above, but de-virtualize the call to SerializeWithCachedSizes(). The - // pointer must point at an instance of MessageType, *not* a subclass (or - // the subclass must not override SerializeWithCachedSizes()). - template - static inline uint8* WriteGroupNoVirtualToArray( - field_number, const MessageType& value, output) INL; - template - static inline uint8* WriteMessageNoVirtualToArray( - field_number, const MessageType& value, output) INL; - -#undef output -#undef input -#undef INL - - // Compute the byte size of a tag. For groups, this includes both the start - // and end tags. - static inline int TagSize(field_number, FieldDescriptor::Type type); - -#undef field_number - - // Compute the byte size of a field. The XxSize() functions do NOT include - // the tag, so you must also call TagSize(). (This is because, for repeated - // fields, you should only call TagSize() once and multiply it by the element - // count, but you may have to call XxSize() for each individual element.) - static inline int Int32Size ( int32 value); - static inline int Int64Size ( int64 value); - static inline int UInt32Size (uint32 value); - static inline int UInt64Size (uint64 value); - static inline int SInt32Size ( int32 value); - static inline int SInt64Size ( int64 value); - static inline int EnumSize ( int value); - - // These types always have the same size. - static const int kFixed32Size = 4; - static const int kFixed64Size = 8; - static const int kSFixed32Size = 4; - static const int kSFixed64Size = 8; - static const int kFloatSize = 4; - static const int kDoubleSize = 8; - static const int kBoolSize = 1; - - static inline int StringSize(const string& value); - static inline int BytesSize (const string& value); - - static inline int GroupSize (const Message& value); - static inline int MessageSize(const Message& value); - - // Like above, but de-virtualize the call to ByteSize(). The - // pointer must point at an instance of MessageType, *not* a subclass (or - // the subclass must not override ByteSize()). - template - static inline int GroupSizeNoVirtual (const MessageType& value); - template - static inline int MessageSizeNoVirtual(const MessageType& value); - - private: - static const WireType kWireTypeForFieldType[]; - // Parse/serialize a MessageSet::Item group. Used with messages that use // opion message_set_wire_format = true. static bool ParseAndMergeMessageSetItem( @@ -476,97 +221,82 @@ class LIBPROTOBUF_EXPORT WireFormat { const FieldDescriptor* field, // Cannot be NULL const Message& message); - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormat); -}; + enum Operation { + PARSE, + SERIALIZE, + }; -// inline methods ==================================================== + // Verifies that a string field is valid UTF8, logging an error if not. + static void VerifyUTF8String(const char* data, int size, Operation op); -// This macro does the same thing as WireFormat::MakeTag(), but the -// result is usable as a compile-time constant, which makes it usable -// as a switch case or a template input. WireFormat::MakeTag() is more -// type-safe, though, so prefer it if possible. -#define GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(FIELD_NUMBER, TYPE) \ - static_cast( \ - ((FIELD_NUMBER) << ::google::protobuf::internal::WireFormat::kTagTypeBits) | (TYPE)) + private: + // Verifies that a string field is valid UTF8, logging an error if not. + static void VerifyUTF8StringFallback( + const char* data, + int size, + Operation op); -inline uint32 WireFormat::MakeTag(int field_number, WireType type) { - return GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(field_number, type); -} -inline WireFormat::WireType WireFormat::GetTagWireType(uint32 tag) { - return static_cast(tag & kTagTypeMask); -} -inline int WireFormat::GetTagFieldNumber(uint32 tag) { - return static_cast(tag >> kTagTypeBits); -} + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormat); +}; -inline uint32 WireFormat::EncodeFloat(float value) { - union {float f; uint32 i;}; - f = value; - return i; -} +// Subclass of FieldSkipper which saves skipped fields to an UnknownFieldSet. +class LIBPROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper { + public: + UnknownFieldSetFieldSkipper(UnknownFieldSet* unknown_fields) + : unknown_fields_(unknown_fields) {} + virtual ~UnknownFieldSetFieldSkipper() {} -inline float WireFormat::DecodeFloat(uint32 value) { - union {float f; uint32 i;}; - i = value; - return f; -} + // implements FieldSkipper ----------------------------------------- + virtual bool SkipField(io::CodedInputStream* input, uint32 tag); + virtual bool SkipMessage(io::CodedInputStream* input); + virtual void SkipUnknownEnum(int field_number, int value); -inline uint64 WireFormat::EncodeDouble(double value) { - union {double f; uint64 i;}; - f = value; - return i; -} + private: + UnknownFieldSet* unknown_fields_; +}; -inline double WireFormat::DecodeDouble(uint64 value) { - union {double f; uint64 i;}; - i = value; - return f; -} +// inline methods ==================================================== -// ZigZag Transform: Encodes signed integers so that they can be -// effectively used with varint encoding. -// -// varint operates on unsigned integers, encoding smaller numbers into -// fewer bytes. If you try to use it on a signed integer, it will treat -// this number as a very large unsigned integer, which means that even -// small signed numbers like -1 will take the maximum number of bytes -// (10) to encode. ZigZagEncode() maps signed integers to unsigned -// in such a way that those with a small absolute value will have smaller -// encoded values, making them appropriate for encoding using varint. -// -// int32 -> uint32 -// ------------------------- -// 0 -> 0 -// -1 -> 1 -// 1 -> 2 -// -2 -> 3 -// ... -> ... -// 2147483647 -> 4294967294 -// -2147483648 -> 4294967295 -// -// >> encode >> -// << decode << +inline WireFormatLite::WireType WireFormat::WireTypeForField( + const FieldDescriptor* field) { + if (field->options().packed()) { + return WireFormatLite::WIRETYPE_LENGTH_DELIMITED; + } else { + return WireTypeForFieldType(field->type()); + } +} -inline uint32 WireFormat::ZigZagEncode32(int32 n) { - // Note: the right-shift must be arithmetic - return (n << 1) ^ (n >> 31); +inline WireFormatLite::WireType WireFormat::WireTypeForFieldType( + FieldDescriptor::Type type) { + // Some compilers don't like enum -> enum casts, so we implicit_cast to + // int first. + return WireFormatLite::WireTypeForFieldType( + static_cast( + implicit_cast(type))); } -inline int32 WireFormat::ZigZagDecode32(uint32 n) { - return (n >> 1) ^ -static_cast(n & 1); +inline uint32 WireFormat::MakeTag(const FieldDescriptor* field) { + return WireFormatLite::MakeTag(field->number(), WireTypeForField(field)); } -inline uint64 WireFormat::ZigZagEncode64(int64 n) { - // Note: the right-shift must be arithmetic - return (n << 1) ^ (n >> 63); +inline int WireFormat::TagSize(int field_number, FieldDescriptor::Type type) { + // Some compilers don't like enum -> enum casts, so we implicit_cast to + // int first. + return WireFormatLite::TagSize(field_number, + static_cast( + implicit_cast(type))); } -inline int64 WireFormat::ZigZagDecode64(uint64 n) { - return (n >> 1) ^ -static_cast(n & 1); +inline void WireFormat::VerifyUTF8String(const char* data, int size, + WireFormat::Operation op) { +#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + WireFormat::VerifyUTF8StringFallback(data, size, op); +#endif } + } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/wire_format_inl.h b/src/google/protobuf/wire_format_inl.h deleted file mode 100644 index 69256080..00000000 --- a/src/google/protobuf/wire_format_inl.h +++ /dev/null @@ -1,687 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// 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. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_INL_H__ -#define GOOGLE_PROTOBUF_WIRE_FORMAT_INL_H__ - -#include -#include -#include -#include -#include -#include - - -// Do UTF-8 validation on string type in Debug build only -#ifndef NDEBUG -#define GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED -#endif - - -namespace google { -namespace protobuf { -namespace internal { - -inline WireFormat::WireType WireFormat::WireTypeForField( - const FieldDescriptor* field) { - if (field->options().packed()) { - return WIRETYPE_LENGTH_DELIMITED; - } else { - return WireTypeForFieldType(field->type()); - } -} - -inline uint32 WireFormat::MakeTag(const FieldDescriptor* field) { - return MakeTag(field->number(), WireTypeForField(field)); -} - -inline bool WireFormat::ReadInt32(io::CodedInputStream* input, int32* value) { - uint32 temp; - if (!input->ReadVarint32(&temp)) return false; - *value = static_cast(temp); - return true; -} -inline bool WireFormat::ReadInt64(io::CodedInputStream* input, int64* value) { - uint64 temp; - if (!input->ReadVarint64(&temp)) return false; - *value = static_cast(temp); - return true; -} -inline bool WireFormat::ReadUInt32(io::CodedInputStream* input, uint32* value) { - return input->ReadVarint32(value); -} -inline bool WireFormat::ReadUInt64(io::CodedInputStream* input, uint64* value) { - return input->ReadVarint64(value); -} -inline bool WireFormat::ReadSInt32(io::CodedInputStream* input, int32* value) { - uint32 temp; - if (!input->ReadVarint32(&temp)) return false; - *value = ZigZagDecode32(temp); - return true; -} -inline bool WireFormat::ReadSInt64(io::CodedInputStream* input, int64* value) { - uint64 temp; - if (!input->ReadVarint64(&temp)) return false; - *value = ZigZagDecode64(temp); - return true; -} -inline bool WireFormat::ReadFixed32(io::CodedInputStream* input, - uint32* value) { - return input->ReadLittleEndian32(value); -} -inline bool WireFormat::ReadFixed64(io::CodedInputStream* input, - uint64* value) { - return input->ReadLittleEndian64(value); -} -inline bool WireFormat::ReadSFixed32(io::CodedInputStream* input, - int32* value) { - uint32 temp; - if (!input->ReadLittleEndian32(&temp)) return false; - *value = static_cast(temp); - return true; -} -inline bool WireFormat::ReadSFixed64(io::CodedInputStream* input, - int64* value) { - uint64 temp; - if (!input->ReadLittleEndian64(&temp)) return false; - *value = static_cast(temp); - return true; -} -inline bool WireFormat::ReadFloat(io::CodedInputStream* input, float* value) { - uint32 temp; - if (!input->ReadLittleEndian32(&temp)) return false; - *value = DecodeFloat(temp); - return true; -} -inline bool WireFormat::ReadDouble(io::CodedInputStream* input, double* value) { - uint64 temp; - if (!input->ReadLittleEndian64(&temp)) return false; - *value = DecodeDouble(temp); - return true; -} -inline bool WireFormat::ReadBool(io::CodedInputStream* input, bool* value) { - uint32 temp; - if (!input->ReadVarint32(&temp)) return false; - *value = temp != 0; - return true; -} -inline bool WireFormat::ReadEnum(io::CodedInputStream* input, int* value) { - uint32 temp; - if (!input->ReadVarint32(&temp)) return false; - *value = static_cast(temp); - return true; -} - -inline bool WireFormat::ReadString(io::CodedInputStream* input, string* value) { - // String is for UTF-8 text only - uint32 length; - if (!input->ReadVarint32(&length)) return false; - if (!input->ReadString(value, length)) return false; -#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED - if (!IsStructurallyValidUTF8(value->data(), length)) { - GOOGLE_LOG(ERROR) << "Encountered string containing invalid UTF-8 data while " - "parsing protocol buffer. Strings must contain only UTF-8; " - "use the 'bytes' type for raw bytes."; - } -#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED - return true; -} -inline bool WireFormat::ReadBytes(io::CodedInputStream* input, string* value) { - uint32 length; - if (!input->ReadVarint32(&length)) return false; - return input->ReadString(value, length); -} - - -inline bool WireFormat::ReadGroup(int field_number, - io::CodedInputStream* input, - Message* value) { - if (!input->IncrementRecursionDepth()) return false; - if (!value->MergePartialFromCodedStream(input)) return false; - input->DecrementRecursionDepth(); - // Make sure the last thing read was an end tag for this group. - if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { - return false; - } - return true; -} -inline bool WireFormat::ReadMessage(io::CodedInputStream* input, - Message* value) { - uint32 length; - if (!input->ReadVarint32(&length)) return false; - if (!input->IncrementRecursionDepth()) return false; - io::CodedInputStream::Limit limit = input->PushLimit(length); - if (!value->MergePartialFromCodedStream(input)) return false; - // Make sure that parsing stopped when the limit was hit, not at an endgroup - // tag. - if (!input->ConsumedEntireMessage()) return false; - input->PopLimit(limit); - input->DecrementRecursionDepth(); - return true; -} - -template -inline bool WireFormat::ReadGroupNoVirtual(int field_number, - io::CodedInputStream* input, - MessageType* value) { - if (!input->IncrementRecursionDepth()) return false; - if (!value->MessageType::MergePartialFromCodedStream(input)) return false; - input->DecrementRecursionDepth(); - // Make sure the last thing read was an end tag for this group. - if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { - return false; - } - return true; -} -template -inline bool WireFormat::ReadMessageNoVirtual(io::CodedInputStream* input, - MessageType* value) { - uint32 length; - if (!input->ReadVarint32(&length)) return false; - if (!input->IncrementRecursionDepth()) return false; - io::CodedInputStream::Limit limit = input->PushLimit(length); - if (!value->MessageType::MergePartialFromCodedStream(input)) return false; - // Make sure that parsing stopped when the limit was hit, not at an endgroup - // tag. - if (!input->ConsumedEntireMessage()) return false; - input->PopLimit(limit); - input->DecrementRecursionDepth(); - return true; -} - -// =================================================================== - -inline void WireFormat::WriteTag(int field_number, WireType type, - io::CodedOutputStream* output) { - output->WriteTag(MakeTag(field_number, type)); -} - -inline void WireFormat::WriteInt32NoTag(int32 value, - io::CodedOutputStream* output) { - output->WriteVarint32SignExtended(value); -} -inline void WireFormat::WriteInt64NoTag(int64 value, - io::CodedOutputStream* output) { - output->WriteVarint64(static_cast(value)); -} -inline void WireFormat::WriteUInt32NoTag(uint32 value, - io::CodedOutputStream* output) { - output->WriteVarint32(value); -} -inline void WireFormat::WriteUInt64NoTag(uint64 value, - io::CodedOutputStream* output) { - output->WriteVarint64(value); -} -inline void WireFormat::WriteSInt32NoTag(int32 value, - io::CodedOutputStream* output) { - output->WriteVarint32(ZigZagEncode32(value)); -} -inline void WireFormat::WriteSInt64NoTag(int64 value, - io::CodedOutputStream* output) { - output->WriteVarint64(ZigZagEncode64(value)); -} -inline void WireFormat::WriteFixed32NoTag(uint32 value, - io::CodedOutputStream* output) { - output->WriteLittleEndian32(value); -} -inline void WireFormat::WriteFixed64NoTag(uint64 value, - io::CodedOutputStream* output) { - output->WriteLittleEndian64(value); -} -inline void WireFormat::WriteSFixed32NoTag(int32 value, - io::CodedOutputStream* output) { - output->WriteLittleEndian32(static_cast(value)); -} -inline void WireFormat::WriteSFixed64NoTag(int64 value, - io::CodedOutputStream* output) { - output->WriteLittleEndian64(static_cast(value)); -} -inline void WireFormat::WriteFloatNoTag(float value, - io::CodedOutputStream* output) { - output->WriteLittleEndian32(EncodeFloat(value)); -} -inline void WireFormat::WriteDoubleNoTag(double value, - io::CodedOutputStream* output) { - output->WriteLittleEndian64(EncodeDouble(value)); -} -inline void WireFormat::WriteBoolNoTag(bool value, - io::CodedOutputStream* output) { - output->WriteVarint32(value ? 1 : 0); -} -inline void WireFormat::WriteEnumNoTag(int value, - io::CodedOutputStream* output) { - output->WriteVarint32SignExtended(value); -} - -inline void WireFormat::WriteInt32(int field_number, int32 value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_VARINT, output); - WriteInt32NoTag(value, output); -} -inline void WireFormat::WriteInt64(int field_number, int64 value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_VARINT, output); - WriteInt64NoTag(value, output); -} -inline void WireFormat::WriteUInt32(int field_number, uint32 value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_VARINT, output); - WriteUInt32NoTag(value, output); -} -inline void WireFormat::WriteUInt64(int field_number, uint64 value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_VARINT, output); - WriteUInt64NoTag(value, output); -} -inline void WireFormat::WriteSInt32(int field_number, int32 value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_VARINT, output); - WriteSInt32NoTag(value, output); -} -inline void WireFormat::WriteSInt64(int field_number, int64 value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_VARINT, output); - WriteSInt64NoTag(value, output); -} -inline void WireFormat::WriteFixed32(int field_number, uint32 value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_FIXED32, output); - WriteFixed32NoTag(value, output); -} -inline void WireFormat::WriteFixed64(int field_number, uint64 value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_FIXED64, output); - WriteFixed64NoTag(value, output); -} -inline void WireFormat::WriteSFixed32(int field_number, int32 value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_FIXED32, output); - WriteSFixed32NoTag(value, output); -} -inline void WireFormat::WriteSFixed64(int field_number, int64 value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_FIXED64, output); - WriteSFixed64NoTag(value, output); -} -inline void WireFormat::WriteFloat(int field_number, float value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_FIXED32, output); - WriteFloatNoTag(value, output); -} -inline void WireFormat::WriteDouble(int field_number, double value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_FIXED64, output); - WriteDoubleNoTag(value, output); -} -inline void WireFormat::WriteBool(int field_number, bool value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_VARINT, output); - WriteBoolNoTag(value, output); -} -inline void WireFormat::WriteEnum(int field_number, int value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_VARINT, output); - WriteEnumNoTag(value, output); -} - -inline void WireFormat::WriteString(int field_number, const string& value, - io::CodedOutputStream* output) { - // String is for UTF-8 text only -#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED - if (!IsStructurallyValidUTF8(value.data(), value.size())) { - GOOGLE_LOG(ERROR) << "Encountered string containing invalid UTF-8 data while " - "serializing protocol buffer. Strings must contain only UTF-8; " - "use the 'bytes' type for raw bytes."; - } -#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED - WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(value.size()); - output->WriteString(value); -} -inline void WireFormat::WriteBytes(int field_number, const string& value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(value.size()); - output->WriteString(value); -} - - -inline void WireFormat::WriteGroup(int field_number, const Message& value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_START_GROUP, output); - value.SerializeWithCachedSizes(output); - WriteTag(field_number, WIRETYPE_END_GROUP, output); -} -inline void WireFormat::WriteMessage(int field_number, const Message& value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(value.GetCachedSize()); - value.SerializeWithCachedSizes(output); -} - -template -inline void WireFormat::WriteGroupNoVirtual( - int field_number, const MessageType& value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_START_GROUP, output); - value.MessageType::SerializeWithCachedSizes(output); - WriteTag(field_number, WIRETYPE_END_GROUP, output); -} -template -inline void WireFormat::WriteMessageNoVirtual( - int field_number, const MessageType& value, - io::CodedOutputStream* output) { - WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(value.MessageType::GetCachedSize()); - value.MessageType::SerializeWithCachedSizes(output); -} - -// =================================================================== - -inline uint8* WireFormat::WriteTagToArray(int field_number, - WireType type, - uint8* target) { - return io::CodedOutputStream::WriteTagToArray(MakeTag(field_number, type), - target); -} - -inline uint8* WireFormat::WriteInt32NoTagToArray(int32 value, uint8* target) { - return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target); -} -inline uint8* WireFormat::WriteInt64NoTagToArray(int64 value, uint8* target) { - return io::CodedOutputStream::WriteVarint64ToArray( - static_cast(value), target); -} -inline uint8* WireFormat::WriteUInt32NoTagToArray(uint32 value, uint8* target) { - return io::CodedOutputStream::WriteVarint32ToArray(value, target); -} -inline uint8* WireFormat::WriteUInt64NoTagToArray(uint64 value, uint8* target) { - return io::CodedOutputStream::WriteVarint64ToArray(value, target); -} -inline uint8* WireFormat::WriteSInt32NoTagToArray(int32 value, uint8* target) { - return io::CodedOutputStream::WriteVarint32ToArray(ZigZagEncode32(value), - target); -} -inline uint8* WireFormat::WriteSInt64NoTagToArray(int64 value, uint8* target) { - return io::CodedOutputStream::WriteVarint64ToArray(ZigZagEncode64(value), - target); -} -inline uint8* WireFormat::WriteFixed32NoTagToArray(uint32 value, - uint8* target) { - return io::CodedOutputStream::WriteLittleEndian32ToArray(value, target); -} -inline uint8* WireFormat::WriteFixed64NoTagToArray(uint64 value, - uint8* target) { - return io::CodedOutputStream::WriteLittleEndian64ToArray(value, target); -} -inline uint8* WireFormat::WriteSFixed32NoTagToArray(int32 value, - uint8* target) { - return io::CodedOutputStream::WriteLittleEndian32ToArray( - static_cast(value), target); -} -inline uint8* WireFormat::WriteSFixed64NoTagToArray(int64 value, - uint8* target) { - return io::CodedOutputStream::WriteLittleEndian64ToArray( - static_cast(value), target); -} -inline uint8* WireFormat::WriteFloatNoTagToArray(float value, uint8* target) { - return io::CodedOutputStream::WriteLittleEndian32ToArray(EncodeFloat(value), - target); -} -inline uint8* WireFormat::WriteDoubleNoTagToArray(double value, - uint8* target) { - return io::CodedOutputStream::WriteLittleEndian64ToArray(EncodeDouble(value), - target); -} -inline uint8* WireFormat::WriteBoolNoTagToArray(bool value, - uint8* target) { - return io::CodedOutputStream::WriteVarint32ToArray(value ? 1 : 0, target); -} -inline uint8* WireFormat::WriteEnumNoTagToArray(int value, - uint8* target) { - return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target); -} - -inline uint8* WireFormat::WriteInt32ToArray(int field_number, - int32 value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); - return WriteInt32NoTagToArray(value, target); -} -inline uint8* WireFormat::WriteInt64ToArray(int field_number, - int64 value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); - return WriteInt64NoTagToArray(value, target); -} -inline uint8* WireFormat::WriteUInt32ToArray(int field_number, - uint32 value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); - return WriteUInt32NoTagToArray(value, target); -} -inline uint8* WireFormat::WriteUInt64ToArray(int field_number, - uint64 value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); - return WriteUInt64NoTagToArray(value, target); -} -inline uint8* WireFormat::WriteSInt32ToArray(int field_number, - int32 value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); - return WriteSInt32NoTagToArray(value, target); -} -inline uint8* WireFormat::WriteSInt64ToArray(int field_number, - int64 value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); - return WriteSInt64NoTagToArray(value, target); -} -inline uint8* WireFormat::WriteFixed32ToArray(int field_number, - uint32 value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); - return WriteFixed32NoTagToArray(value, target); -} -inline uint8* WireFormat::WriteFixed64ToArray(int field_number, - uint64 value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); - return WriteFixed64NoTagToArray(value, target); -} -inline uint8* WireFormat::WriteSFixed32ToArray(int field_number, - int32 value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); - return WriteSFixed32NoTagToArray(value, target); -} -inline uint8* WireFormat::WriteSFixed64ToArray(int field_number, - int64 value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); - return WriteSFixed64NoTagToArray(value, target); -} -inline uint8* WireFormat::WriteFloatToArray(int field_number, - float value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); - return WriteFloatNoTagToArray(value, target); -} -inline uint8* WireFormat::WriteDoubleToArray(int field_number, - double value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); - return WriteDoubleNoTagToArray(value, target); -} -inline uint8* WireFormat::WriteBoolToArray(int field_number, - bool value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); - return WriteBoolNoTagToArray(value, target); -} -inline uint8* WireFormat::WriteEnumToArray(int field_number, - int value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); - return WriteEnumNoTagToArray(value, target); -} - -inline uint8* WireFormat::WriteStringToArray(int field_number, - const string& value, - uint8* target) { - // String is for UTF-8 text only -#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED - if (!IsStructurallyValidUTF8(value.data(), value.size())) { - GOOGLE_LOG(ERROR) << "Encountered string containing invalid UTF-8 data while " - "serializing protocol buffer. Strings must contain only UTF-8; " - "use the 'bytes' type for raw bytes."; - } -#endif - // WARNING: In wire_format.cc, both strings and bytes are handled by - // WriteString() to avoid code duplication. If the implementations become - // different, you will need to update that usage. - target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); - target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target); - return io::CodedOutputStream::WriteStringToArray(value, target); -} -inline uint8* WireFormat::WriteBytesToArray(int field_number, - const string& value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); - target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target); - return io::CodedOutputStream::WriteStringToArray(value, target); -} - - -inline uint8* WireFormat::WriteGroupToArray(int field_number, - const Message& value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); - target = value.SerializeWithCachedSizesToArray(target); - return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); -} -inline uint8* WireFormat::WriteMessageToArray(int field_number, - const Message& value, - uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); - target = io::CodedOutputStream::WriteVarint32ToArray( - value.GetCachedSize(), target); - return value.SerializeWithCachedSizesToArray(target); -} - -template -inline uint8* WireFormat::WriteGroupNoVirtualToArray( - int field_number, const MessageType& value, uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); - target = value.MessageType::SerializeWithCachedSizesToArray(target); - return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); -} -template -inline uint8* WireFormat::WriteMessageNoVirtualToArray( - int field_number, const MessageType& value, uint8* target) { - target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); - target = io::CodedOutputStream::WriteVarint32ToArray( - value.MessageType::GetCachedSize(), target); - return value.MessageType::SerializeWithCachedSizesToArray(target); -} - -// =================================================================== - -inline int WireFormat::TagSize(int field_number, FieldDescriptor::Type type) { - int result = io::CodedOutputStream::VarintSize32( - field_number << kTagTypeBits); - if (type == FieldDescriptor::TYPE_GROUP) { - // Groups have both a start and an end tag. - return result * 2; - } else { - return result; - } -} - -inline int WireFormat::Int32Size(int32 value) { - return io::CodedOutputStream::VarintSize32SignExtended(value); -} -inline int WireFormat::Int64Size(int64 value) { - return io::CodedOutputStream::VarintSize64(static_cast(value)); -} -inline int WireFormat::UInt32Size(uint32 value) { - return io::CodedOutputStream::VarintSize32(value); -} -inline int WireFormat::UInt64Size(uint64 value) { - return io::CodedOutputStream::VarintSize64(value); -} -inline int WireFormat::SInt32Size(int32 value) { - return io::CodedOutputStream::VarintSize32(ZigZagEncode32(value)); -} -inline int WireFormat::SInt64Size(int64 value) { - return io::CodedOutputStream::VarintSize64(ZigZagEncode64(value)); -} -inline int WireFormat::EnumSize(int value) { - return io::CodedOutputStream::VarintSize32SignExtended(value); -} - -inline int WireFormat::StringSize(const string& value) { - return io::CodedOutputStream::VarintSize32(value.size()) + - value.size(); -} -inline int WireFormat::BytesSize(const string& value) { - return io::CodedOutputStream::VarintSize32(value.size()) + - value.size(); -} - - -inline int WireFormat::GroupSize(const Message& value) { - return value.ByteSize(); -} -inline int WireFormat::MessageSize(const Message& value) { - int size = value.ByteSize(); - return io::CodedOutputStream::VarintSize32(size) + size; -} - -template -inline int WireFormat::GroupSizeNoVirtual(const MessageType& value) { - return value.MessageType::ByteSize(); -} -template -inline int WireFormat::MessageSizeNoVirtual(const MessageType& value) { - int size = value.MessageType::ByteSize(); - return io::CodedOutputStream::VarintSize32(size) + size; -} - -} // namespace internal -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_INL_H__ diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc new file mode 100644 index 00000000..bbbf5236 --- /dev/null +++ b/src/google/protobuf/wire_format_lite.cc @@ -0,0 +1,193 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +#ifndef _MSC_VER // MSVC doesn't like definitions of inline constants, GCC + // requires them. +const int WireFormatLite::kMessageSetItemStartTag; +const int WireFormatLite::kMessageSetItemEndTag; +const int WireFormatLite::kMessageSetTypeIdTag; +const int WireFormatLite::kMessageSetMessageTag; + +#endif + +const int WireFormatLite::kMessageSetItemTagsSize = + io::CodedOutputStream::VarintSize32(kMessageSetItemStartTag) + + io::CodedOutputStream::VarintSize32(kMessageSetItemEndTag) + + io::CodedOutputStream::VarintSize32(kMessageSetTypeIdTag) + + io::CodedOutputStream::VarintSize32(kMessageSetMessageTag); + +const WireFormatLite::CppType +WireFormatLite::kFieldTypeToCppTypeMap[MAX_FIELD_TYPE + 1] = { + static_cast(0), // 0 is reserved for errors + + CPPTYPE_DOUBLE, // TYPE_DOUBLE + CPPTYPE_FLOAT, // TYPE_FLOAT + CPPTYPE_INT64, // TYPE_INT64 + CPPTYPE_UINT64, // TYPE_UINT64 + CPPTYPE_INT32, // TYPE_INT32 + CPPTYPE_UINT64, // TYPE_FIXED64 + CPPTYPE_UINT32, // TYPE_FIXED32 + CPPTYPE_BOOL, // TYPE_BOOL + CPPTYPE_STRING, // TYPE_STRING + CPPTYPE_MESSAGE, // TYPE_GROUP + CPPTYPE_MESSAGE, // TYPE_MESSAGE + CPPTYPE_STRING, // TYPE_BYTES + CPPTYPE_UINT32, // TYPE_UINT32 + CPPTYPE_ENUM, // TYPE_ENUM + CPPTYPE_INT32, // TYPE_SFIXED32 + CPPTYPE_INT64, // TYPE_SFIXED64 + CPPTYPE_INT32, // TYPE_SINT32 + CPPTYPE_INT64, // TYPE_SINT64 +}; + +const WireFormatLite::WireType +WireFormatLite::kWireTypeForFieldType[MAX_FIELD_TYPE + 1] = { + static_cast(-1), // invalid + WireFormatLite::WIRETYPE_FIXED64, // TYPE_DOUBLE + WireFormatLite::WIRETYPE_FIXED32, // TYPE_FLOAT + WireFormatLite::WIRETYPE_VARINT, // TYPE_INT64 + WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT64 + WireFormatLite::WIRETYPE_VARINT, // TYPE_INT32 + WireFormatLite::WIRETYPE_FIXED64, // TYPE_FIXED64 + WireFormatLite::WIRETYPE_FIXED32, // TYPE_FIXED32 + WireFormatLite::WIRETYPE_VARINT, // TYPE_BOOL + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_STRING + WireFormatLite::WIRETYPE_START_GROUP, // TYPE_GROUP + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_MESSAGE + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_BYTES + WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT32 + WireFormatLite::WIRETYPE_VARINT, // TYPE_ENUM + WireFormatLite::WIRETYPE_FIXED32, // TYPE_SFIXED32 + WireFormatLite::WIRETYPE_FIXED64, // TYPE_SFIXED64 + WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT32 + WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT64 +}; + +bool WireFormatLite::SkipField( + io::CodedInputStream* input, uint32 tag) { + switch (WireFormatLite::GetTagWireType(tag)) { + case WireFormatLite::WIRETYPE_VARINT: { + uint64 value; + if (!input->ReadVarint64(&value)) return false; + return true; + } + case WireFormatLite::WIRETYPE_FIXED64: { + uint64 value; + if (!input->ReadLittleEndian64(&value)) return false; + return true; + } + case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (!input->Skip(length)) return false; + return true; + } + case WireFormatLite::WIRETYPE_START_GROUP: { + if (!input->IncrementRecursionDepth()) return false; + if (!SkipMessage(input)) return false; + input->DecrementRecursionDepth(); + // Check that the ending tag matched the starting tag. + if (!input->LastTagWas(WireFormatLite::MakeTag( + WireFormatLite::GetTagFieldNumber(tag), + WireFormatLite::WIRETYPE_END_GROUP))) { + return false; + } + return true; + } + case WireFormatLite::WIRETYPE_END_GROUP: { + return false; + } + case WireFormatLite::WIRETYPE_FIXED32: { + uint32 value; + if (!input->ReadLittleEndian32(&value)) return false; + return true; + } + default: { + return false; + } + } +} + +bool WireFormatLite::SkipMessage(io::CodedInputStream* input) { + while(true) { + uint32 tag = input->ReadTag(); + if (tag == 0) { + // End of input. This is a valid place to end, so return true. + return true; + } + + WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); + + if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) { + // Must be the end of the message. + return true; + } + + if (!SkipField(input, tag)) return false; + } +} + +bool FieldSkipper::SkipField( + io::CodedInputStream* input, uint32 tag) { + return WireFormatLite::SkipField(input, tag); +} + +bool FieldSkipper::SkipMessage(io::CodedInputStream* input) { + return WireFormatLite::SkipMessage(input); +} + +void FieldSkipper::SkipUnknownEnum( + int field_number, int value) { + // Nothing. +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h new file mode 100644 index 00000000..9b7a4010 --- /dev/null +++ b/src/google/protobuf/wire_format_lite.h @@ -0,0 +1,558 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// atenasio@google.com (Chris Atenasio) (ZigZag transform) +// wink@google.com (Wink Saville) (refactored from wire_format.h) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This header is logically internal, but is made public because it is used +// from protocol-compiler-generated code, which may reside in other components. + +#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__ +#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__ + +#include +#include + +namespace google { + +namespace protobuf { + namespace io { + class CodedInputStream; // coded_stream.h + class CodedOutputStream; // coded_stream.h + } +} + +namespace protobuf { +namespace internal { + +// This class is for internal use by the protocol buffer library and by +// protocol-complier-generated message classes. It must not be called +// directly by clients. +// +// This class contains helpers for implementing the binary protocol buffer +// wire format without the need for reflection. Use WireFormat when using +// reflection. +// +// This class is really a namespace that contains only static methods. +class LIBPROTOBUF_EXPORT WireFormatLite { + public: + + // ----------------------------------------------------------------- + // Helper constants and functions related to the format. These are + // mostly meant for internal and generated code to use. + + // The wire format is composed of a sequence of tag/value pairs, each + // of which contains the value of one field (or one element of a repeated + // field). Each tag is encoded as a varint. The lower bits of the tag + // identify its wire type, which specifies the format of the data to follow. + // The rest of the bits contain the field number. Each type of field (as + // declared by FieldDescriptor::Type, in descriptor.h) maps to one of + // these wire types. Immediately following each tag is the field's value, + // encoded in the format specified by the wire type. Because the tag + // identifies the encoding of this data, it is possible to skip + // unrecognized fields for forwards compatibility. + + enum WireType { + WIRETYPE_VARINT = 0, + WIRETYPE_FIXED64 = 1, + WIRETYPE_LENGTH_DELIMITED = 2, + WIRETYPE_START_GROUP = 3, + WIRETYPE_END_GROUP = 4, + WIRETYPE_FIXED32 = 5, + }; + + // Lite alternative to FieldDescriptor::Type. Must be kept in sync. + enum FieldType { + TYPE_DOUBLE = 1, + TYPE_FLOAT = 2, + TYPE_INT64 = 3, + TYPE_UINT64 = 4, + TYPE_INT32 = 5, + TYPE_FIXED64 = 6, + TYPE_FIXED32 = 7, + TYPE_BOOL = 8, + TYPE_STRING = 9, + TYPE_GROUP = 10, + TYPE_MESSAGE = 11, + TYPE_BYTES = 12, + TYPE_UINT32 = 13, + TYPE_ENUM = 14, + TYPE_SFIXED32 = 15, + TYPE_SFIXED64 = 16, + TYPE_SINT32 = 17, + TYPE_SINT64 = 18, + MAX_FIELD_TYPE = 18, + }; + + // Lite alternative to FieldDescriptor::CppType. Must be kept in sync. + enum CppType { + CPPTYPE_INT32 = 1, + CPPTYPE_INT64 = 2, + CPPTYPE_UINT32 = 3, + CPPTYPE_UINT64 = 4, + CPPTYPE_DOUBLE = 5, + CPPTYPE_FLOAT = 6, + CPPTYPE_BOOL = 7, + CPPTYPE_ENUM = 8, + CPPTYPE_STRING = 9, + CPPTYPE_MESSAGE = 10, + MAX_CPPTYPE = 10, + }; + + // Helper method to get the CppType for a particular Type. + static CppType FieldTypeToCppType(FieldType type); + + // Given a FieldSescriptor::Type return its WireType + static inline WireFormatLite::WireType WireTypeForFieldType( + WireFormatLite::FieldType type) { + return kWireTypeForFieldType[type]; + } + + // Number of bits in a tag which identify the wire type. + static const int kTagTypeBits = 3; + // Mask for those bits. + static const uint32 kTagTypeMask = (1 << kTagTypeBits) - 1; + + // Helper functions for encoding and decoding tags. (Inlined below and in + // _inl.h) + // + // This is different from MakeTag(field->number(), field->type()) in the case + // of packed repeated fields. + static uint32 MakeTag(int field_number, WireType type); + static WireType GetTagWireType(uint32 tag); + static int GetTagFieldNumber(uint32 tag); + + // Compute the byte size of a tag. For groups, this includes both the start + // and end tags. + static inline int TagSize(int field_number, WireFormatLite::FieldType type); + + // Skips a field value with the given tag. The input should start + // positioned immediately after the tag. Skipped values are simply discarded, + // not recorded anywhere. See WireFormat::SkipField() for a version that + // records to an UnknownFieldSet. + static bool SkipField(io::CodedInputStream* input, uint32 tag); + + // Reads and ignores a message from the input. Skipped values are simply + // discarded, not recorded anywhere. See WireFormat::SkipMessage() for a + // version that records to an UnknownFieldSet. + static bool SkipMessage(io::CodedInputStream* input); + +// This macro does the same thing as WireFormatLite::MakeTag(), but the +// result is usable as a compile-time constant, which makes it usable +// as a switch case or a template input. WireFormatLite::MakeTag() is more +// type-safe, though, so prefer it if possible. +#define GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(FIELD_NUMBER, TYPE) \ + static_cast( \ + ((FIELD_NUMBER) << ::google::protobuf::internal::WireFormatLite::kTagTypeBits) \ + | (TYPE)) + + // These are the tags for the old MessageSet format, which was defined as: + // message MessageSet { + // repeated group Item = 1 { + // required int32 type_id = 2; + // required string message = 3; + // } + // } + static const int kMessageSetItemStartTag = + GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(1, WireFormatLite::WIRETYPE_START_GROUP); + static const int kMessageSetItemEndTag = + GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(1, WireFormatLite::WIRETYPE_END_GROUP); + static const int kMessageSetTypeIdTag = + GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(2, WireFormatLite::WIRETYPE_VARINT); + static const int kMessageSetMessageTag = + GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(3, WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + + // Byte size of all tags of a MessageSet::Item combined. + static const int kMessageSetItemTagsSize; + + // Helper functions for converting between floats/doubles and IEEE-754 + // uint32s/uint64s so that they can be written. (Assumes your platform + // uses IEEE-754 floats.) + static uint32 EncodeFloat(float value); + static float DecodeFloat(uint32 value); + static uint64 EncodeDouble(double value); + static double DecodeDouble(uint64 value); + + // Helper functions for mapping signed integers to unsigned integers in + // such a way that numbers with small magnitudes will encode to smaller + // varints. If you simply static_cast a negative number to an unsigned + // number and varint-encode it, it will always take 10 bytes, defeating + // the purpose of varint. So, for the "sint32" and "sint64" field types, + // we ZigZag-encode the values. + static uint32 ZigZagEncode32(int32 n); + static int32 ZigZagDecode32(uint32 n); + static uint64 ZigZagEncode64(int64 n); + static int64 ZigZagDecode64(uint64 n); + + // ================================================================= + // Methods for reading/writing individual field. The implementations + // of these methods are defined in wire_format_lite_inl.h; you must #include + // that file to use these. + +// Avoid ugly line wrapping +#define input io::CodedInputStream* input +#define output io::CodedOutputStream* output +#define field_number int field_number +#define INL GOOGLE_ATTRIBUTE_ALWAYS_INLINE + + // Read fields, not including tags. The assumption is that you already + // read the tag to determine what field to read. + static inline bool ReadInt32 (input, int32* value); + static inline bool ReadInt64 (input, int64* value); + static inline bool ReadUInt32 (input, uint32* value); + static inline bool ReadUInt64 (input, uint64* value); + static inline bool ReadSInt32 (input, int32* value); + static inline bool ReadSInt64 (input, int64* value); + static inline bool ReadFixed32 (input, uint32* value); + static inline bool ReadFixed64 (input, uint64* value); + static inline bool ReadSFixed32(input, int32* value); + static inline bool ReadSFixed64(input, int64* value); + static inline bool ReadFloat (input, float* value); + static inline bool ReadDouble (input, double* value); + static inline bool ReadBool (input, bool* value); + static inline bool ReadEnum (input, int* value); + + static inline bool ReadString(input, string* value); + static inline bool ReadBytes (input, string* value); + + static inline bool ReadGroup (field_number, input, MessageLite* value); + static inline bool ReadMessage(input, MessageLite* value); + + // Like above, but de-virtualize the call to MergePartialFromCodedStream(). + // The pointer must point at an instance of MessageType, *not* a subclass (or + // the subclass must not override MergePartialFromCodedStream()). + template + static inline bool ReadGroupNoVirtual(field_number, input, + MessageType* value); + template + static inline bool ReadMessageNoVirtual(input, MessageType* value); + + // Write a tag. The Write*() functions typically include the tag, so + // normally there's no need to call this unless using the Write*NoTag() + // variants. + static inline void WriteTag(field_number, WireType type, output) INL; + + // Write fields, without tags. + static inline void WriteInt32NoTag (int32 value, output) INL; + static inline void WriteInt64NoTag (int64 value, output) INL; + static inline void WriteUInt32NoTag (uint32 value, output) INL; + static inline void WriteUInt64NoTag (uint64 value, output) INL; + static inline void WriteSInt32NoTag (int32 value, output) INL; + static inline void WriteSInt64NoTag (int64 value, output) INL; + static inline void WriteFixed32NoTag (uint32 value, output) INL; + static inline void WriteFixed64NoTag (uint64 value, output) INL; + static inline void WriteSFixed32NoTag(int32 value, output) INL; + static inline void WriteSFixed64NoTag(int64 value, output) INL; + static inline void WriteFloatNoTag (float value, output) INL; + static inline void WriteDoubleNoTag (double value, output) INL; + static inline void WriteBoolNoTag (bool value, output) INL; + static inline void WriteEnumNoTag (int value, output) INL; + + // Write fields, including tags. + static inline void WriteInt32 (field_number, int32 value, output) INL; + static inline void WriteInt64 (field_number, int64 value, output) INL; + static inline void WriteUInt32 (field_number, uint32 value, output) INL; + static inline void WriteUInt64 (field_number, uint64 value, output) INL; + static inline void WriteSInt32 (field_number, int32 value, output) INL; + static inline void WriteSInt64 (field_number, int64 value, output) INL; + static inline void WriteFixed32 (field_number, uint32 value, output) INL; + static inline void WriteFixed64 (field_number, uint64 value, output) INL; + static inline void WriteSFixed32(field_number, int32 value, output) INL; + static inline void WriteSFixed64(field_number, int64 value, output) INL; + static inline void WriteFloat (field_number, float value, output) INL; + static inline void WriteDouble (field_number, double value, output) INL; + static inline void WriteBool (field_number, bool value, output) INL; + static inline void WriteEnum (field_number, int value, output) INL; + + static inline void WriteString(field_number, const string& value, output) INL; + static inline void WriteBytes (field_number, const string& value, output) INL; + + static inline void WriteGroup( + field_number, const MessageLite& value, output) INL; + static inline void WriteMessage( + field_number, const MessageLite& value, output) INL; + + // Like above, but de-virtualize the call to SerializeWithCachedSizes(). The + // pointer must point at an instance of MessageType, *not* a subclass (or + // the subclass must not override SerializeWithCachedSizes()). + template + static inline void WriteGroupNoVirtual( + field_number, const MessageType& value, output) INL; + template + static inline void WriteMessageNoVirtual( + field_number, const MessageType& value, output) INL; + +#undef output +#define output uint8* target + + // Like above, but use only *ToArray methods of CodedOutputStream. + static inline uint8* WriteTagToArray(field_number, WireType type, output) INL; + + // Write fields, without tags. + static inline uint8* WriteInt32NoTagToArray (int32 value, output) INL; + static inline uint8* WriteInt64NoTagToArray (int64 value, output) INL; + static inline uint8* WriteUInt32NoTagToArray (uint32 value, output) INL; + static inline uint8* WriteUInt64NoTagToArray (uint64 value, output) INL; + static inline uint8* WriteSInt32NoTagToArray (int32 value, output) INL; + static inline uint8* WriteSInt64NoTagToArray (int64 value, output) INL; + static inline uint8* WriteFixed32NoTagToArray (uint32 value, output) INL; + static inline uint8* WriteFixed64NoTagToArray (uint64 value, output) INL; + static inline uint8* WriteSFixed32NoTagToArray(int32 value, output) INL; + static inline uint8* WriteSFixed64NoTagToArray(int64 value, output) INL; + static inline uint8* WriteFloatNoTagToArray (float value, output) INL; + static inline uint8* WriteDoubleNoTagToArray (double value, output) INL; + static inline uint8* WriteBoolNoTagToArray (bool value, output) INL; + static inline uint8* WriteEnumNoTagToArray (int value, output) INL; + + // Write fields, including tags. + static inline uint8* WriteInt32ToArray( + field_number, int32 value, output) INL; + static inline uint8* WriteInt64ToArray( + field_number, int64 value, output) INL; + static inline uint8* WriteUInt32ToArray( + field_number, uint32 value, output) INL; + static inline uint8* WriteUInt64ToArray( + field_number, uint64 value, output) INL; + static inline uint8* WriteSInt32ToArray( + field_number, int32 value, output) INL; + static inline uint8* WriteSInt64ToArray( + field_number, int64 value, output) INL; + static inline uint8* WriteFixed32ToArray( + field_number, uint32 value, output) INL; + static inline uint8* WriteFixed64ToArray( + field_number, uint64 value, output) INL; + static inline uint8* WriteSFixed32ToArray( + field_number, int32 value, output) INL; + static inline uint8* WriteSFixed64ToArray( + field_number, int64 value, output) INL; + static inline uint8* WriteFloatToArray( + field_number, float value, output) INL; + static inline uint8* WriteDoubleToArray( + field_number, double value, output) INL; + static inline uint8* WriteBoolToArray( + field_number, bool value, output) INL; + static inline uint8* WriteEnumToArray( + field_number, int value, output) INL; + + static inline uint8* WriteStringToArray( + field_number, const string& value, output) INL; + static inline uint8* WriteBytesToArray( + field_number, const string& value, output) INL; + + static inline uint8* WriteGroupToArray( + field_number, const MessageLite& value, output) INL; + static inline uint8* WriteMessageToArray( + field_number, const MessageLite& value, output) INL; + + // Like above, but de-virtualize the call to SerializeWithCachedSizes(). The + // pointer must point at an instance of MessageType, *not* a subclass (or + // the subclass must not override SerializeWithCachedSizes()). + template + static inline uint8* WriteGroupNoVirtualToArray( + field_number, const MessageType& value, output) INL; + template + static inline uint8* WriteMessageNoVirtualToArray( + field_number, const MessageType& value, output) INL; + +#undef output +#undef input +#undef INL + +#undef field_number + + // Compute the byte size of a field. The XxSize() functions do NOT include + // the tag, so you must also call TagSize(). (This is because, for repeated + // fields, you should only call TagSize() once and multiply it by the element + // count, but you may have to call XxSize() for each individual element.) + static inline int Int32Size ( int32 value); + static inline int Int64Size ( int64 value); + static inline int UInt32Size (uint32 value); + static inline int UInt64Size (uint64 value); + static inline int SInt32Size ( int32 value); + static inline int SInt64Size ( int64 value); + static inline int EnumSize ( int value); + + // These types always have the same size. + static const int kFixed32Size = 4; + static const int kFixed64Size = 8; + static const int kSFixed32Size = 4; + static const int kSFixed64Size = 8; + static const int kFloatSize = 4; + static const int kDoubleSize = 8; + static const int kBoolSize = 1; + + static inline int StringSize(const string& value); + static inline int BytesSize (const string& value); + + static inline int GroupSize (const MessageLite& value); + static inline int MessageSize(const MessageLite& value); + + // Like above, but de-virtualize the call to ByteSize(). The + // pointer must point at an instance of MessageType, *not* a subclass (or + // the subclass must not override ByteSize()). + template + static inline int GroupSizeNoVirtual (const MessageType& value); + template + static inline int MessageSizeNoVirtual(const MessageType& value); + + private: + static const CppType kFieldTypeToCppTypeMap[]; + static const WireFormatLite::WireType kWireTypeForFieldType[]; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormatLite); +}; + +// A class which deals with unknown values. The default implementation just +// discards them. WireFormat defines a subclass which writes to an +// UnknownFieldSet. This class is used by ExtensionSet::ParseField(), since +// ExtensionSet is part of the lite library but UnknownFieldSet is not. +class LIBPROTOBUF_EXPORT FieldSkipper { + public: + FieldSkipper() {} + virtual ~FieldSkipper() {} + + // Skip a field whose tag has already been consumed. + virtual bool SkipField(io::CodedInputStream* input, uint32 tag); + + // Skip an entire message or group, up to an end-group tag (which is consumed) + // or end-of-stream. + virtual bool SkipMessage(io::CodedInputStream* input); + + // Deal with an already-parsed unrecognized enum value. The default + // implementation does nothing, but the UnknownFieldSet-based implementation + // saves it as an unknown varint. + virtual void SkipUnknownEnum(int field_number, int value); +}; + +// inline methods ==================================================== + +inline WireFormatLite::CppType +WireFormatLite::FieldTypeToCppType(FieldType type) { + return kFieldTypeToCppTypeMap[type]; +} + +inline uint32 WireFormatLite::MakeTag(int field_number, WireType type) { + return GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(field_number, type); +} + +inline WireFormatLite::WireType WireFormatLite::GetTagWireType(uint32 tag) { + return static_cast(tag & kTagTypeMask); +} + +inline int WireFormatLite::GetTagFieldNumber(uint32 tag) { + return static_cast(tag >> kTagTypeBits); +} + +inline int WireFormatLite::TagSize(int field_number, + WireFormatLite::FieldType type) { + int result = io::CodedOutputStream::VarintSize32( + field_number << kTagTypeBits); + if (type == TYPE_GROUP) { + // Groups have both a start and an end tag. + return result * 2; + } else { + return result; + } +} + +inline uint32 WireFormatLite::EncodeFloat(float value) { + union {float f; uint32 i;}; + f = value; + return i; +} + +inline float WireFormatLite::DecodeFloat(uint32 value) { + union {float f; uint32 i;}; + i = value; + return f; +} + +inline uint64 WireFormatLite::EncodeDouble(double value) { + union {double f; uint64 i;}; + f = value; + return i; +} + +inline double WireFormatLite::DecodeDouble(uint64 value) { + union {double f; uint64 i;}; + i = value; + return f; +} + +// ZigZag Transform: Encodes signed integers so that they can be +// effectively used with varint encoding. +// +// varint operates on unsigned integers, encoding smaller numbers into +// fewer bytes. If you try to use it on a signed integer, it will treat +// this number as a very large unsigned integer, which means that even +// small signed numbers like -1 will take the maximum number of bytes +// (10) to encode. ZigZagEncode() maps signed integers to unsigned +// in such a way that those with a small absolute value will have smaller +// encoded values, making them appropriate for encoding using varint. +// +// int32 -> uint32 +// ------------------------- +// 0 -> 0 +// -1 -> 1 +// 1 -> 2 +// -2 -> 3 +// ... -> ... +// 2147483647 -> 4294967294 +// -2147483648 -> 4294967295 +// +// >> encode >> +// << decode << + +inline uint32 WireFormatLite::ZigZagEncode32(int32 n) { + // Note: the right-shift must be arithmetic + return (n << 1) ^ (n >> 31); +} + +inline int32 WireFormatLite::ZigZagDecode32(uint32 n) { + return (n >> 1) ^ -static_cast(n & 1); +} + +inline uint64 WireFormatLite::ZigZagEncode64(int64 n) { + // Note: the right-shift must be arithmetic + return (n << 1) ^ (n >> 63); +} + +inline int64 WireFormatLite::ZigZagDecode64(uint64 n) { + return (n >> 1) ^ -static_cast(n & 1); +} + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__ diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h new file mode 100644 index 00000000..eb9155e9 --- /dev/null +++ b/src/google/protobuf/wire_format_lite_inl.h @@ -0,0 +1,657 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// wink@google.com (Wink Saville) (refactored from wire_format.h) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__ +#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__ + +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace internal { + +inline bool WireFormatLite::ReadInt32(io::CodedInputStream* input, + int32* value) { + uint32 temp; + if (!input->ReadVarint32(&temp)) return false; + *value = static_cast(temp); + return true; +} +inline bool WireFormatLite::ReadInt64(io::CodedInputStream* input, + int64* value) { + uint64 temp; + if (!input->ReadVarint64(&temp)) return false; + *value = static_cast(temp); + return true; +} +inline bool WireFormatLite::ReadUInt32(io::CodedInputStream* input, + uint32* value) { + return input->ReadVarint32(value); +} +inline bool WireFormatLite::ReadUInt64(io::CodedInputStream* input, + uint64* value) { + return input->ReadVarint64(value); +} +inline bool WireFormatLite::ReadSInt32(io::CodedInputStream* input, + int32* value) { + uint32 temp; + if (!input->ReadVarint32(&temp)) return false; + *value = ZigZagDecode32(temp); + return true; +} +inline bool WireFormatLite::ReadSInt64(io::CodedInputStream* input, + int64* value) { + uint64 temp; + if (!input->ReadVarint64(&temp)) return false; + *value = ZigZagDecode64(temp); + return true; +} +inline bool WireFormatLite::ReadFixed32(io::CodedInputStream* input, + uint32* value) { + return input->ReadLittleEndian32(value); +} +inline bool WireFormatLite::ReadFixed64(io::CodedInputStream* input, + uint64* value) { + return input->ReadLittleEndian64(value); +} +inline bool WireFormatLite::ReadSFixed32(io::CodedInputStream* input, + int32* value) { + uint32 temp; + if (!input->ReadLittleEndian32(&temp)) return false; + *value = static_cast(temp); + return true; +} +inline bool WireFormatLite::ReadSFixed64(io::CodedInputStream* input, + int64* value) { + uint64 temp; + if (!input->ReadLittleEndian64(&temp)) return false; + *value = static_cast(temp); + return true; +} +inline bool WireFormatLite::ReadFloat(io::CodedInputStream* input, + float* value) { + uint32 temp; + if (!input->ReadLittleEndian32(&temp)) return false; + *value = DecodeFloat(temp); + return true; +} +inline bool WireFormatLite::ReadDouble(io::CodedInputStream* input, + double* value) { + uint64 temp; + if (!input->ReadLittleEndian64(&temp)) return false; + *value = DecodeDouble(temp); + return true; +} +inline bool WireFormatLite::ReadBool(io::CodedInputStream* input, + bool* value) { + uint32 temp; + if (!input->ReadVarint32(&temp)) return false; + *value = temp != 0; + return true; +} +inline bool WireFormatLite::ReadEnum(io::CodedInputStream* input, + int* value) { + uint32 temp; + if (!input->ReadVarint32(&temp)) return false; + *value = static_cast(temp); + return true; +} + +inline bool WireFormatLite::ReadString(io::CodedInputStream* input, + string* value) { + // String is for UTF-8 text only + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (!input->ReadString(value, length)) return false; + return true; +} +inline bool WireFormatLite::ReadBytes(io::CodedInputStream* input, + string* value) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + return input->ReadString(value, length); +} + + +inline bool WireFormatLite::ReadGroup(int field_number, + io::CodedInputStream* input, + MessageLite* value) { + if (!input->IncrementRecursionDepth()) return false; + if (!value->MergePartialFromCodedStream(input)) return false; + input->DecrementRecursionDepth(); + // Make sure the last thing read was an end tag for this group. + if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { + return false; + } + return true; +} +inline bool WireFormatLite::ReadMessage(io::CodedInputStream* input, + MessageLite* value) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (!input->IncrementRecursionDepth()) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + if (!value->MergePartialFromCodedStream(input)) return false; + // Make sure that parsing stopped when the limit was hit, not at an endgroup + // tag. + if (!input->ConsumedEntireMessage()) return false; + input->PopLimit(limit); + input->DecrementRecursionDepth(); + return true; +} + +template +inline bool WireFormatLite::ReadGroupNoVirtual(int field_number, + io::CodedInputStream* input, + MessageType* value) { + if (!input->IncrementRecursionDepth()) return false; + if (!value->MessageType::MergePartialFromCodedStream(input)) return false; + input->DecrementRecursionDepth(); + // Make sure the last thing read was an end tag for this group. + if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { + return false; + } + return true; +} +template +inline bool WireFormatLite::ReadMessageNoVirtual(io::CodedInputStream* input, + MessageType* value) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (!input->IncrementRecursionDepth()) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + if (!value->MessageType::MergePartialFromCodedStream(input)) return false; + // Make sure that parsing stopped when the limit was hit, not at an endgroup + // tag. + if (!input->ConsumedEntireMessage()) return false; + input->PopLimit(limit); + input->DecrementRecursionDepth(); + return true; +} + +// =================================================================== + +inline void WireFormatLite::WriteTag(int field_number, WireType type, + io::CodedOutputStream* output) { + output->WriteTag(MakeTag(field_number, type)); +} + +inline void WireFormatLite::WriteInt32NoTag(int32 value, + io::CodedOutputStream* output) { + output->WriteVarint32SignExtended(value); +} +inline void WireFormatLite::WriteInt64NoTag(int64 value, + io::CodedOutputStream* output) { + output->WriteVarint64(static_cast(value)); +} +inline void WireFormatLite::WriteUInt32NoTag(uint32 value, + io::CodedOutputStream* output) { + output->WriteVarint32(value); +} +inline void WireFormatLite::WriteUInt64NoTag(uint64 value, + io::CodedOutputStream* output) { + output->WriteVarint64(value); +} +inline void WireFormatLite::WriteSInt32NoTag(int32 value, + io::CodedOutputStream* output) { + output->WriteVarint32(ZigZagEncode32(value)); +} +inline void WireFormatLite::WriteSInt64NoTag(int64 value, + io::CodedOutputStream* output) { + output->WriteVarint64(ZigZagEncode64(value)); +} +inline void WireFormatLite::WriteFixed32NoTag(uint32 value, + io::CodedOutputStream* output) { + output->WriteLittleEndian32(value); +} +inline void WireFormatLite::WriteFixed64NoTag(uint64 value, + io::CodedOutputStream* output) { + output->WriteLittleEndian64(value); +} +inline void WireFormatLite::WriteSFixed32NoTag(int32 value, + io::CodedOutputStream* output) { + output->WriteLittleEndian32(static_cast(value)); +} +inline void WireFormatLite::WriteSFixed64NoTag(int64 value, + io::CodedOutputStream* output) { + output->WriteLittleEndian64(static_cast(value)); +} +inline void WireFormatLite::WriteFloatNoTag(float value, + io::CodedOutputStream* output) { + output->WriteLittleEndian32(EncodeFloat(value)); +} +inline void WireFormatLite::WriteDoubleNoTag(double value, + io::CodedOutputStream* output) { + output->WriteLittleEndian64(EncodeDouble(value)); +} +inline void WireFormatLite::WriteBoolNoTag(bool value, + io::CodedOutputStream* output) { + output->WriteVarint32(value ? 1 : 0); +} +inline void WireFormatLite::WriteEnumNoTag(int value, + io::CodedOutputStream* output) { + output->WriteVarint32SignExtended(value); +} + +inline void WireFormatLite::WriteInt32(int field_number, int32 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteInt32NoTag(value, output); +} +inline void WireFormatLite::WriteInt64(int field_number, int64 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteInt64NoTag(value, output); +} +inline void WireFormatLite::WriteUInt32(int field_number, uint32 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteUInt32NoTag(value, output); +} +inline void WireFormatLite::WriteUInt64(int field_number, uint64 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteUInt64NoTag(value, output); +} +inline void WireFormatLite::WriteSInt32(int field_number, int32 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteSInt32NoTag(value, output); +} +inline void WireFormatLite::WriteSInt64(int field_number, int64 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteSInt64NoTag(value, output); +} +inline void WireFormatLite::WriteFixed32(int field_number, uint32 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED32, output); + WriteFixed32NoTag(value, output); +} +inline void WireFormatLite::WriteFixed64(int field_number, uint64 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED64, output); + WriteFixed64NoTag(value, output); +} +inline void WireFormatLite::WriteSFixed32(int field_number, int32 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED32, output); + WriteSFixed32NoTag(value, output); +} +inline void WireFormatLite::WriteSFixed64(int field_number, int64 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED64, output); + WriteSFixed64NoTag(value, output); +} +inline void WireFormatLite::WriteFloat(int field_number, float value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED32, output); + WriteFloatNoTag(value, output); +} +inline void WireFormatLite::WriteDouble(int field_number, double value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED64, output); + WriteDoubleNoTag(value, output); +} +inline void WireFormatLite::WriteBool(int field_number, bool value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteBoolNoTag(value, output); +} +inline void WireFormatLite::WriteEnum(int field_number, int value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteEnumNoTag(value, output); +} + +inline void WireFormatLite::WriteString(int field_number, const string& value, + io::CodedOutputStream* output) { + // String is for UTF-8 text only + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + output->WriteVarint32(value.size()); + output->WriteString(value); +} +inline void WireFormatLite::WriteBytes(int field_number, const string& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + output->WriteVarint32(value.size()); + output->WriteString(value); +} + + +inline void WireFormatLite::WriteGroup(int field_number, + const MessageLite& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_START_GROUP, output); + value.SerializeWithCachedSizes(output); + WriteTag(field_number, WIRETYPE_END_GROUP, output); +} +inline void WireFormatLite::WriteMessage(int field_number, + const MessageLite& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + output->WriteVarint32(value.GetCachedSize()); + value.SerializeWithCachedSizes(output); +} + +template +inline void WireFormatLite::WriteGroupNoVirtual(int field_number, + const MessageType& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_START_GROUP, output); + value.MessageType::SerializeWithCachedSizes(output); + WriteTag(field_number, WIRETYPE_END_GROUP, output); +} +template +inline void WireFormatLite::WriteMessageNoVirtual(int field_number, + const MessageType& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + output->WriteVarint32(value.MessageType::GetCachedSize()); + value.MessageType::SerializeWithCachedSizes(output); +} + +// =================================================================== + +inline uint8* WireFormatLite::WriteTagToArray(int field_number, + WireType type, + uint8* target) { + return io::CodedOutputStream::WriteTagToArray(MakeTag(field_number, type), + target); +} + +inline uint8* WireFormatLite::WriteInt32NoTagToArray(int32 value, + uint8* target) { + return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target); +} +inline uint8* WireFormatLite::WriteInt64NoTagToArray(int64 value, + uint8* target) { + return io::CodedOutputStream::WriteVarint64ToArray( + static_cast(value), target); +} +inline uint8* WireFormatLite::WriteUInt32NoTagToArray(uint32 value, + uint8* target) { + return io::CodedOutputStream::WriteVarint32ToArray(value, target); +} +inline uint8* WireFormatLite::WriteUInt64NoTagToArray(uint64 value, + uint8* target) { + return io::CodedOutputStream::WriteVarint64ToArray(value, target); +} +inline uint8* WireFormatLite::WriteSInt32NoTagToArray(int32 value, + uint8* target) { + return io::CodedOutputStream::WriteVarint32ToArray(ZigZagEncode32(value), + target); +} +inline uint8* WireFormatLite::WriteSInt64NoTagToArray(int64 value, + uint8* target) { + return io::CodedOutputStream::WriteVarint64ToArray(ZigZagEncode64(value), + target); +} +inline uint8* WireFormatLite::WriteFixed32NoTagToArray(uint32 value, + uint8* target) { + return io::CodedOutputStream::WriteLittleEndian32ToArray(value, target); +} +inline uint8* WireFormatLite::WriteFixed64NoTagToArray(uint64 value, + uint8* target) { + return io::CodedOutputStream::WriteLittleEndian64ToArray(value, target); +} +inline uint8* WireFormatLite::WriteSFixed32NoTagToArray(int32 value, + uint8* target) { + return io::CodedOutputStream::WriteLittleEndian32ToArray( + static_cast(value), target); +} +inline uint8* WireFormatLite::WriteSFixed64NoTagToArray(int64 value, + uint8* target) { + return io::CodedOutputStream::WriteLittleEndian64ToArray( + static_cast(value), target); +} +inline uint8* WireFormatLite::WriteFloatNoTagToArray(float value, + uint8* target) { + return io::CodedOutputStream::WriteLittleEndian32ToArray(EncodeFloat(value), + target); +} +inline uint8* WireFormatLite::WriteDoubleNoTagToArray(double value, + uint8* target) { + return io::CodedOutputStream::WriteLittleEndian64ToArray(EncodeDouble(value), + target); +} +inline uint8* WireFormatLite::WriteBoolNoTagToArray(bool value, + uint8* target) { + return io::CodedOutputStream::WriteVarint32ToArray(value ? 1 : 0, target); +} +inline uint8* WireFormatLite::WriteEnumNoTagToArray(int value, + uint8* target) { + return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target); +} + +inline uint8* WireFormatLite::WriteInt32ToArray(int field_number, + int32 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteInt32NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteInt64ToArray(int field_number, + int64 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteInt64NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteUInt32ToArray(int field_number, + uint32 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteUInt32NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteUInt64ToArray(int field_number, + uint64 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteUInt64NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteSInt32ToArray(int field_number, + int32 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteSInt32NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteSInt64ToArray(int field_number, + int64 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteSInt64NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteFixed32ToArray(int field_number, + uint32 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); + return WriteFixed32NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteFixed64ToArray(int field_number, + uint64 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); + return WriteFixed64NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteSFixed32ToArray(int field_number, + int32 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); + return WriteSFixed32NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteSFixed64ToArray(int field_number, + int64 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); + return WriteSFixed64NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteFloatToArray(int field_number, + float value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); + return WriteFloatNoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteDoubleToArray(int field_number, + double value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); + return WriteDoubleNoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteBoolToArray(int field_number, + bool value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteBoolNoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteEnumToArray(int field_number, + int value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteEnumNoTagToArray(value, target); +} + +inline uint8* WireFormatLite::WriteStringToArray(int field_number, + const string& value, + uint8* target) { + // String is for UTF-8 text only + // WARNING: In wire_format.cc, both strings and bytes are handled by + // WriteString() to avoid code duplication. If the implementations become + // different, you will need to update that usage. + target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); + target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target); + return io::CodedOutputStream::WriteStringToArray(value, target); +} +inline uint8* WireFormatLite::WriteBytesToArray(int field_number, + const string& value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); + target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target); + return io::CodedOutputStream::WriteStringToArray(value, target); +} + + +inline uint8* WireFormatLite::WriteGroupToArray(int field_number, + const MessageLite& value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); + target = value.SerializeWithCachedSizesToArray(target); + return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); +} +inline uint8* WireFormatLite::WriteMessageToArray(int field_number, + const MessageLite& value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); + target = io::CodedOutputStream::WriteVarint32ToArray( + value.GetCachedSize(), target); + return value.SerializeWithCachedSizesToArray(target); +} + +template +inline uint8* WireFormatLite::WriteGroupNoVirtualToArray( + int field_number, const MessageType& value, uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); + target = value.MessageType::SerializeWithCachedSizesToArray(target); + return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); +} +template +inline uint8* WireFormatLite::WriteMessageNoVirtualToArray( + int field_number, const MessageType& value, uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); + target = io::CodedOutputStream::WriteVarint32ToArray( + value.MessageType::GetCachedSize(), target); + return value.MessageType::SerializeWithCachedSizesToArray(target); +} + +// =================================================================== + +inline int WireFormatLite::Int32Size(int32 value) { + return io::CodedOutputStream::VarintSize32SignExtended(value); +} +inline int WireFormatLite::Int64Size(int64 value) { + return io::CodedOutputStream::VarintSize64(static_cast(value)); +} +inline int WireFormatLite::UInt32Size(uint32 value) { + return io::CodedOutputStream::VarintSize32(value); +} +inline int WireFormatLite::UInt64Size(uint64 value) { + return io::CodedOutputStream::VarintSize64(value); +} +inline int WireFormatLite::SInt32Size(int32 value) { + return io::CodedOutputStream::VarintSize32(ZigZagEncode32(value)); +} +inline int WireFormatLite::SInt64Size(int64 value) { + return io::CodedOutputStream::VarintSize64(ZigZagEncode64(value)); +} +inline int WireFormatLite::EnumSize(int value) { + return io::CodedOutputStream::VarintSize32SignExtended(value); +} + +inline int WireFormatLite::StringSize(const string& value) { + return io::CodedOutputStream::VarintSize32(value.size()) + + value.size(); +} +inline int WireFormatLite::BytesSize(const string& value) { + return io::CodedOutputStream::VarintSize32(value.size()) + + value.size(); +} + + +inline int WireFormatLite::GroupSize(const MessageLite& value) { + return value.ByteSize(); +} +inline int WireFormatLite::MessageSize(const MessageLite& value) { + int size = value.ByteSize(); + return io::CodedOutputStream::VarintSize32(size) + size; +} + +template +inline int WireFormatLite::GroupSizeNoVirtual(const MessageType& value) { + return value.MessageType::ByteSize(); +} +template +inline int WireFormatLite::MessageSizeNoVirtual(const MessageType& value) { + int size = value.MessageType::ByteSize(); + return io::CodedOutputStream::VarintSize32(size) + size; +} + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__ diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc index 6352b0a6..51960ee7 100644 --- a/src/google/protobuf/wire_format_unittest.cc +++ b/src/google/protobuf/wire_format_unittest.cc @@ -33,7 +33,7 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include -#include +#include #include #include #include @@ -51,9 +51,27 @@ namespace protobuf { namespace internal { namespace { +TEST(WireFormatTest, EnumsInSync) { + // Verify that WireFormatLite::FieldType and WireFormatLite::CppType match + // FieldDescriptor::Type and FieldDescriptor::CppType. + + EXPECT_EQ(implicit_cast(FieldDescriptor::MAX_TYPE), + implicit_cast(WireFormatLite::MAX_FIELD_TYPE)); + EXPECT_EQ(implicit_cast(FieldDescriptor::MAX_CPPTYPE), + implicit_cast(WireFormatLite::MAX_CPPTYPE)); + + for (int i = 1; i <= WireFormatLite::MAX_FIELD_TYPE; i++) { + EXPECT_EQ( + implicit_cast(FieldDescriptor::TypeToCppType( + static_cast(i))), + implicit_cast(WireFormatLite::FieldTypeToCppType( + static_cast(i)))); + } +} + TEST(WireFormatTest, MaxFieldNumber) { // Make sure the max field number constant is accurate. - EXPECT_EQ((1 << (32 - WireFormat::kTagTypeBits)) - 1, + EXPECT_EQ((1 << (32 - WireFormatLite::kTagTypeBits)) - 1, FieldDescriptor::kMaxNumber); } @@ -326,9 +344,9 @@ TEST(WireFormatTest, SerializeMessageSet) { EXPECT_EQ("bar", raw.item(2).message()); } -TEST(WireFormatTest, SerializeMessageSetToStreamAndArrayAreEqual) { - // Serialize a MessageSet to a stream and to a flat array and check that the - // results are equal. +TEST(WireFormatTest, SerializeMessageSetVariousWaysAreEqual) { + // Serialize a MessageSet to a stream and to a flat array using generated + // code, and also using WireFormat, and check that the results are equal. // Set up a TestMessageSet with two known messages and an unknown one, as // above. @@ -341,10 +359,15 @@ TEST(WireFormatTest, SerializeMessageSetToStreamAndArrayAreEqual) { kUnknownTypeId, "bar"); int size = message_set.ByteSize(); + EXPECT_EQ(size, message_set.GetCachedSize()); + ASSERT_EQ(size, WireFormat::ByteSize(message_set)); + string flat_data; string stream_data; + string dynamic_data; flat_data.resize(size); stream_data.resize(size); + // Serialize to flat array { uint8* target = reinterpret_cast(string_as_array(&flat_data)); @@ -360,7 +383,16 @@ TEST(WireFormatTest, SerializeMessageSetToStreamAndArrayAreEqual) { ASSERT_FALSE(output_stream.HadError()); } + // Serialize to buffer with WireFormat. + { + io::StringOutputStream string_stream(&dynamic_data); + io::CodedOutputStream output_stream(&string_stream); + WireFormat::SerializeWithCachedSizes(message_set, size, &output_stream); + ASSERT_FALSE(output_stream.HadError()); + } + EXPECT_TRUE(flat_data == stream_data); + EXPECT_TRUE(flat_data == dynamic_data); } TEST(WireFormatTest, ParseMessageSet) { @@ -407,6 +439,13 @@ TEST(WireFormatTest, ParseMessageSet) { ASSERT_EQ(UnknownField::TYPE_LENGTH_DELIMITED, message_set.unknown_fields().field(0).type()); EXPECT_EQ("bar", message_set.unknown_fields().field(0).length_delimited()); + + // Also parse using WireFormat. + unittest::TestMessageSet dynamic_message_set; + io::CodedInputStream input(reinterpret_cast(data.data()), + data.size()); + ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &dynamic_message_set)); + EXPECT_EQ(message_set.DebugString(), dynamic_message_set.DebugString()); } TEST(WireFormatTest, RecursionLimit) { @@ -464,10 +503,10 @@ TEST(WireFormatTest, ZigZag) { // avoid line-wrapping #define LL(x) GOOGLE_LONGLONG(x) #define ULL(x) GOOGLE_ULONGLONG(x) -#define ZigZagEncode32(x) WireFormat::ZigZagEncode32(x) -#define ZigZagDecode32(x) WireFormat::ZigZagDecode32(x) -#define ZigZagEncode64(x) WireFormat::ZigZagEncode64(x) -#define ZigZagDecode64(x) WireFormat::ZigZagDecode64(x) +#define ZigZagEncode32(x) WireFormatLite::ZigZagEncode32(x) +#define ZigZagDecode32(x) WireFormatLite::ZigZagDecode32(x) +#define ZigZagEncode64(x) WireFormatLite::ZigZagEncode64(x) +#define ZigZagDecode64(x) WireFormatLite::ZigZagDecode64(x) EXPECT_EQ(0u, ZigZagEncode32( 0)); EXPECT_EQ(1u, ZigZagEncode32(-1)); @@ -545,7 +584,7 @@ class WireFormatInvalidInputTest : public testing::Test { io::StringOutputStream raw_output(&result); io::CodedOutputStream output(&raw_output); - WireFormat::WriteBytes(field->number(), string(bytes, size), &output); + WireFormatLite::WriteBytes(field->number(), string(bytes, size), &output); } return result; @@ -569,8 +608,8 @@ class WireFormatInvalidInputTest : public testing::Test { output.WriteVarint32(WireFormat::MakeTag(field)); output.WriteString(string(bytes, size)); if (include_end_tag) { - output.WriteVarint32(WireFormat::MakeTag( - field->number(), WireFormat::WIRETYPE_END_GROUP)); + output.WriteVarint32(WireFormatLite::MakeTag( + field->number(), WireFormatLite::WIRETYPE_END_GROUP)); } } -- cgit v1.2.3